HTTP Status 500 - cn.it.shop.action.CategoryAction.1()
java.lang.NoSuchMethodException: cn.it.shop.action.CategoryAction.1()
at org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor.getActionMethod(...)
核心錯誤:Struts2 嘗試調用 CategoryAction.1() 方法,但該類中根本不存在名為 1 的方法。
/update.action 或 /save.actionActionMapper 解析出 actionName=update、method=updateActionProxy 創建 CategoryAction 實例DefaultActionInvocation 通過反射調用 update() 方法查看提供的 struts.xml 片段:
<action name="*" class="cn.it.shop.action.CategoryAction">
<result name="index">/index.jsp</result>
</action>
關鍵問題:name="*" 通配符匹配任意 action 名稱,但**缺少 method 屬性指定**或**動態方法調用配置**。
<!-- struts.xml -->
<package name="default" namespace="/" extends="struts-default">
<!-- 開啟動態方法調用 -->
<constant name="struts.enable.DynamicMethodInvocation" value="true" />
<action name="category/*" class="cn.it.shop.action.CategoryAction">
<result name="index">/index.jsp</result>
</action>
</package>
URL 格式:/category/update.action → 自動調用 update();/category/save.action → 調用 save()。
<action name="update" class="cn.it.shop.action.CategoryAction" method="update">
<result name="index">/index.jsp</result>
</action>
<action name="save" class="cn.it.shop.action.CategoryAction" method="save">
<result name="index">/index.jsp</result>
</action>
<action name="category/*" class="cn.it.shop.action.CategoryAction" method="{1}">
<result name="index">/index.jsp</result>
</action>
機制:category/update → {1} 替換為 update → 調用 update()。
<%-- 方案一/三對應 --%>
<a href="<s:url action='category/update'/>">訪問 update</a>
<a href="<s:url action='category/save'/>">訪問 save</a>
<%-- 方案二對應 --%>
<a href="<s:url action='update'/>">訪問 update</a>
<a href="<s:url action='save'/>">訪問 save</a>
.1()?AnnotationValidationInterceptor 在驗證階段嘗試獲取 action 方法名進行註解驗證。當動態方法解析失敗時,Struts2 內部可能將方法名解析為索引 1(第一個匹配的方法),導致反射查找 getMethod("1") 失敗。
| 場景 | 推薦配置 | 優點 |
|---|---|---|
| 少量固定方法 | 顯式配置 method 屬性 | 清晰、無魔法、易除錯 |
| CRUD 標準化 | 通配符 {1} 映射 | 約定優於配置、擴展性強 |
| REST 風格 | REST 插件或約定插件 | 標準化、語義清晰 |