首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 程式設計入門

Struts 源碼深度解析:Action input 屬性與驗證失敗導向機制

     編輯:Java 程式設計入門

問題場景重現

Struts 設定檔中 Action 定義:

<action path="/docreateuser" type="com.zchome.CreateUserAction"
        name="CreateUserForm" scope="request" input="createuser">
    <forward name="createuser" path="/jsp/createuser.jsp"/>
</action>

現象:Validator 驗證通過;但 ActionForm validate() 失敗時,拋出 IllegalArgumentException: Path createuser does not start with a "/" character。

源碼追蹤:RequestProcessor.processValidate()

// RequestProcessor.java (Struts 1.1)
protected boolean processValidate(HttpServletRequest request, HttpServletResponse response,
                                  ActionForm form, ActionMapping mapping) throws IOException, ServletException {
    if (form == null) return true;

    // 執行驗證
    ActionErrors errors = form.validate(mapping, request);
    if (errors != null && !errors.isEmpty()) {
        // 驗證失敗,導向 input 指定路徑
        request.setAttribute(Globals.ERROR_KEY, errors);
        // 關鍵行:
        return processForward(request, response, mapping.getInput());
    }
    return true;
}

processForward() 內部實作

protected boolean processForward(HttpServletRequest request, HttpServletResponse response,
                                 String forward) throws IOException, ServletException {
    if (forward == null) return false;
    // 內部呼叫 internalModuleRelativeForward()
    return internalModuleRelativeForward(request, response, forward);
}

protected boolean internalModuleRelativeForward(HttpServletRequest request,
                                                HttpServletResponse response, String path)
        throws IOException, ServletException {
    // 關鍵檢查:路徑必須以 "/" 開頭
    if (!path.startsWith("/")) {
        throw new IllegalArgumentException("Path " + path + " does not start with a '/' character");
    }
    // ... 取得 RequestDispatcher 並 forward
}

根因分析

mapping.getInput() 返回的是 struts-config.xml 中 input="createuser" 的原始值。internalModuleRelativeForward() 要求路徑必須以 / 開頭,但設定值未加斜線,導致異常。

解決方案

在 struts-config.xml 中修正 input 屬性:

<action path="/docreateuser" type="com.zchome.CreateUserAction"
        name="CreateUserForm" scope="request" input="/jsp/createuser.jsp">
    <forward name="createuser" path="/jsp/createuser.jsp"/>
</action>

或直接使用 forward 名稱(需 Struts 1.1+ 支援):

<action ... input="createuser" />  <!-- 僅當 input 對應 forward name 時有效,否則需完整路徑 -->

最佳實踐建議

  • 永遠使用以 / 開頭的絕對路徑 作為 input、forward 的 path 值
  • 統一路徑前綴:/jsp/、/tiles/ 等,便於維護
  • 驗證失敗導向頁面應保留原表單資料(request 作用域),避免用戶重新輸入
  • 全域例外處理:在 <global-exceptions> 設定未捕獲異常導向

相關源碼位置參考

類別方法職責
RequestProcessorprocessValidate()執行表單驗證,失敗時導向 input
RequestProcessorprocessForward()處理前導轉向
RequestProcessorinternalModuleRelativeForward()模組相對路徑轉向,檢查 "/" 前綴
TilesRequestProcessordoForward()Tiles 整合下的轉向實作

總結

input 屬性值必須為以 / 開頭的模組相對路徑,否則驗證失敗時會拋出 IllegalArgumentException。此為 Struts 1.1 核心轉向機制的強制要求,開發者需養成絕對路徑習慣。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved