Java程式設計師從笨鳥到菜鳥之(八十二)細談Spring(十一)深入理解spring+struts2整合(附原始碼)
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow
也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!
Spring和struts2是我們在專案架構中用的比較多的兩個框架,怎麼才能把這兩個框架用好,怎麼來整合是我們掌握運用這兩個框架的關鍵點,下面我們就怎麼來整合,從哪來整合,為什麼要整合,從這幾點來看一下
我們一起來想想,如果讓spring和struts2進行整合,我們就希望我們可以在spring中直接注入action,spring容器初始化的時候就給我們建好了action,但是事情不像我們想象的那麼簡單,因為struts2的action是由struts2自己new出來的,他不受spring的管理,所以無法自動注入。所以struts和spring的整合的結合點在於,struts2的action不能直接入service。好了,既然有了問題,spring或者struts2肯定已經為我們把這個問題解決了。
原始碼下載:用力點
下面我們就具體的來看一下struts+spring的整合過程:
1.需要的jar包列表:Struts2.1.6 + Spring2.5.6 + Hibernate3.3.2
jar包名稱 |
所在位置 |
說明 |
antlr-2.7.6.jar |
hibernate/lib/required |
解析HQL |
aspectjrt |
spring/lib/aspectj |
AOP |
aspectjweaver |
.. |
AOP |
cglib-nodep-2.1_3.jar |
spring/lib/cglib |
代理,二進位制增強 |
common-annotations.jar |
spring/lib/j2ee |
@Resource |
commons-collections-3.1.jar |
hibernate/lib/required |
集合框架 |
commons-fileupload-1.2.1.jar |
struts/lib |
struts |
commons-io-1.3.2 |
struts/lib |
struts |
commons-logging-1.1.1 |
單獨下載,刪除1.0.4(struts/lib) |
struts spring |
dom4j-1.6.1.jar |
hibernate/required |
解析xml |
ejb3-persistence |
hibernate-annotation/lib |
@Entity |
freemarker-2.3.13 |
struts/lib |
struts |
hibernate3.jar |
hibernate |
|
hibernate-annotations |
hibernate-annotation/ |
|
hibernate-common-annotations |
hibernate-annotation/lib |
|
javassist-3.9.0.GA.jar |
hiberante/lib/required |
hibernate |
jta-1.1.jar |
.. |
hibernate transaction |
junit4.5 |
||
mysql- |
||
ognl-2.6.11.jar |
struts/lib |
|
slf4j-api-1.5.8.jar |
hibernate/lib/required |
hibernate-log |
slf4j-nop-1.5.8.jar |
hibernate/lib/required |
|
spring.jar |
spring/dist |
|
struts2-core-2.1.6.jar |
struts/lib |
|
xwork-2.1.2.jar |
struts/lib |
struts2 |
commons-dbcp |
spring/lib/jarkata-commons |
|
commons-pool.jar |
.. |
|
struts2-spring-plugin-2.1.6.jar |
struts/lib |
2.配置好jar包以後,如果我們想在伺服器一啟動就可以讓spring容器自動去載入我們在配置檔案中配置的bean,那麼我們要在web.xml中去配置一個監聽器,這個監聽器的作用是監聽我們的application,一旦我們的專案啟動就觸發了監聽器,我們來看一下這個監聽器的配置:
<listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class><!-- default: /WEB-INF/applicationContext.xml --></listener>
如果你的配置檔案不想放在預設的位置,而是自己去指定位置,那麼我們將要在web.xml中再次配置如下:
<context-param><param-name>contextConfigLocation</param-name>//這種配置可以指定多個配置檔案,因為spring的配置檔案可以分開寫成好幾個<!-- <param-value>/WEB-INF/applicationContext-*.xml,classpath*:applicationContext-*.xml</param-value> -->//指定spring配置檔案的位置classpath下的beans.xml<param-value>classpath:beans.xml</param-value></context-param>
載入完上面的bean之後,我們就要考慮去管理我們的action了,我們應該讓spring去找struts去要相應的action,把action例項化為響應的bean,這時我們就需要我們上邊所提到的struts-spring-plugin這個jar包了。加上這個jar包之後我們就可以讓spring來管理我們的action了。在struts-spring-plugin中有一個struts--plugin。Xml檔案。下面我們來看一下這個檔案中的配置執行的具體過程:
<struts> <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" /> <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>
關鍵是這個 <constant name="struts.objectFactory" value="spring" />,這句配置就指明瞭我們產生struts物件的工廠交給spring來產生,我們來看一下具體步驟:
struts2一起動就會去載入配置檔案,其中包括struts—plugin。xml讀取順序:
struts的讀常量:
struts-default.xml
struts-plugin.xml
struts.xml
struts.properties
web.xml
struts-plugin.xml指明瞭我們產生物件的工廠交給spring來完成,當執行到web.xml時,由於spring容器的監聽器,這時spring容器就開始啟動,spring啟動之後會web.xml去找相應的配置,在web.xml中可以找到spring中的配置檔案beans.xml,然後去初始化所有的bean。
spring去載入beans.xml的時候會自動把所有的bean初始化,並且放在自己的容器裡。與此同時,struts2也有自己的bean容器,這個容器是struts—plugin提供的,他會把所有的action載入都載入到自己的容器裡。然後根據action的屬性名字自動去spring去找名字和action屬性相同的bean直接注入到action中,也就是說。我們在action中其實不用配置注入的東西,struts容器會自動給我們注入。但還是要提供相應的set、get方法。並且名字要約定好,action屬性和spring中的bean的id要一樣。但不要忘記,action的scope設定成prototype
下面我們來看一下具體的示例程式碼:
package com.bzu.action;import org.springframework.context.support.ClassPathXmlApplicationContext;import com.bzu.entity.Student;import com.bzu.service.StudentService;import com.opensymphony.xwork2.ActionSupport;public class StudentAction extends ActionSupport {private Student student;private StudentService service;@Overridepublic String execute() throws Exception {// TODO Auto-generated method stubservice.login(student);return SUCCESS;}public StudentService getService() {return service;}public Student getStudent() {return student;}public void setStudent(Student student) {this.student = student;}public void setService(StudentService service) {this.service = service;}//public static void main(String[] args) {//ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(//"beans.xml");////StudentAction action = (StudentAction) context.getBean("StudentAction");////System.out.println(action == null);////StudentService ser = action.getService();////ser.login(new Student("ss", "ss"));////}
需要注意的是,spring和struts2整合的時候有一個屬性struts.objectFactory.spring.autoware,也就是說是struts屬性的的自動裝配型別,他的預設值是name,也就是說struts中的action中的屬性不需要配置,他預設的去beans.xml中去找名字相同的,應該注意的是,在給一些屬性起名字的時候不要和spring中配置的action的name屬性相同,否則會報異常
下面我們來看一下struts.xml和beans.xml的相關配置:
Struts.xml:
<struts><package name="registration" extends="struts-default"><action name="StudentAction" class="com.bzu.action.StudentAction"><result name="success">/Success.jsp</result><result name="fail">/Fail.jsp</result></action></package></struts>
Beans.xml
<bean id="stuDao" class="com.bzu.dao.impl.StudentDaoImpl"></bean><bean id="service" class="com.bzu.service.impl.StudentServiceImpl"><property name="dao" ref="stuDao"></property></bean><!--這裡完全可以不寫--><!--<bean id="StudentAction" class="com.bzu.action.StudentAction" scope="prototype"><property name="service" ref="service"></property></bean>-->
上面的示例是用的struts2的容器來產生action,spring需要的時候要去struts容器裡面去找action,然後再初始化bean,其實我們還有一種方法產生action,那就是讓spring容器去幫我們來產生action,這樣我們產生action的時候就可以去spring容器裡面去找了,具體應該是在spring配置檔案beans.xml中把對應的action配置成bean,然後再struts.xml中配置action的時候,action對應的class就不再是配置成該action對應的類了,而是配置這個action對應的spring容器的bean的id屬性,這樣action初始化的時候就會去spring容器裡面去找了。但是這樣配置的話,我們的action屬性就必須配置了,因為spring來產生action後,struts容器就不會在自動去給我們注入屬性了。如果不配置屬性的話會產生異常,下面我們來看一下具體配置情況:
Action的程式碼還是以前的程式碼,沒有改變,這裡就不再重複寫了,下面我們來看一下struts.xml的配置:
Struts.xml
<struts><package name="registration" extends="struts-default"><action name="StudentAction" class="stuAction"><result name="success">/Success.jsp</result><result name="fail">/Fail.jsp</result></action></package></struts>
上面的class對應的是下面action中bean的id屬性
Beans.xml
[html]
view plain
copy
print
?
- <code class="language-html"><bean id="stuDao" class="com.bzu.dao.impl.StudentDaoImpl"></bean>
- <bean id="service" class="com.bzu.service.impl.StudentServiceImpl">
- <property name="dao" ref="stuDao"></property>
- </bean>
- <!--現在這裡必須寫了,不寫會報錯-->
- <bean id="stuAction" class="com.bzu.action.StudentAction" scope="prototype">
- <property name="service" ref="service"></property>
- </bean></code>
<bean id="stuDao" class="com.bzu.dao.impl.StudentDaoImpl"></bean><bean id="service" class="com.bzu.service.impl.StudentServiceImpl"><property name="dao" ref="stuDao"></property></bean><!--現在這裡必須寫了,不寫會報錯--><bean id="stuAction" class="com.bzu.action.StudentAction" scope="prototype"><property name="service" ref="service"></property></bean>
OK,struts2+spring整合講到這就基本完了,當然我說的也不是很全面,希望大家見諒,希望大家能提出寶貴意見