Spring整合Struts的兩種方式介紹


1 使用Spring托管Struts Action

該種方式就是將Struts Action也視為一種Bean交給Spring來進行托管,使用時Struts的配置文件中配置的Action的classs屬性不再是具體Action的實現類,而是在Spring配置文件中配置的BeanID,也就是說具體是Action實現類是在Spring的配置文件中進行配置的,Struts的配置文件中的Class屬性只是Spring文件中Bean的ID。Struts配置文件如下示例:

<action name="LoginAction" class="loginAction">

       <!--登錄Action com.simpleworkflow.action.LoginAction-->

       <result name="input">/WEB-INF/content/login.jsp</result>

        <result name="mgr">/WEB-INF/content/manager/index.jsp</result>

        <result name="emp">/WEB-INF/content/employee/index.jsp</result>

        <result name="error">/WEB-INF/content/login.jsp</result>

</action>

 

同時需要在Struts配置文件中加入如下配置:

<struts>

    <constant name="struts.objectFactory" value="spring" />

</struts>

 

而Spring的配置文件中有如下配置:

<!--配置Action-->

<bean id="loginAction" class="com.simpleworkflow.action.LoginAction" scope="prototype">

    <!--登錄驗證Action-->

    <property name="empService" ref="employeeOperator"/>

    <property name="mgrService" ref="managerOperator"/>

</bean>

 

可以看到,在Spring中配置的Bean的Class屬性才是該Action的具體實現類,而且還可以為該Action設置其行為,該行為可以有singleton、prototype、request、session、global Session幾個值(幾個值的詳細解釋請參考Spring Bean介紹),由於Web環境下,Action通常是無狀態的,即每個HttpRequest對應一個Action,請求完成后該Action就應該進行釋放,而不是繼續保留供其他請求使用,因此,Action的Scope屬性的值通常設為prototype,表示每次請求都會產生一個新的實例。

需要注意的是,為了完成Spring托管Struts Action,必須加入一個包,該包為:struts2-spring-plugin-2.2.1.jar,或者其他版本。如果系統中加入了該包,那么就不需要在Struts配置文件中加入<constant/>配置了,該常量配置是指示Action的創建者由Struts變為Spring。為什么加入了該包以后就不需要加入<constant/>的配置了呢?這是由於在包內定義了一個struts-plugin.xml的文件,該文件內容如下所示:

<struts>

     <!—創建Action的類變為了StrutsSpringObjectFactory-->

    <bean type="com.opensymphony.xwork2.ObjectFactory" name="spring" class="org.apache.struts2.spring.StrutsSpringObjectFactory" />

    <!--  Make the Spring object factory the automatic default -->

    <constant name="struts.objectFactory" value="spring" />

    <constant name="struts.class.reloading.watchList" value="" />

    <constant name="struts.class.reloading.acceptClasses" value="" />

    <constant name="struts.class.reloading.reloadConfig" value="false" />

    <package name="spring-default">

        <interceptors>

            <interceptor name="autowiring" class="com.opensymphony.xwork2.spring.interceptor.ActionAutowiringInterceptor"/>

            <interceptor name="sessionAutowiring" class="org.apache.struts2.spring.interceptor.SessionContextAutowiringInterceptor"/>

        </interceptors>

    </package>   

</struts>

 

由於這種方式Struts配置文件中指定的Action的Class屬性並不是真實的實現類,因此破壞了Struts配置文件的原生性,並且需要在Spring中添加Action的配置文件,造成大量的配置冗余,因此更加推薦自動裝配的方式。

 

2 自動裝配方式(推薦)

由Spring托管Struts Action的方式(方式1)將Action的創建者由Struts改變為Spring,Action不再由Struts核心進行創建,而是類似應用中的其他Bean一樣由Spring進行容器在初始化時進行創建。自動裝配則不然,它會用Struts2配置文件中的class屬性去和Spring配置文件中的id屬性進行關聯(存在一個尋找過程),如果能找到則由Spring創建,否則由Struts2框架自身創建,然后由Spring來裝配。所以Action的實際創建者仍然是Struts(沒人會拿包路徑當BeanID),Spring只是負責裝配。

同樣需要引入上面介紹的包(必須引入該包了),並且在Struts.xml中加入如下常量屬性配置(必須):

<constant name="struts.objectFactory.spring.autoWire" value="true"></constant>

 

但是Struts配置文件中Action的Class屬性不再是BeanID,而是實際的Action類。

<action name="loginAction" class="com.huateng.framework.action.LoginAction">

       <result name="emperorsuccess">/fpages/emperorMain.jsp</result>

       <result name="adminsuccess">/fpages/admin.jsp</result>

       <result name="queensuccess">/fpages/queenMain.jsp</result>

       <result name="ministersuccess">/fpages/ministerMain.jsp</result>

       <result name="input">/fpages/login.jsp</result>

</action>

 

而在Spring配置文件中不需要再次配置該Action。

 

3   方式1、2的對比

方式一中加入額外插件,可加可不加常量配置語句,Action的創建者為Spring,他會根據Action的Class屬性的值搜索Spring配置文件,找到Bean Id為Class屬性值的Bean。Action由Spring在初始化時創建並完成后續的裝載(裝載:在Action中使用的其他Bean由Spring容器生成,並注入到Action中去。詳見4.4)。由於需要在兩個配置文件中添加配置,因此容易造成配置冗余。

方式二加入了額外插件,以及在Struts配置文件中加入一條常量配置,Action的實際創建者仍為Struts,Spring只是負責為創建好的Action注入所需要的邏輯組件。

 

方式1

方式2

使用方法

加入插件;

加插件,加常量配置

Action的創建者

Spring

在容器中尋找,找到則為Spring,未找到則為Struts

插件中的組件裝配攔截器是否起作用

插件中的攔截器起作用。Spring負責注入邏輯組件。

插件中的攔截器起作用。Spring負責注入邏輯組件。

 

4 使用Spring管理Struts中使用到的Bean

使用自動裝配方式來整合Spring和Struts,Struts的配置文件—struts.xml中Action的定義方式不需要做任何改變,但是需要在web.xml中配置Spring的配置文件,來加載Bean的定義文件,加載后容器就會托管已經定義好的Bean,而在Action中,只需要定義需要注入的Bean,比如Service等,同時設置好Setter方法和Getter方法,在execute方法中直接使用該Bean的方法即可。

需要改變的地方有:

需要打開Spring托管Struts的開關,該開關相當於是告知Spring,要負責為定義的Action注入所需的邏輯組件。在Struts.xml中添加如下語句(方式2需要加入,如果是方式一不需要):

<constant name="struts.objectFactory.spring.autoWire" value="true"></constant>

 

變量struts.objectFactory.spring.autoWire的值設置為true即為標識自動裝配打開,Spring容器會自動根據在Struts Action類中定義的Bean的名字查找容器中是否有該容器的定義,如果有,就自動為該類(Action)注入該Bean,如果沒有那么就無法完成注入。

這種策略下,Struts的配置文件和不整合Spring時沒有區別(需要加入上面的語句)。區別在於如果是方式1,Action的創建者是Spring,那么后續的裝配自然由Spring容器完成。而方式2由於Action的實際創建者仍然是Struts,而Spring容器只是負責為創建好的Action實例注入所需要的邏輯組件而已。

 

5     struts.objectFactory和struts.objectFactory.spring.autoWire

struts.objectFactory這個屬性用於說明Struts2的對象池創建工廠,Struts2也有自己的對象池,就像Spring那樣,在配置文件中你可以引用對象池中的對象,你可以借助於Spring中的對象池,當想要得到Spring中的對象池時,申明struts.objectFactory為Spring的對象池構建工廠。當指定struts.objectFactory為spring時,struts2框架就會把bean轉發給spring來創建,裝配,注入。但是bean創建完成之后,還是由struts容器來管理其生命周期。

在struts.xml中的代碼如下:

<constant name="struts.objectFactory" value="spring" />

 

struts.objectFactory.spring.autoWire是用spring插件通過覆蓋(override)Struts2的 ObjectFactory來增強核心框架對象的創建。當創建一個對象的時候,它會用Struts2配置文件中的class屬性去和Spring配置文件中的id屬性進行關聯,如果能找到則由Spring創建,否則由Struts2框架自身創建,然后由Spring來裝配。

Spring插件(struts2-spring-plugin-2.2.1.jar)具體有如下幾個作用:

1. 允許spring來創建Action、Interceptror和Result;

2. 由Struts創建的對象能夠被Spring裝配;

3. 提供了2個攔截器來自動裝配action;

這里要注意的是,我們不必在Spring中去注冊action,盡管我們可以這么去做,通常Struts框架會自動的從action mapping中創建action對象。

這樣就是讓spring去管理這些bean


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM