Struts 1.x 時代,將 Action 納管給 Spring IoC 容器可享受依賴注入、AOP 攔截器等紅利。本文對比三種整合方案,推薦「動作委派」模式為最佳實踐。
<plug-in className="org.springframework.web.struts.ContextLoaderPlugIn">
<set-property property="contextConfigLocation" value="/WEB-INF/beans.xml"/>
</plug-in>
public class SearchSubmit extends ActionSupport { // 繼承 Spring 基類
public ActionForward execute(...) {
ApplicationContext ctx = getWebApplicationContext(); // 取容器
BookService svc = (BookService) ctx.getBean("bookService"); // 手動查找
...
}
}
<controller processorClass="org.springframework.web.struts.DelegatingRequestProcessor"/>
<bean name="/searchSubmit" class="ca.nexcel.books.actions.SearchSubmit">
<property name="bookService" ref="bookService"/>
</bean>
public class SearchSubmit extends Action { // 繼承 Struts 原生 Action
private BookService bookService;
public void setBookService(BookService svc) { this.bookService = svc; } // Setter 注入
...
}
<action path="/searchSubmit"
type="org.springframework.web.struts.DelegatingActionProxy" />
<bean name="/searchSubmit" class="ca.nexcel.books.actions.SearchSubmit">
<property name="bookService" ref="bookService"/>
</bean>
// 1. 定義攔截器
public class LoggingInterceptor implements MethodBeforeAdvice {
public void before(Method m, Object[] args, Object target) {
System.out.println("Logging before: " + m.getName());
}
}
// 2. Spring 配置自動代理
<bean name="logger" class="ca.nexcel.books.interceptors.LoggingInterceptor"/>
<bean name="loggingAutoProxy" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="beanNames">
<list><value>/searchSubmit</value></list>
</property>
<property name="interceptorNames">
<list><value>logger</value></list>
</property>
</bean>
無需修改 Action 代碼,即可橫切織入日誌、事務、效能監控等關注點。
| 方案 | 耦合度 | AOP 支援 | 生命周期管理 | 推薦指數 |
|---|---|---|---|---|
| ActionSupport | 高(依賴 Spring API) | 無 | 無 | ⭐ |
| DelegatingRequestProcessor | 低 | 有 | 有 | ⭐⭐⭐ |
| DelegatingActionProxy | 零 | 有 | 完整 | ⭐⭐⭐⭐⭐ |
以 DelegatingActionProxy 為核心的「動作委派」模式,讓 Struts 專注於 Web 層調度,Spring 專注於業務對象管理與切面織入,是經典架構整合的教科書級範例。