Struts2 預設每個 Action 只處理 execute() 方法對應的單一請求。實際開發中,同一業務實體常需多種操作 (增刪改查),Dynamic Method Invocation (DMI) 允許在同一 Action 類中定義多個方法,透過 URL 指定調用哪個方法。
在 struts.xml 中設定常數啟用:
<constant name="struts.enable.DynamicMethodInvocation" value="true"/>
注意:Struts 2.3+ 預設關閉 DMI (安全性考量),必須顯式開啟。
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@taglib prefix="s" uri="/struts-tags"%>
<html>
<head><title>登入</title></head>
<body>
<h4>請輸入帳號密碼</h4>
<s:form action="DMIAction!login">
<s:textfield name="username" label="使用者名稱" />
<s:password name="password" label="密碼" />
<s:submit value="登入" />
</s:form>
</body>
</html>
<s:form action="DMIAction!register">
<s:textfield name="username" label="使用者名稱" />
<s:password name="password" label="密碼" />
<s:submit value="註冊" />
</s:form>
關鍵語法:action="ActionName!methodName",驚嘆號分隔 Action 名稱與方法名。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"https://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<constant name="struts.enable.DynamicMethodInvocation" value="true"/>
<package name="default" extends="struts-default">
<action name="DMIAction" class="struts2.action.DMIAction">
<result name="success">RegisterSuccess.jsp</result>
</action>
</package>
</struts>
package struts2.action;
import com.opensymphony.xwork2.ActionSupport;
import java.util.Map;
public class DMIAction extends ActionSupport {
private static final long serialVersionUID = 1L;
// 登入業務邏輯
public String login() {
// 驗證帳密邏輯...
return SUCCESS;
}
// 註冊業務邏輯
public String register() {
// 註冊存檔邏輯...
return SUCCESS;
}
// 表單屬性驅動
private String username;
private String password;
// getter/setter 省略...
// Session/Application 注入 (可選)
private Map sessionMap;
private Map applicationMap;
public void setSession(Map sessionMap) { this.sessionMap = sessionMap; }
public void setApplication(Map applicationMap) { this.applicationMap = applicationMap; }
}
String (對應 result 名稱)ExceptionStruts 2.3+ 推薦使用通配符而非 DMI:
<action name="DMIAction_*" class="struts2.action.DMIAction" method="{1}">
<result name="success">{1}Success.jsp</result>
<result name="login">login.jsp</result>
<result name="register">register.jsp</result>
</action>
URL 格式:/DMIAction_login.action、/DMIAction_register.action
<constant name="struts.mapper.alwaysSelectFullNamespace" value="false"/>
<constant name="struts.enable.SlashesInActionNames" value="true"/>
<package name="default" extends="struts-default,rest-default">
<action name="users/*" class="struts2.action.UserAction">
<result name="success" type="redirectAction">users</result>
</action>
</package>
false,防止惡意調用內部方法struts.allowedMethods 限制可調用方法DMI 讓單一 Action 處理多個相關業務邏輯,減少 Action 類數量。核心步驟:
struts.enable.DynamicMethodInvocation = trueaction="ActionName!methodName"public String methodName()現代 Struts 開發建議改用通配符映射或 REST 風格,兼顧安全與維護性。