異常堆疊分析
java.lang.NoSuchMethodException: com.action.LoginAction.Login()
at java.lang.Class.getMethod(Class.java:1605)
at org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor.getActionMethod(...)
核心原因
Struts2 的 `AnnotationValidationInterceptor` 嘗試透過反射取得 `LoginAction` 類別的 `Login()` 方法以執行驗證邏輯,但找不到符合簽名的方法。
常見觸發情境
- 方法簽名不符:`public String Login()` vs `public void Login()` 或帶參數 `public String Login(HttpServletRequest req)`
- 方法非 public:`protected String Login()` 或預設包裝可見性
- 類別未被正確掃描/代理:Spring AOP 代理導致方法在代理類中不可見
- 拼寫錯誤:`login()` vs `Login()`(Java 區分大小寫)
標準 Action 方法簽名
public class LoginAction extends ActionSupport {
// 標準:public、無參、回傳 String
public String Login() {
// 業務邏輯
return SUCCESS;
}
}
排查步驟
- 確認 `LoginAction.java` 中方法確切為 `public String Login()`
- 檢查 `struts.xml` 中 action 設定:``
- 若使用 Spring 管理 Action,確認 `` 且無 AOP 代理干擾
- 暫時註解驗證攔截器測試:在 `struts.xml` 移除 `validation` 攔截器或設定 `validate="false"`
- 啟用 Debug 模式觀察實際調用的方法:`-Dstruts.devMode=true`
快速修正方案
若確定方法存在但仍報錯,嘗試在 Action 中新增無參 `execute()` 方法並修改 `struts.xml` 使用預設 `method="execute"`,繞過方法名反射查找。
最佳實踐
- Action 方法統一命名為 `execute()`,避免指定 method 造成反射查找失敗
- 使用註解驗證(`@Validations`)替代 XML,減少配置錯誤
- 單元測試直接實例化 Action 呼叫方法,隔離 Struts2 容器問題