通過前面幾篇博客,不知道大家有沒有發現這個問題,雖然現在可以靈活控制跳轉了,但是Action的數量 還是比較多,如何既能保證跳轉靈活,還能減少Action的數量?這就是我們這篇博客所說的DispatchAction, 如其名,可以理解為“分發式Action”,使用它可以避免為每個Action創建一個類。
我們先來看一下 實例。
UserAction
DispatchAction繼承的是Action,它的特點就是把以前的多個Action合並為 一個,當多個Action關聯較大時,可以像這樣放在一起,減少Action類的同時,也降低了維護的難度。
package com.tgb.drp.web.actions; import java.util.Date; import java.util.List; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.beanutils.BeanUtils; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; import org.apache.struts.actions.DispatchAction; import com.tgb.drp.manager.UserManager; import com.tgb.drp.model.User; import com.tgb.drp.web.forms.UserActionForm; public class UserAction extends DispatchAction { @Override protected ActionForward unspecified(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { //調用業務邏輯操作 List userList = UserManager.getInstance().findAllUserList(); request.setAttribute("userlist", userList); return mapping.findForward("list_success"); } /** * 用戶刪除 * @param mapping * @param form * @param request * @param response * @return * @throws Exception */ public ActionForward del(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { //獲取從頁面表單中提交過來的值 UserActionForm uaf = (UserActionForm)form; //取得需要刪除的userId的集合 String[] userIdList = uaf.getSelectFlag(); //調用業務邏輯操作 UserManager.getInstance().deleteUsers(userIdList); return mapping.findForward("del_success"); } /** * 用戶添加 * @param mapping * @param form * @param request * @param response * @return * @throws Exception */ public ActionForward add(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { //獲取從頁面表單中提交過來的值 UserActionForm uaf = (UserActionForm)form; User user = new User(); BeanUtils.copyProperties(user, uaf); user.setCreateDate(new Date()); //調用業務邏輯操作 UserManager.getInstance().addUser(user); return mapping.findForward("add_success"); } /** * 修改用戶 * @param mapping * @param form * @param request * @param response * @return * @throws Exception */ public ActionForward modify(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { //獲取從頁面表單中提交過來的值 UserActionForm uaf = (UserActionForm)form; User user = new User(); BeanUtils.copyProperties(user, uaf); //調用業務邏輯操作 UserManager.getInstance().modifyUser(user); return mapping.findForward("modify_success"); } /** * 根據ID查詢用戶 * * @param mapping * @param form * @param request * @param response * @return * @throws Exception */ public ActionForward find(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { //獲取從頁面表單中提交過來的值 UserActionForm uaf = (UserActionForm)form; String userId = uaf.getUserId(); //調用業務邏輯操作 User user = UserManager.getInstance().findUserById(userId); //將user對象從Action傳遞到JSP頁面 request.setAttribute("user", user); return mapping.findForward("find_success"); } }
UserActionForm
封裝表單中的數據,需要注意的是,不用為每個表單 建立一個ActionForm ,多個表單可以使用一個進行封裝。
package com.tgb.drp.web.forms; import java.util.Date; import org.apache.struts.action.ActionForm; /** * 用戶管理ActionForm * */ public class UserActionForm extends ActionForm { //用戶代碼 private String userId; //用戶名稱 private String userName; //密碼 private String password; //聯系電話 private String contactTel; //email private String email; //創建日期 private Date createDate; //接收界面中的選中標記的集合 private String[] selectFlag; public String getContactTel() { return contactTel; } public void setContactTel(String contactTel) { this.contactTel = contactTel; } public Date getCreateDate() { return createDate; } public void setCreateDate(Date createDate) { this.createDate = createDate; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getUserId() { return userId; } public void setUserId(String userId) { this.userId = userId; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String[] getSelectFlag() { return selectFlag; } public void setSelectFlag(String[] selectFlag) { this.selectFlag = selectFlag; } }
struts-config
配置Action和ActionForm,區別於以前的是需要添加parameter屬性。
<form-beans> <form-bean name="userForm" type="com.tgb.drp.web.forms.UserActionForm"/> </form-beans> <action-mappings> <action path="/user/user_maint" type="com.tgb.drp.web.actions.UserAction" name="userForm" scope="request" parameter="command" > <forward name="list_success" path="/user/user_list.jsp"/> <forward name="del_success" path="/user/user_maint.do" redirect="true"/> <forward name="add_success" path="/user/user_maint.do" redirect="true"/> <forward name="modify_success" path="/user/user_maint.do" redirect="true"/> <forward name="find_success" path="/user/user_modify.jsp"/> </action> <action path="/user/show_add" forward="/user/user_input.jsp" ></action> </action-mappings>
訪問接口
<body> <a href="user/user_maint.do" title="請點擊訪問用戶管理系統">用戶管理系統</a> </body>
如上所示,它是根據command屬性的值確定的。
執行流程
把斷點主要 設置在DispatchAction中,可以看到,執行流程如下:
代碼分析
在DispatchAction的execute函數中,有如下代碼:
// Prevent recursive calls if ("execute".equals(name) || "perform".equals(name)){ String message = messages.getMessage("dispatch.recursive", mapping.getPath()); log.error(message); throw new ServletException(message); }
所以在給parameter設置值時,不能為execute或perform。
在DispatchAction的 dispatchMethod中,有如下代碼:
if (name == null) { return this.unspecified(mapping, form, request, response); }
即如果parameter值為空,則執行unspecified函數,可以在子類中實現這個函數,作為無參數值的 跳轉。
總結
總而言之,DispatchAction的出現減少了Action的數量,將多個Action融合到一起 ,雖然有顯而易見的好處,但是同樣會有問題,這樣的耦合性的提高,必然伴隨著擴展性的降低,所以用還是 不用,還要根據具體情況而定。