通過前面幾篇博客,不知道大家有沒有發現這個問題,雖然現在可以靈活控制跳轉了,但是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融合到一起 ,雖然有顯而易見的好處,但是同樣會有問題,這樣的耦合性的提高,必然伴隨著擴展性的降低,所以用還是 不用,還要根據具體情況而定。