
核心兩類:ActionServlet(前端控制器)與 RequestProcessor(請求處理模板)。
process(HttpServletRequest, HttpServletResponse)
protected void process(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
ModuleUtils.getInstance().selectModule(request, getServletContext());
ModuleConfig config = getModuleConfig(request);
RequestProcessor processor = getProcessorForModule(config);
if (processor == null) {
processor = getRequestProcessor(config);
}
processor.process(request, response); // 委託給 RequestProcessor
}
RequestProcessor 實例。process(HttpServletRequest, HttpServletResponse) 主流程
public void process(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
// 1. 多部分請求包裝
request = processMultipart(request);
// 2. 路徑識別與映射
String path = processPath(request, response);
if (path == null) return;
// 3. Locale、Content-Type、No-Cache 設置
processLocale(request, response);
processContent(request, response);
processNoCache(request, response);
// 4. 預處理鉤子
if (!processPreprocess(request, response)) return;
// 5. 清理舊消息
processCachedMessages(request, response);
// 6. ActionMapping 查找
ActionMapping mapping = processMapping(request, response, path);
if (mapping == null) return;
// 7. 角色權限檢查
if (!processRoles(request, response, mapping)) return;
// 8. ActionForm 創建、填充、驗證
ActionForm form = processActionForm(request, response, mapping);
processPopulate(request, response, form, mapping);
try {
if (!processValidate(request, response, form, mapping)) return;
} catch (InvalidCancelException e) {
ActionForward forward = processException(request, response, e, form, mapping);
processForwardConfig(request, response, forward);
return;
}
// 9. Forward/Include 配置檢查
if (!processForward(request, response, mapping)) return;
if (!processInclude(request, response, mapping)) return;
// 10. Action 創建與執行
Action action = processActionCreate(request, response, mapping);
if (action == null) return;
ActionForward forward = processActionPerform(request, response, action, form, mapping);
// 11. 結果轉發
processForwardConfig(request, response, forward);
}
processMultipart:文件上傳檢測
protected HttpServletRequest processMultipart(HttpServletRequest request) {
if (!"POST".equalsIgnoreCase(request.getMethod())) return request;
String contentType = request.getContentType();
if (contentType != null && contentType.startsWith("multipart/form-data")) {
return new MultipartRequestWrapper(request); // 包裝解析文件流
}
return request;
}
processPath:路徑提取與標準化pathInfo。servletPath,去除模塊前綴(/module)和擴展名(.do)。https://localhost:8080/struts_login/login.do → /login。processMapping:ActionMapping 解析path 查找 ActionConfig。Globals.MAPPING_KEY。unknown="true" 的備用映射。processActionForm 與 processPopulate:表單生命週期RequestUtils.createActionForm() 實例化。request 或 session(按 mapping.getScope())。processPopulate() 調用 BeanUtils.populate() 綁定請求參數,先調用 reset() 重置默認值。processValidate:驗證攔截mapping.getValidate() == true 且 Form 實現 validate(),則執行驗證。ActionErrors 到請求 → 自動轉發到 mapping.getInput() 頁面。InvalidCancelException(用戶點擊取消)→ 走異常處理分支。processForward / processInclude:配置級導航<action> 的 forward/include 屬性。forward(RequestDispatcher.forward()),次之 include(include())。processActionCreate:Action 實例化(單例模式)
Action instance = null;
synchronized (actions) {
instance = (Action) actions.get(className);
if (instance != null) return instance;
instance = (Action) RequestUtils.applicationInstance(className); // 反射創建
instance.setServlet(this.servlet);
actions.put(className, instance);
}
return instance;
processActionPerform:執行業務邏輯
try {
return action.execute(mapping, form, request, response);
} catch (Exception e) {
return processException(request, response, e, form, mapping);
}
execute()。processException 記錄日志、構造錯誤轉發。processForwardConfig:最終轉發ActionForward.getPath()。/ 開頭 → 模塊相對路徑,經 RequestUtils.forwardURL() 解析。RequestDispatcher → forward()。processXxx 方法,定制流程(如集成 Spring、添加權限檢查、修改驗證邏輯)。RequestProcessor.process() 是 Struts 1 的「心臟」,以模板方法模式定義了請求處理的標準化流程。每個 processXxx 都是可覆寫的擴展點,框架使用者通過配置(struts-config.xml)和繼承(自定義 Processor/Action/Form)即可實現絕大多數 Web 應用需求,而無需修改框架核心代碼。深度理解這條鏈路,是排查疑難雜症、進行框架級優化、平滑遷移現代框架的關鍵基石。