struts調用流程如下圖所示。
看到這幅圖一下子就能了解了struts的原理。spring的核心就是ioc容器和aop,所以我們用spring主要是管理業(yè)務對象和事務的管理,所以主要是model層來讓spring管理,這是我們的一種方案。
第一種集成方案在action中取得beanfactory
還記的在上篇文章中,測試的時候是在單元測試中拿到的beanfactory,與struts結合就是在action中取得beanfactory。步驟如下。
1、 建立一個web項目。
2、 建立相關頁面,代碼如下所示。
login.jsp代碼入下所示。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
<%@ pagelanguage= "java" contenttype= "text/html; charset=gb18030" pageencoding= "gb18030" %> <!doctype html public "-//w3c//dtd html 4.01 transitional//en" "http://www.w3.org/tr/html4/loose.dtd" > <html> <head> <metahttp-equiv= "content-type" content= "text/html;charset=gb18030" > <title>insert titlehere</title> </head> <body> <formaction= "login.do" method= "post" > 用戶:<input type= "text" name= "username" ><br> 密碼:<input type= "password" name= "password" ><br> <inputtype= "submit" value= "登錄" > </form> </body> </html> |
login_success.jsp
1
2
3
4
5
6
7
8
9
10
11
12
13
|
<%@ pagelanguage= "java" contenttype= "text/html; charset=gb18030" pageencoding= "gb18030" %> <!doctype html public "-//w3c//dtd html 4.01 transitional//en" "http://www.w3.org/tr/html4/loose.dtd" > <html> <head> <metahttp-equiv= "content-type" content= "text/html;charset=gb18030" > <title>insert titlehere</title> </head> <body> xx,用戶登錄成功! </body> </html> |
3、 配置struts環(huán)境,關于struts的配置,拷貝struts和jstl的依賴包;在web.xml中配置actionservlet,提供struts-config.xml文件。前篇文中有說明,在此就不贅述了。
struts-config.xml代碼如下所示。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
<struts-config> <form-beans> <form-beanname= "loginform" type= "com.bjpowernode.usermgr.web.forms.loginactionform" ></form-bean> </form-beans> <action-mappings> <actionpath= "/login" type= "com.bjpowernode.usermgr.web.actions.loginaction" name= "loginform" scope= "request" > <forwardname= "success" path= "/login_success.jsp" /> </action> </action-mappings> <message-resourcesparameter= "resources.messageresources" /> </struts-config> |
4、 配置spring環(huán)境,拷貝spring相關jar包,建立spring配置文件applicationcontext-beans.xml。
applicationcontext-beans.xml代碼如下所示。
1
2
3
4
5
6
7
8
9
|
<beansxmlns= "http://www.springframework.org/schema/beans" xmlns:xsi= "http://www.w3.org/2001/xmlschema-instance" xmlns:aop= "http://www.springframework.org/schema/aop" xmlns:tx= "http://www.springframework.org/schema/tx" xsi:schemalocation="http: //www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.0.xsd http: //www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-2.0.xsd http: //www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx-2.0.xsd"> <beanid= "usermanager" class = "com.bjpowernode.usermgr.manager.usermanagerimpl" /> </beans> |
5、 建立相關的action和actionform。代碼如下所示。
loginaction.java代碼如下所示。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
public class loginaction extendsaction { @override publicactionforward execute(actionmapping mapping, actionform form, httpservletrequestrequest, httpservletresponse response) throwsexception { loginactionformlaf = (loginactionform)form; stringusername = laf.getusername(); stringpassword = laf.getpassword(); //但是我們每次都要去調用,去創(chuàng)建太麻煩了. //我們在這里只需要去配置listener就可以了,spring給實現(xiàn)好了. beanfactoryfactory = newclasspathxmlapplicationcontext( "applicationcontext.xml" ); usermanagerusermanager = (usermanager)factory.getbean( "usermanager" ); usermanager.login(username,password); } } |
loginactionform.java代碼如下所示。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
public class loginactionformextends actionform { //表單上有什么提供什么屬性. //名字一定要與表單中的一樣. privatestring username; publicstring getusername() { returnusername; } publicvoid setusername(string username) { this .username= username; } privatestring password; publicstring getpassword() { returnpassword; } publicvoid setpassword(string password) { this .password= password; } } |
6、 建立業(yè)務邏輯層,代碼如下所示。
usermanager代碼如下所示。
1
2
3
|
public interface usermanager { publicvoid login(string username, string password); } |
usermanagerimpl.java代碼如下所示。
1
2
3
4
5
|
public class usermanagerimplimplements usermanager { publicvoid login(string username, string password) { system.out.println( "usermanagerimpl" + "username=" + username); } } |
7、 web.xml配置文件代碼如下所示。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
<servlet> <servlet-name>action</servlet-name> <servlet- class >org.apache.struts.action.actionservlet</servlet- class > <init-param> <param-name>config</param-name> <param-value>/web-inf/struts-config.xml</param-value> </init-param> <init-param> <param-name>debug</param-name> <param-value> 2 </param-value> </init-param> <init-param> <param-name>detail</param-name> <param-value> 2 </param-value> </init-param> <load-on-startup> 2 </load-on-startup> </servlet> |
就這樣我們在loginaction中,使用beanfactory讀取spring配置文件,找到usermanagerimpl實例。如果每次在action中讀取application-beans.xml文件,我們是否可以在服務器啟動的時候就就創(chuàng)建beanfactory呢?在這里我們可以使用spirng的工具webapplicationcontextutils.getrequiredwebapplicationcontext()從 servletcontext中 取得beanfactory,然后再web.xml中配置spring的listener。
修改后,loginaction代碼如下所示。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
public class loginaction extendsaction { @override publicactionforward execute(actionmapping mapping, actionform form, httpservletrequestrequest, httpservletresponse response) throwsexception { loginactionformlaf = (loginactionform)form; stringusername = laf.getusername(); stringpassword = laf.getpassword(); //用工具包直接拿出來就可以了。 beanfactoryfactory =webapplicationcontextutils.getrequiredwebapplicationcontext(request.getsession().getservletcontext()); usermanagerusermanager = (usermanager)factory.getbean( "usermanager" ); usermanager.login(username,password); returnmapping.findforward( "success" ); } } |
加入相關配置,web.xml代碼如下所示。
1
2
3
4
5
6
7
|
<context-param> <param-name>contextconfiglocation</param-name> <param-value>classpath:applicationcontext-*.xml</param-value> </context-param> <listener> <listener- class >org.springframework.web.context.contextloaderlistener</listener- class > </listener> |
這種方案缺點:
我們在在action中仍然看到spring相關東西,看到spring相關類,要是程序只看到的是接口,那要怎么做呢?
第二種方案,將struts的aciton交給spring來創(chuàng)建,讓代理action負責拿到beanfactory,根據(jù)path名稱到ioc中把對應的action取出來。
我們是在model層應用spring,在action中取得beanfactory,然后通過springioc來找到model層的bean。但是這這樣存在一些問題,我們在action中使用的是spring相關的靜態(tài)類,這就說明我們依賴的是spring的靜態(tài)類,我們希望所依賴的是接口而不是類,符合設計原則,面向接口編程,這樣也容易擴展和維護。于是在此基礎上進行改進。
第二種方案是將struts的action交給spring創(chuàng)建,這樣業(yè)務邏輯對象將被注入,這樣就避免了依賴查找,而spring中會有一個代理action,通過代理actionproxy取得banfactory。方案一和方案二的對比圖如下圖所示。
這樣就不用spring的listener了,所以我們的web.xml配置文件代碼如下所示。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
<?xml version= "1.0" encoding= "utf-8" ?> <web-app version= "2.4" xmlns= "http://java.sun.com/xml/ns/j2ee" xmlns:xsi= "http://www.w3.org/2001/xmlschema-instance" xsi:schemalocation="http: //java.sun.com/xml/ns/j2ee http: //java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <servlet> <servlet-name>action</servlet-name> <servlet- class >org.apache.struts.action.actionservlet</servlet- class > <init-param> <param-name>config</param-name> <param-value>/web-inf/struts-config.xml</param-value> </init-param> <init-param> <param-name>debug</param-name> <param-value> 2 </param-value> </init-param> <init-param> <param-name>detail</param-name> <param-value> 2 </param-value> </init-param> <load-on-startup> 2 </load-on-startup> </servlet> |
同時再struts的配置文件,struts-config.xml中,在<action-mappings>標簽中配置action,也不再配置我們自己建立的action,而是配置spring自己的代理action。代碼如下所示。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
<?xml version= "1.0" encoding= "iso-8859-1" ?> <!doctype struts-config public "-//apache software foundation//dtd struts configuration 1.2//en" "http://jakarta.apache.org/struts/dtds/struts-config_1_2.dtd" > <struts-config> <form-beans> <form-bean name= "loginform" type= "com.bjpowernode.usermgr.web.forms.loginactionform" ></form-bean> </form-beans> <action-mappings> <action path= "/login" type= "org.springframework.web.struts.delegatingactionproxy" name= "loginform" scope= "request" > <forward name= "success" path= "/login_success.jsp" /> </action> </action-mappings> <message-resources parameter= "resources.messageresources" /> </struts-config> |
spring對aciton的配置文件如下所示。applicationcontext-actions.xml.
1
2
3
4
5
6
7
8
9
10
11
12
|
<?xml version= "1.0" encoding= "utf-8" ?> <beans xmlns= "http://www.springframework.org/schema/beans" xmlns:xsi= "http://www.w3.org/2001/xmlschema-instance" xmlns:aop= "http://www.springframework.org/schema/aop" xmlns:tx= "http://www.springframework.org/schema/tx" xsi:schemalocation="http: //www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http: //www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd http: //www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd"> <bean name= "/login" class = "com.bjpowernode.usermgr.web.actions.loginaction" scope= "prototype" > <property name= "usermanager" ref= "usermanager" /> </bean> </beans> |
在這里配置對應的本系統(tǒng)實際的action,注意名字一定要和struts中代理action一致!并且設置每次創(chuàng)建一個新的action,而不是共用一個action,scope="prototype"。
這樣在loginaction中,我們不用再看到創(chuàng)建model和工廠的細節(jié),使用springioc,創(chuàng)建model,usermanager,并且配置文件中注入loginaction,這樣loginaction代碼如下所示。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
public class loginaction extends action { private usermanager usermanager; // 讓spring注入,loginaction讓spring管理, 不是讓strus創(chuàng)建而是由spring創(chuàng)建. public void setusermanager(usermanager usermanager) { this .usermanager = usermanager; } @override public actionforward execute(actionmapping mapping, actionform form, httpservletrequest request, httpservletresponse response) throws exception { loginactionform laf = (loginactionform) form; string username = laf.getusername(); string password = laf.getpassword(); usermanager.login(username, password); return mapping.findforward( "success" ); } } |
小結:
spring框架就相當于我們的工具,我們把工具挖掘和使用的淋漓盡致才好,這可能就是人和工具的區(qū)別,人利用創(chuàng)造和利用工具,工具被創(chuàng)造和被利用。這中間的過程就是磨合了。
原文鏈接:http://blog.sina.com.cn/s/blog_9c6852670102wvtr.html