傳統 Action 一個業務操作一個類(UserAddAction、UserDelAction、UserModifyAction...),導致類數量膨脹、維護困難。DispatchAction 允許將相關操作合併到一個類,根據請求參數分發到不同方法。
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");
}
public ActionForward del(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) throws Exception {
UserActionForm uaf = (UserActionForm) form;
String[] userIdList = uaf.getSelectFlag();
UserManager.getInstance().deleteUsers(userIdList);
return mapping.findForward("del_success");
}
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");
}
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");
}
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);
request.setAttribute("user", user);
return mapping.findForward("find_success");
}
}
public class UserActionForm extends ActionForm {
private String userId, userName, password, contactTel, email;
private Date createDate;
private String[] selectFlag; // 批量刪除勾選框
// getter/setter 省略
}
<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-mappings>
<a href="user/user_maint.do?command=add">新增用戶</a> <a href="user/user_maint.do?command=del">刪除用戶</a> <form action="user/user_maint.do" method="post"> <input type="hidden" name="command" value="modify"/> ... </form>
根據 command 參數值(add/del/modify/find)自動調用同名方法。

execute → dispatchMethod
// DispatchAction.execute()
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) throws Exception {
String parameter = mapping.getParameter(); // 獲取 "command"
if (parameter == null) {
return unspecified(mapping, form, request, response);
}
// 防止遞歸調用 execute/perform
if ("execute".equals(parameter) || "perform".equals(parameter)) {
throw new ServletException("DispatchAction parameter cannot be 'execute' or 'perform'");
}
return dispatchMethod(mapping, form, request, response, parameter);
}
// DispatchAction.dispatchMethod()
protected ActionForward dispatchMethod(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response,
String parameter) throws Exception {
String name = request.getParameter(parameter); // 獲取 command 值
if (name == null) {
return unspecified(mapping, form, request, response);
}
// 反射調用同名方法
Method method = getMethod(name);
return (ActionForward) method.invoke(this, mapping, form, request, response);
}
parameter 屬性不能為 "execute" 或 "perform",否則拋異常防遞歸。unspecified()(可覆寫作為默認入口)。execute 完全一致:(ActionMapping, ActionForm, HttpServletRequest, HttpServletResponse)。public,返回 ActionForward,拋出 Exception。| 優點 | 缺點 |
|---|---|
| 大幅減少 Action 類數量 | 單類職責過重,違反單一職責原則 |
| 相關邏輯聚合,便於協調 | 耦合度升高,修改一個方法可能影響其他 |
| 配置簡潔,減少 struts-config 體積 | 擴展性降低,新增操作需修改同一類 |
| 共享 ActionForm,減少表單類 | 團隊並行開發衝突概率增加 |
getKeyMethodMap() 返回鍵值對映射,支持國際化(按鍵值而非方法名分發)。ActionMapping 的 parameter 屬性值直接分發,無需請求參數。DispatchAction 是 Struts 1 時代解決「Action 類爆炸」的經典模式,通過 parameter 指定分發參數、反射調用同名方法,實現單類多入口。理解其源碼流程(execute → dispatchMethod → 反射調用)與配置約束,有助於在維護老項目時快速定位問題。但隨著項目規模增長,其耦合副作用會顯現,適時重構為細粒度 Action 或遷移現代框架才是長久之計。