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 模板檔名,檔案編碼,頁面標題,布局。如果葉分發器屬于某個分發器組,則也會使用分發器組的布局。頁面標題標簽通常定義在布局檔案中。