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

WebWork 2 源碼深度解析 (二):ModelDrivenInterceptor 與 ActionInvocation 調度機制

     編輯:Java 相關知識

前言

WebWork 2 透過攔截器實現兩種資料綁定模式:**Property-Driven** (傳統 Setter 注入) 與 **Model-Driven** (領域模型直接綁定)。本文分析 ModelDrivenInterceptor 及核心調度器 DefaultActionInvocation。

一、ModelDrivenInterceptor — 模型驅動綁定

設計目的

  • Property-Driven:Action 自身擁有屬性 (或 FormBean),攔截器逐個設值。
  • Model-Driven:Action 實作 ModelDriven 介面,回傳領域模型物件,攔截器將模型壓入 OgnlValueStack,OGNL 直接操作模型屬性。

核心程式碼

public class ModelDrivenInterceptor extends AroundInterceptor {
    protected void before(ActionInvocation invocation) throws Exception {
        Action action = invocation.getAction();
        if (action instanceof ModelDriven) {
            ModelDriven modelDriven = (ModelDriven) action;
            OgnlValueStack stack = invocation.getStack();
            stack.push(modelDriven.getModel()); // 關鍵:模型壓入值棧頂端
        }
    }
    protected void after(ActionInvocation dispatcher, String result) {}
}

關鍵點

  • OgnlValueStack 是 WebWork 的核心資料結構,支援巢狀屬性存取 (user.address.city)、類型轉換、集合操作。
  • 模型壓入棧頂 → JSP/Velocity 模板直接用 <ww:property value="name"/> 存取模型屬性,無需 model.name 前綴。
  • Action 需實作 ModelDriven:public Object getModel() { return userModel; }。

二、DefaultActionInvocation — 調度器核心

初始化流程 (init())

  1. 建立 ActionContext (Map 包裝 request/session/application/parameters)。
  2. createAction():透過 ObjectFactory 實例化 Action。
  3. 若 pushAction 為真,將 Action 壓入值棧。
  4. 從 ActionProxy.getConfig().getInterceptors() 取得攔截器清單,轉為 Iterator。

執行流程 (invoke())

public String invoke() throws Exception {
    if (executed) throw new IllegalStateException("Action has already executed");

    if (interceptors.hasNext()) {
        Interceptor interceptor = (Interceptor) interceptors.next();
        resultCode = interceptor.intercept(this); // 責任鏈模式
    } else {
        resultCode = invokeAction(action, proxy.getConfig()); // 執行 Action 邏輯
    }

    if (!executed) {
        // PreResultListener 回調 (如檔案上傳清理)
        if (preResultListeners != null) { ... }

        // 執行 Result (視圖渲染、重導向等)
        if (proxy.getExecuteResult()) {
            executeResult();
        }
        executed = true;
    }
    return resultCode;
}

Action Chain (動作鏈) 處理

  • ActionChainResult 表示結果為另一個 Action。
  • getResult() 遞迴解析鏈路,直到非 Chain Result。
public Result getResult() throws Exception {
    Result r = result;
    while (r instanceof ActionChainResult) {
        ActionProxy proxy = ((ActionChainResult) r).getProxy();
        if (proxy != null && proxy.getExecuteResult()) {
            r = proxy.getInvocation().getResult();
        } else break;
    }
    return r;
}

三、攔截器架構回顧

  • 所有攔截器實作 Interceptor 介面。
  • AroundInterceptor 抽象類定義責任鏈模板:before() → invocation.invoke() → after()。
  • 核心攔截器:ParametersInterceptor (屬性綁定)、ModelDrivenInterceptor (模型綁定)、ValidationInterceptor (驗證)、ServletConfigInterceptor (Servlet API 注入) 等。

四、OGNL ValueStack 關鍵特性

  • 多層級 Map 疊加:[Action, Model, Request, Session, Application]。
  • setValue("user.name", "John") 自動建立巢狀物件、類型轉換 (String→Integer 等)。
  • 支援投影、選擇、Lambda 運算:users.{name}, users.{? age > 18}。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved