也許有些人會因為學習了struts1,會以為struts2、struts1與spring的整合也是一樣的,其實這兩者相差甚遠。下面就來講解一下struts2與spring的整合兩種方案。(部分轉載,里面也有自己的內容)
借助于Spring插件(Struts2-spring-plugin-XXX.jar),我們可以非常簡單地完成Spring和Struts2的整合,這種整合包括讓Action自動裝配Spring容器中的Bean,以及讓Spring管理應用中的Action兩種方式,不管采用哪種方式,完成Struts2和Spring的整合都是非常簡單的,而且差別不大.一旦在Web應用中安裝了Spring插件,即可充分利用該插件提供的功能: 1,可以通過Spring來創(chuàng)建所有的Action,Interceptor和Result. 2,可以在Struts創(chuàng)建了某個對象(Action實例)之后,Spring將其依賴的組件自動注入該對象 3,提供了兩個攔截器來完成自動裝配. 此外,在使用Spring容器之前,必須先完成Spring容器的初始化,為了完成Spring容器的初始化,Struts2利用了Spring所提供的兩種初始化方式.1. 利用ContextLoaderListener Spring提供一個ContextLoaderListener對象,該類可以作為Web應用的Listener使用,它會在Web應用啟動時自動查找WEB-INF/下的applicationContext.xml配置文件(Spring的配置文件),并且根據該文件來創(chuàng)建Spring容器.因此,如果Web應用中只有一個Spring配置文件,并且文件名為"applicationContext.xml",并將該文件放在Web應用的WEB-INF/路徑下,則只需在web.xml文件中增加如下一段即可: <!-- 根據默認配置文件來初始化Spring容器 --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> 如果有多個配置文件需要載入,或則applicationContext.xml不在WEB-INF目錄下,則應該在web.xml中再使用<context-param>元素來確定配置文件的文件名,內容如下: <!-- 定義spring配置文件 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value> /WEB-INF/applicationContext.xml, /WEB-INF/classes/conf/spring/applicationContext-*.xml </param-value> </context-param> 如果spring配置文件被命名為applicationContext.xml,并且放在WEB-INF目錄下,則不需要配
置<context-param>,因為ContextLoaderListener默認在WEB-INF目錄下尋找名為
applicationContext.xml的文件。若存在多個Spring配置文件,則在<param-value>中依次列出,之間以
逗號隔開。
2. 采用load-on-startup Servlet創(chuàng)建ApplicationContext(這也是為了兼容Servlet 2.3以下版本,它們不支持<listener>,需要配置<servlet>) 利用Listener創(chuàng)建Spring容器很簡單,但有一個明顯的局限,因為Listener是Servlet2.3以后才開始出現(xiàn)的規(guī)范,這意味著在低版本的Servlet中只能利用Web應用中的load-on-startup的Servlet而不能利用Listener.這兩者的作用是一樣的.為了使用load-on-startup Servlet來創(chuàng)建Spring容器,Spring提供了一個特殊的Servlet類:ContextLoaderServlet,該Servlet在初始化時,會自動查找WEB-INF/下的"applicationContext.xml"文件,如果只有一個配置文件,并且名為"applicationContext.xml",則在web.xml文件中的配置如下: <servlet> <servlet-name>context</servlet-name> <servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> 該servlet僅用于提供后臺服務,負責創(chuàng)建spring容器,無需響應客戶端請求,因此無需配置servlet mapping. 如果有多個配置文件,則與上面一樣使用<context-param>元素來確定多個配置文件,事實上,無論是ContextLoaderServlet還是ContextLoaderListener都是通過調用ContextLoader來創(chuàng)建spring容器的。
在Servlet規(guī)范中Listener總是比Servlet優(yōu)先加載的,因此,采用ContextLoaderListener更好(web.xml 的加載順序是:context-param -> listener -> filter -> servlet ).
為了讓控制器Action訪問Spring的業(yè)務邏輯組件,有兩種策略: 1. Spring管理控制器,并利用依賴注入為控制器注入業(yè)務邏輯組件 1) 將Struts的業(yè)務邏輯控制器類配置在Spring的配置文件中,業(yè)務邏輯控制器中引用的業(yè)務類一并注入。注意,必須將業(yè)務邏輯控制器類配置為scope=”prototype”!
示例如下: <bean id=”LoginAction” class=”yaso.struts.action.LoginAction”>
<property name=”loginDao” ref=”LoginDao”/>
</bean>
2) 在struts.xml或者等效的Struts2配置文件中配置Action時,指定<action>的class屬性為Spring配置文件中相應bean的id或者name值。示例如下:
<action name=”LoginAction” class=”LoginAction”>
<result name=”success”>/index.jsp</result>
</action>
2. 控制器定位Spring工廠,也就是Spring的容器,從Spring容器中取得所需的業(yè)務邏輯組件.
1) 業(yè)務類在Spring配置文件中配置,業(yè)務邏輯控制器類不需要配置,Struts2的Action像沒有整合Spring之前一樣配置,<action>的class屬性指定業(yè)務邏輯控制器類的全限定名。
2)
業(yè)務邏輯控制器類中引用的業(yè)務類不需要自己去初始化,Struts2的Spring插件會使用bean的自動裝配將業(yè)務類注入進來,其實業(yè)務邏輯控制器也
不是Struts2創(chuàng)建的,而是Struts2的Spring插件創(chuàng)建的。默認情況下,插件使用by
name的方式裝配,可以通過增加Struts2常量來修改匹配方式:設置方式
為:struts.objectFactory.spring.autoWire = typeName,可選的裝配參數(shù)如下:
a) name:等價于Spring配置中的autowire=”byName”,這是缺省值。(框架會去Spring中尋找與Action屬性名字相同的bean)
b) type:等價于Spring配置中的autowire=”byType”。
c) auto:等價于Spring配置中的autowire=”autodetect”。
d) constructor:等價于Spring配置中的autowire=” constructor”。
就這個策略,我現(xiàn)在只知道利用byName來實現(xiàn)自動裝配。代碼如下: <?xml version="1.0" encoding="UTF-8"?> <bean name="empDao" class="com.neusoft.leehom.dao.EmpDao" ></bean> </beans> 由于上面empDao的名字相同,所以spring會直接根據注入屬性的名字查找與之同名字的bean。 對于這兩種方式,Struts2都提供了對應的整合實現(xiàn).比較這兩種整合方式,其本質是一樣的。不同之處在于,使用第二種自動裝配的方式時,由于沒有在Spring中配置業(yè)務邏輯控制器,所以需要對其配置一些AOP之類的內容時就很難實現(xiàn)了。 |
|