開發中常遇到:驗證失敗時 Struts 拋出 IllegalArgumentException: Path createuser does not start with a "/" character。本文通過源碼追蹤,揭示 input 屬性的兩種工作模式及 inputForward 參數的關鍵作用。
錯誤配置片段:
<action path="/docreateuser" type="com.zchome.CreateUserAction"
name="CreateUserForm" scope="request" input="createuser">
<forward name="createuser" path="/jsp/createuser.jsp"/>
</action>
異常堆疊指向 RequestProcessor.internalModuleRelativeForward() → doForward() → ServletContext.getRequestDispatcher(uri)。Servlet API 明確要求:getRequestDispatcher(path) 的路徑必須以 "/" 開頭。
在 RequestProcessor.processValidate() 中:
String input = mapping.getInput(); // 獲取 "createuser"
if (moduleConfig.getControllerConfig().getInputForward()) {
// 分支 A:將 input 視為 forward 名稱
ForwardConfig forward = mapping.findForward(input);
processForwardConfig(request, response, forward);
} else {
// 分支 B(默認):將 input 視為模塊相對路徑
internalModuleRelativeForward(input, request, response);
}
源碼註釋說明:
「inputForward 屬性決定 ActionConfig 的 input 屬性是作為 ForwardConfig 名稱(true),還是作為模塊相對路徑(false,兼容舊版本行為)。默認值為 false。」
未顯式配置時默認走分支 B,導致 uri = moduleConfig.getPrefix() + "createuser" 缺少前導 "/",觸發異常。
<action path="/docreateuser" ... input="/jsp/createuser.jsp">
<forward name="createusersuccess" path="/jsp/Welcome.jsp"/>
</action>
<controller>
<set-property property="inputForward" value="true"/>
<set-property property="processorClass" value="org.apache.struts.tiles.TilesRequestProcessor"/>
</controller>
<action path="/docreateuser" ... input="createuser">
<forward name="createuser" path="/jsp/createuser.jsp"/>
<forward name="createusersuccess" path="/jsp/Welcome.jsp"/>
</action>
源碼中的轉發模式值得借鑒:
RequestDispatcher rd = getServletContext().getRequestDispatcher(uri);
if (rd == null) { /* 錯誤處理 */ }
rd.forward(request, response);
以後頁面跳轉只需給定相對 URI(以 / 開頭),無需拼接項目上下文路徑。