richlet 为一个小型的Java程序,可以创建所有必须的组件以响应用户的请求。
当用户请求一个URL内容时,ZK加载器(loader)会检查指定的URL资源是一个ZUML页面,还是一个richlet。若为ZUML页面, ZK加载器会基于ZUML页面的内容自动创建组件,就像在前面章节描述的那样。
若资源为一个richlet, ZK加载器会将处理交给richlet。创建什么组件与如何创建组件都由richlet 处理。换言之,编程创建所有需要的组件以响应用户请求是开发人员的工作。
选择ZUML页面还是richlet取决于你的偏好。对于大多数开发人员,ZUML页面更具有可读性和简洁性。
实现一个richlet是很直接的。首先,实现org.zkoss.zk.ui.Richlet接口,然后声明richlet 的注释及一个URL(association of the richlet with an URL)。
所有的richlet都必须实现org.zkoss.zk.ui.Richlet接口。为将实现所有方法的影响降至最低,可以继承org.zkoss.zk.ui.GenericRichlet类代替。然后,当请求指定的URL时,service方法会被调用,然后你可创建用户界面。
package org.zkoss.zkdemo;import org.zkoss.zk.ui.Page;import org.zkoss.zk.ui.GenericRichlet;
import org.zkoss.zk.ui.event.*;
import org.zkoss.zul.*;
public class TestRichlet extends GenericRichlet
{//Richlet//
public void service(Page page) {
page.setTitle("Richlet Test");
final Window w = new Window("Richlet Test", "normal", false);
new Label("Hello World!").setParent(w);
final Label l = new Label();
l.setParent(w);
final Button b = new Button("Change");
b.addEventListener(Events.ON_CLICK,
new EventListener() {
int count;
public void onEvent(Event evt) {
l.setValue("" + ++count);
}
});
b.setParent(w);
w.setPage(page);
}
}
就像servlet,你可以实现init和destroy方法以在加载时初始化和销毁richlet。就像servlet,richlet被加载一次,且为关联URL的所有请求服务(serves all requests for the URL it is associated with)。
就像servlet,一个richlet被创建且为相同的URL所共享。换言之,richlet(至少为service方法)必须为线程安全的。另外,组件是不共享的。每个桌面都一套独立的组件。因此,将组件作为一个richlet 的数据成员来存储通常并不是一个好主意。
有许多方式来来解决这个问题。一个典型的方法是使用另一个类来处理每个桌面的组件,如下所述。
class MyApp { //one per desktop
Window _main;
MyApp(Page page) {
_main = new Window();
_main.setPage(page);
}
}
class MyRichlet extends GenericRichlet {
public void service(Page page) {
new MyApp(page); //create and forget
}
}
在实现richlet 之后,你可以在zk.xml中使用下列语句定义richlet。
<richlet> <richlet-name>Test</richlet-name> <richlet-class>org.zkoss.zkdemo.TestRichlet</richlet-class> </richlet>
一旦声明了一个richlet,你可以使用richlet-mapping将其映射到任意数量的URL,如下所示。
<richlet-mapping> <richlet-name>Test</richlet-name> <url-pattern>/test</url-pattern> </richlet-mapping> <richlet-mapping> <richlet-name>Test</richlet-name> <url-pattern>/some/more/*</url-pattern> </richlet-mapping>
默认情况下,richlet是不可用的。为启用richlet,你必须在web.xml中添加下列声明。一旦启用了richlet,你可以添加任意多的richlet而无需再修改web.xml。
<servlet-mapping> <servlet-name>zkLoader</servlet-name> <url-pattern>/zk/*</url-pattern> </servlet-mapping>
然后,你可以访问http://localhost/zk/test 来请求richlet。
在url-pattern元素内指定的URL必须以/开始。若URL以/*开始,那么它会匹配所有相同前缀的请求。为获取真实的请求,你可以检查由当前页面的getRequestPath方法返回的值。
public void service(Page page) {
if ("/some/more/hi".equals(page.getRequestPath()) {
...
}
}
[提示]: 通过为url-pattern指定/*,你可以将所有不匹配的URL映射到被映射的 richlet (you can map all unmatched URL to the mapped richlet)。