struts调用流程如下图所示。
看到这幅图一下子就能了解了struts的原理。spring的核心就是ioc容器和aop,所以我们用spring主要是管理业务对象和事务的管理,所以主要是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环境,关于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环境,拷贝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();
//但是我们每次都要去调用,去创建太麻烦了.
//我们在这里只需要去配置listener就可以了,spring给实现好了.
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、 建立业务逻辑层,代码如下所示。
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文件,我们是否可以在服务器启动的时候就就创建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来创建,让代理action负责拿到beanfactory,根据path名称到ioc中把对应的action取出来。
我们是在model层应用spring,在action中取得beanfactory,然后通过springioc来找到model层的bean。但是这这样存在一些问题,我们在action中使用的是spring相关的静态类,这就说明我们依赖的是spring的静态类,我们希望所依赖的是接口而不是类,符合设计原则,面向接口编程,这样也容易扩展和维护。于是在此基础上进行改进。
第二种方案是将struts的action交给spring创建,这样业务逻辑对象将被注入,这样就避免了依赖查找,而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>
|
在这里配置对应的本系统实际的action,注意名字一定要和struts中代理action一致!并且设置每次创建一个新的action,而不是共用一个action,scope="prototype"。
这样在loginaction中,我们不用再看到创建model和工厂的细节,使用springioc,创建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创建而是由spring创建.
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框架就相当于我们的工具,我们把工具挖掘和使用的淋漓尽致才好,这可能就是人和工具的区别,人利用创造和利用工具,工具被创造和被利用。这中间的过程就是磨合了。
原文链接:http://blog.sina.com.cn/s/blog_9c6852670102wvtr.html