WebWork 2 透過攔截器實現兩種資料綁定模式:**Property-Driven** (傳統 Setter 注入) 與 **Model-Driven** (領域模型直接綁定)。本文分析 ModelDrivenInterceptor 及核心調度器 DefaultActionInvocation。
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)、類型轉換、集合操作。<ww:property value="name"/> 存取模型屬性,無需 model.name 前綴。ModelDriven:public Object getModel() { return userModel; }。ActionContext (Map 包裝 request/session/application/parameters)。createAction():透過 ObjectFactory 實例化 Action。pushAction 為真,將 Action 壓入值棧。ActionProxy.getConfig().getInterceptors() 取得攔截器清單,轉為 Iterator。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;
}
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 注入) 等。[Action, Model, Request, Session, Application]。setValue("user.name", "John") 自動建立巢狀物件、類型轉換 (String→Integer 等)。users.{name}, users.{? age > 18}。