1.0          其他语言
 
 

3.3 分发器 dispatcher

 
 

有两种分发器:叶分发器(LeafDispatcher)和分发器组(DispatcherGroup)。他们都是 org.velocityweb.dispatcher.Dispatcher 的子类。分发器组可以包含叶分发器。分发器组可以包含分发器组。叶分发器和分发器组之间的关系,就像文件和目录之间的关系。

每种分发器有一个 URL ID。本框架会使用这些 IDs 来生成 URL ID 树。当新的 URL 请求被控制器接收到,比如,

http://<somedomain>:<port>/<ControllerServletPath>?m1=cart&m2=add_item_to_cart&item_id=EST-11

控制器会在根控制器中查找 "cart" ,然后找到 CartDispatcherGroup。找到后,继续在 CartDispatcherGroup 中查找"add_item_to_cart",结果找到 AddItemToCartDispatcher。由于 AddItemToCartDispatcher 是一个叶分发器,AddItemToCartDispatcher 会从 request 中读取数据,调用后台的 service/DAO 函数,然后,往 WebAppContext 或者 session 中保存结果数据。VelocityWeb 会合并 WebAppContext 中的数据到用户指定的 HTML 模板中。然后用户就可以看到动态的 HTML 网页了。

网页布局可以定义在叶分发器和分发器组上。当分发器组有布局,所有这个组里面的东西,都会使用这个布局。比如,如果根分发器包含一个带有布局 l1 的分发器组 g1,g1 包含一个带有布局 l2 的分发器组 p2, p2 包含一个带有布局 l3 的叶分发器 d1。则 d1 的页面数据显示在 l3 里,外面是 l2,再外面是 l1。

在大多数 J2EE 项目中,布局会像示例程序 VPetstore 一样简单。那就是只有一层分发器组。可以直接在分发器组上定义布局。比如:

public class CartDispatcherGroup extends DispatcherGroup {
        static {
                DispatcherTreeManager.addParentChildrenRelationship(
                        CartDispatcherGroup.class, AddItemToCartDispatcher.class);                 DispatcherTreeManager.addParentChildrenRelationship(
                        CartDispatcherGroup.class, ViewCartDispatcher.class);
                DispatcherTreeManager.addParentChildrenRelationship(
                        CartDispatcherGroup.class, UpdateCartDispatcher.class);
                DispatcherTreeManager.addParentChildrenRelationship(
                        CartDispatcherGroup.class, RemoveItemFromCartDispatcher.class);
        }

        public CartDispatcherGroup() {
                this.setPageLayout(new VPetStorePageLayout());
        }

        public String getUrlId() {
                return "cart";
        }
}


public class AddItemToCartDispatcher extends QueryDispatcher {
        public boolean process(HttpServletRequest request, WebAppContext webContext, Controller controller)
                        throws Exception {

                ...

                return forward(ViewCartDispatcher.class, request, webContext, controller);
        }

        public String getUrlId() {
                return "add_item_to_cart";
        }
}

在 VelocityWeb 框架里,叶分发器用来读取请求的数据,调用 service/DAO,然后将数据放入 WebContext 对象中。如果没有错误,没有异常,则在 process() 里返回 true。

public class UpdateUserInfoDispatcher extends QueryDispatcher {
        public boolean process(HttpServletRequest request, WebAppContext context, Controller controller)
                        throws Exception{

                this.setHtmlTemplateFileName("user/update_user_info.htm");
                this.setPageTitle("Update user info");
                context.put("result_win_url",
                        DispatcherTreeManager.getUrl(ShowProcessResultDispatcher.class));
                context.put("target_process_url",
                        DispatcherTreeManager.getUrl(UpdateUserInfoProcessDispatcher.class));
                
                 // get user from session
                Account user = (Account) controller.getSessionUser(request);
                //reload user data, some others may change it
                UserService srv = new UserService(context);
                user = srv.getUserById(user.getUserid());

                context.put("user_id", user.getUserid());

                 //show account information
                context.put("first_name", user.getFirstname());
                context.put("last_name", user.getLastname());
                context.put("email", user.getEmail());
                context.put("phone", user.getPhone());
                context.put("address1", user.getAddr1());
                context.put("address2", user.getAddr2());
                context.put("city", user.getCity());
                context.put("state", user.getState());
                context.put("zip", user.getZip());
                context.put("country", user.getCountry());

                //show user profile
                Profile profile = srv.getProfileById(user.getUserid());
                context.put("langpref", profile.getLangpref());
                context.put("favcategory", profile.getFavcategory());
                context.put("mylistopt", profile.getMylistopt());
                context.put("banneropt", profile.getBanneropt());

                return true;
        }

        public String getUrlId() {
                return "update_user";
        }
}

每个叶分发器有自己的事务级别、HTML 模板文件名,文件编码,页面标题,布局。如果叶分发器属于某个分发器组,则也会使用分发器组的布局。页面标题标签通常定义在布局文件中。