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

Spring 與 Struts 整合實戰:基於 ContextLoaderPlugin 與 ActionSupport 的最佳實踐

     編輯:Java 相關知識

為什麼要整合 Spring 與 Struts?

  • Struts 1.x 是經典 MVC 框架,掌管 Web 層請求分派、表單驗證、視圖轉向。
  • Spring 提供強大的 IoC 容器、AOP、宣告式事務、統一資料存取異常處理,管理業務邏輯與持久層。
  • 整合後:Struts 負責控制層,Spring 管理 Service/DAO 層,職責分離清晰,利於測試與維護。

整合架構圖解

HTTP Request
    │
    ▼
Struts ActionServlet (Controller)
    │
    ├──► ActionForm (表單資料綁定/驗證)
    │
    └──► Action (Struts Action 子類)
            │
            ▼ (透過 Spring 取得 Bean)
    Spring Business Service (交易、邏輯)
            │
            ▼
    Spring DAO / ORM (Hibernate/MyBatis/JPA)
            │
            ▼
    Database
            │
            ▼
    Return ActionForward → JSP View

步驟一:配置 Struts 載入 Spring 容器

在 struts-config.xml 中註冊 ContextLoaderPlugIn,指定 Spring 設定檔位置:

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE struts-config PUBLIC
  "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"
  "https://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">

<struts-config>
  <!-- 既有 form-beans、global-forwards、action-mappings 略 -->

  <!-- Validator 外掛 -->
  <plug-in className="org.apache.struts.validator.ValidatorPlugIn">
    <set-property property="pathnames"
      value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml"/>
  </plug-in>

  <!-- ★ 關鍵:Spring 容器載入外掛 -->
  <plug-in className="org.springframework.web.struts.ContextLoaderPlugIn">
    <set-property property="contextConfigLocation"
      value="/WEB-INF/applicationContext.xml"/> <!-- Spring Bean 定義檔 -->
  </plug-in>
</struts-config>

步驟二:定義 Spring 業務 Bean

/WEB-INF/applicationContext.xml:

<beans>
  <bean id="creditcardService"
        class="com.infotek.Creditcard.business.CreditcardServiceImpl">
    <property name="dao" ref="creditcardDao"/>
  </bean>

  <bean id="creditcardDao"
        class="com.infotek.Creditcard.persistence.CreditcardDaoImpl">
    <property name="sessionFactory" ref="sessionFactory"/>
  </bean>
  <!-- dataSource、sessionFactory、transactionManager 等基礎設施 Bean 略 -->
</beans>

步驟三:Action 繼承 Spring 的 ActionSupport

package com.infotek.Creditcard.actions;

import org.springframework.web.struts.ActionSupport;
import org.springframework.context.ApplicationContext;
import com.infotek.Creditcard.business.CreditcardService;
import com.infotek.Creditcard.beans.Creditcard;
import org.apache.struts.action.*;

public class SearchSubmit extends ActionSupport { // ★ 繼承 ActionSupport

    public ActionForward execute(ActionMapping mapping, ActionForm form,
                                 HttpServletRequest request, HttpServletResponse response)
            throws IOException, ServletException {

        DynaActionForm searchForm = (DynaActionForm) form;
        String cardNo = (String) searchForm.get("cardno");

        // 1. 取得 Spring WebApplicationContext
        ApplicationContext ctx = getWebApplicationContext();

        // 2. 從容器取得 Service Bean(依賴查找)
        CreditcardService service = (CreditcardService) ctx.getBean("creditcardService");

        // 3. 呼叫業務邏輯
        Creditcard card = service.read(cardNo.trim());

        if (card == null) {
            ActionErrors errors = new ActionErrors();
            errors.add(ActionErrors.GLOBAL_ERROR,
                new ActionError("message.notfound"));
            saveErrors(request, errors);
            return mapping.findForward("failure");
        }

        request.setAttribute("creditcard", card);
        return mapping.findForward("success");
    }
}

關鍵類別說明

類別/介面角色備註
ContextLoaderPlugInStruts 啟動時初始化 Spring 容器,綁定至 ServletContext對應 WebApplicationContextUtils.getWebApplicationContext(servletContext)
ActionSupportSpring 提供的 Struts Action 基類,內建 getWebApplicationContext()避免在 Action 中硬編碼 WebApplicationContextUtils
DelegatingActionProxy另一種整合方式:Action 交由 Spring 管理,Struts 只持有 Proxy更純粹的 IoC,但需額外配置,本文採用 ActionSupport 簡單直接

優缺點分析與進階建議

優點

  • 設定簡單,零侵入業務碼,快速上手。
  • Action 仍由 Struts 管理生命週期,符合 Struts 開發習慣。

缺點

  • Action 與 Spring 耦合:繼承 ActionSupport 導致難以單元測試 Action(需模擬 Spring 容器)。
  • 無法享受 Spring AOP:Action 本身不在 Spring 容器管理下,攔截器、事務邊界無法套用到 Action 方法。
  • 依賴查找而非依賴注入:手動 ctx.getBean(),不如注入優雅。

進階改良:DelegatingActionProxy(推薦)

<!-- struts-config.xml -->
<action path="/searchSubmit"
        type="org.springframework.web.struts.DelegatingActionProxy"> <!-- Proxy -->
  <set-property property="delegateAction" value="searchSubmitAction"/> <!-- Spring Bean 名稱 -->
  <forward name="success" path="/WEB-INF/pages/detail.jsp"/>
  <forward name="failure" path="/WEB-INF/pages/search.jsp"/>
</action>
<!-- applicationContext.xml -->
<bean name="searchSubmitAction" class="com.infotek.Creditcard.actions.SearchSubmit">
  <property name="creditcardService" ref="creditcardService"/> <!-- 真正的 DI -->
</bean>

此時 SearchSubmit 可改為普通 POJO 或繼承 Action,由 Spring 完整管理,支援 AOP、@Transactional、單元測試注入 Mock。

總結

本文示範的 ContextLoaderPlugIn + ActionSupport 是 Struts 1.x 整合 Spring 最經典、門檻最低的方式,適合快速遷移既有專案。若追求純粹 IoC、AOP 支援與測試性,建議升級為 DelegatingActionProxy 模式,甚至考慮遷移至 Spring MVC 或 Spring Boot 現代架構。

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