在Struts 2通过Spring实现控制反转(IoC)
2016-05-21 18:00
591 查看
目录(?)在Struts
2通过Spring实现控制反转(IoC)
[-]
历史背景
具体实现
总结
IoC(Inversion of Control,以下译为控制反转)随着Java社区中轻量级容器(Lightweight
Contianer)的推广而越来越为大家耳熟能详。在此,我不想再多费唇舌来解释“什么是控制反转”和“为什么需要控制反转”。因为互联网上已经有非常多的文章对诸如此类的问题作了精彩而准确的回答。大家可以去读一下Rod Johnson和Juergen Hoeller合著的《Expert
one-on-one J2EE Development without EJB》或Martin Fowler所写的《Inversion
of Control Containers and the Dependency Injection pattern》。
言归正传,本文的目的主要是介绍在Struts 2中实现控制反转。
2推荐大家通过Spring实现控制反转。
然后,将所需的Spring的jar包加入到工程的构建环境(Build Path)中,如下图1所示:
图1 所依赖的Spring的jar包
本文使用的是Spring 2.0,Spring强烈建议大家在使用其jar包时,只引用需要的包,原因是Spring是一个功能非常强大的框架,其中有些功能是您不需要的;而且Spring提倡的是“按需所取”,而不是EJB的“爱我就要爱我的一切”。当然,如果你怕麻烦或者是不清楚每个包的作用,引用一个Spring的总包也未尝不可。
接下来,就要修改WEB-INF\web.xml文件了,内容为:
<?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">
<display-name>Struts 2 IoC Demo</display-name>
<filter>
<filter-name>struts-cleanup</filter-name>
<filter-class>
org.apache.struts2.dispatcher.ActionContextCleanUp
</filter-class>
</filter>
<filter>
<filter-name>struts2</filter-name>
<filter-class>
org.apache.struts2.dispatcher.FilterDispatcher
</filter-class>
</filter>
<filter-mapping>
<filter-name>struts-cleanup</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
</web-app>
清单1 WEB-INF\web.xml
大家一看便知道,主要是加入Spring的ContextLoaderListener监听器,方便Spring与Web容器交互。
紧接着,修改Struts.properties文件,告知Struts 2运行时使用Spring来创建对象(如Action等),内容如下:
struts.objectFactory=spring
清单2 classes\struts.properties
再下来,遵循Spring的原则——面向接口编程,创建接口ChatService,代码如下:
packagetutorial;
importjava.util.Set;
publicinterfaceChatService{
Set<String>getUserNames();
}
清单3 tutorial.ChatService.java
然后,再创建一个默认实现ChatServiceImpl,代码如下:
packagetutorial;
importjava.util.HashSet;
importjava.util.Set;
publicclassChatServiceImplimplementsChatService{
publicSet<String>getUserNames(){
Set<String>users=newHashSet<String>();
users.add("Max");
users.add("Scott");
users.add("Bob");
returnusers;
}
}
清单4 tutorial.ChatServiceImpl.java
接下来,就该新建Action了。tutorial.ChatAction.java的代码如下:
packagetutorial;
importjava.util.Set;
importcom.opensymphony.xwork2.ActionSupport;
publicclassChatActionextendsActionSupport{
privatestaticfinallongserialVersionUID=8445871212065L;
privateChatService chatService;
privateSet<String>userNames;
publicvoidsetChatService(ChatService
chatService) {
this.chatService=chatService;
}
publicSet<String>getUserNames(){
returnuserNames;
}
@Override
publicString
execute(){
userNames=chatService.getUserNames();
returnSUCCESS;
}
}
清单5 tutorial.ChatAction.java
ChatAction类使用属性(Getter/Setter)注入法取得ChatService对象。
然后,配置Spring的applicationContext.xml(位于WEB-INF下)文件,内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
<bean id="chatService"class="tutorial.ChatServiceImpl"/>
<bean id="chatAction"class="tutorial.ChatAction"scope="prototype">
<propertyname="chatService">
<reflocal="chatService"/>
</property>
</bean>
</beans>
清单6 WEB-INF\applicationContext.xml
上述代码有二点值得大家注意的:
Struts 2会为每一个请求创建一个Action对象,所以在定义chatAction时,使用scope="prototype"。这样Spring就会每次都返回一个新的ChatAction对象了;
因为ChatServiceImpl被配置为默认的scope(也即是singleton,唯一的),所以在实现时应保证其线程安全(关于编写线程安全的代码的讨论已经超出本文的范围,更超出了本人的能力范围,大家可以参考Addison Wesley Professional出版的《Java
Concurrency in Practice》)。
接下来,在classes/struts.xml中配置Action,内容如下:
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<includefile="struts-default.xml"/>
<packagename="Struts2_IoC"extends="struts-default">
<actionname="Chat"class="chatAction">
<result>/UserList.jsp</result>
</action>
</package>
</struts>
清单7 classes\struts.xml
这里的Action和平常不同的就是class属性,它对应于Spring所定义的bean的id,而不是它的类全名。
最后,让我们看看/UserList.jsp,内容如下:
<%@ page contentType="text/html;
charset=UTF-8"%>
<%@ taglib prefix="s"uri="/struts-tags"%>
<html>
<head>
<title>User List</title>
</head>
<body>
<h2>User List</h2>
<ol>
<s:iteratorvalue="userNames">
<li><s:property/></li>
</s:iterator>
</ol>
</body>
</html>
清单8 /UserList.jsp
大功告成,分布运行应用程序,在浏览器中键入http://localhost:8080/Struts2_IoC/Chat.action,出现如图2所示页面:
图2 /ListUser.jsp
2通过Spring实现控制反转(IoC)
[-]
历史背景
具体实现
总结
IoC(Inversion of Control,以下译为控制反转)随着Java社区中轻量级容器(Lightweight
Contianer)的推广而越来越为大家耳熟能详。在此,我不想再多费唇舌来解释“什么是控制反转”和“为什么需要控制反转”。因为互联网上已经有非常多的文章对诸如此类的问题作了精彩而准确的回答。大家可以去读一下Rod Johnson和Juergen Hoeller合著的《Expert
one-on-one J2EE Development without EJB》或Martin Fowler所写的《Inversion
of Control Containers and the Dependency Injection pattern》。
言归正传,本文的目的主要是介绍在Struts 2中实现控制反转。
历史背景
众所周知,Struts 2是以Webwork 2作为基础发展出来。而在Webwork 2.2之前的Webwork版本,其自身有一套控制反转的实现,Webwork 2.2在Spring 框架的如火如荼发展的背景下,决定放弃控制反转功能的开发,转由spring实现。值得一提的是,Spring确实是一个值得学习的框架,因为有越来越多的开源组件(如iBATIS等)都放弃与Spring重叠的功能的开发。因此,Struts2推荐大家通过Spring实现控制反转。
具体实现
首先,在开发环境中配置好Struts 2的工程。对这部分仍然有问题的朋友,请参考我的早前的文章。然后,将所需的Spring的jar包加入到工程的构建环境(Build Path)中,如下图1所示:
图1 所依赖的Spring的jar包
本文使用的是Spring 2.0,Spring强烈建议大家在使用其jar包时,只引用需要的包,原因是Spring是一个功能非常强大的框架,其中有些功能是您不需要的;而且Spring提倡的是“按需所取”,而不是EJB的“爱我就要爱我的一切”。当然,如果你怕麻烦或者是不清楚每个包的作用,引用一个Spring的总包也未尝不可。
接下来,就要修改WEB-INF\web.xml文件了,内容为:
<?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">
<display-name>Struts 2 IoC Demo</display-name>
<filter>
<filter-name>struts-cleanup</filter-name>
<filter-class>
org.apache.struts2.dispatcher.ActionContextCleanUp
</filter-class>
</filter>
<filter>
<filter-name>struts2</filter-name>
<filter-class>
org.apache.struts2.dispatcher.FilterDispatcher
</filter-class>
</filter>
<filter-mapping>
<filter-name>struts-cleanup</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
</web-app>
清单1 WEB-INF\web.xml
大家一看便知道,主要是加入Spring的ContextLoaderListener监听器,方便Spring与Web容器交互。
紧接着,修改Struts.properties文件,告知Struts 2运行时使用Spring来创建对象(如Action等),内容如下:
struts.objectFactory=spring
清单2 classes\struts.properties
再下来,遵循Spring的原则——面向接口编程,创建接口ChatService,代码如下:
packagetutorial;
importjava.util.Set;
publicinterfaceChatService{
Set<String>getUserNames();
}
清单3 tutorial.ChatService.java
然后,再创建一个默认实现ChatServiceImpl,代码如下:
packagetutorial;
importjava.util.HashSet;
importjava.util.Set;
publicclassChatServiceImplimplementsChatService{
publicSet<String>getUserNames(){
Set<String>users=newHashSet<String>();
users.add("Max");
users.add("Scott");
users.add("Bob");
returnusers;
}
}
清单4 tutorial.ChatServiceImpl.java
接下来,就该新建Action了。tutorial.ChatAction.java的代码如下:
packagetutorial;
importjava.util.Set;
importcom.opensymphony.xwork2.ActionSupport;
publicclassChatActionextendsActionSupport{
privatestaticfinallongserialVersionUID=8445871212065L;
privateChatService chatService;
privateSet<String>userNames;
publicvoidsetChatService(ChatService
chatService) {
this.chatService=chatService;
}
publicSet<String>getUserNames(){
returnuserNames;
}
@Override
publicString
execute(){
userNames=chatService.getUserNames();
returnSUCCESS;
}
}
清单5 tutorial.ChatAction.java
ChatAction类使用属性(Getter/Setter)注入法取得ChatService对象。
然后,配置Spring的applicationContext.xml(位于WEB-INF下)文件,内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
<bean id="chatService"class="tutorial.ChatServiceImpl"/>
<bean id="chatAction"class="tutorial.ChatAction"scope="prototype">
<propertyname="chatService">
<reflocal="chatService"/>
</property>
</bean>
</beans>
清单6 WEB-INF\applicationContext.xml
上述代码有二点值得大家注意的:
Struts 2会为每一个请求创建一个Action对象,所以在定义chatAction时,使用scope="prototype"。这样Spring就会每次都返回一个新的ChatAction对象了;
因为ChatServiceImpl被配置为默认的scope(也即是singleton,唯一的),所以在实现时应保证其线程安全(关于编写线程安全的代码的讨论已经超出本文的范围,更超出了本人的能力范围,大家可以参考Addison Wesley Professional出版的《Java
Concurrency in Practice》)。
接下来,在classes/struts.xml中配置Action,内容如下:
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<includefile="struts-default.xml"/>
<packagename="Struts2_IoC"extends="struts-default">
<actionname="Chat"class="chatAction">
<result>/UserList.jsp</result>
</action>
</package>
</struts>
清单7 classes\struts.xml
这里的Action和平常不同的就是class属性,它对应于Spring所定义的bean的id,而不是它的类全名。
最后,让我们看看/UserList.jsp,内容如下:
<%@ page contentType="text/html;
charset=UTF-8"%>
<%@ taglib prefix="s"uri="/struts-tags"%>
<html>
<head>
<title>User List</title>
</head>
<body>
<h2>User List</h2>
<ol>
<s:iteratorvalue="userNames">
<li><s:property/></li>
</s:iterator>
</ol>
</body>
</html>
清单8 /UserList.jsp
大功告成,分布运行应用程序,在浏览器中键入http://localhost:8080/Struts2_IoC/Chat.action,出现如图2所示页面:
图2 /ListUser.jsp
总结
通过Spring在Struts 2上实现控制反转是强烈推荐的做法,当然您也可以组合其它的实现(如Pico等)相关文章推荐
- JAVA正则表达式 Pattern和Matcher
- JAVA正则表达式:Pattern类与Matcher类详解
- spring错误提示:nested exception is org.xml.sax.SAXParseException; lineNumber: 10; columnNum原因
- Java学习(3)Java语言的环境搭建
- Spring Mvc那点事---(8)Spring Mvc @Resource注解
- Java 多线程
- 全方位剖析Set
- struts2入门-第一个例子==》第一个struts2实例——HelloWorld==》Struts2.0搭建和简单实例==>写一个Steuts2的经典入门案例,做了一个登陆程序作为入门例子
- Java学习基础(2)
- java中Math的一些用法
- retrofit2、RxJava简单使用总结
- Java学习基础(1)
- 处理 eclipse 导入报错 Invalid project description,问题
- Spring-bean作用域scope详解
- 单例模式—java实现
- JDK源码学习(6)-ConcurrentHashMap代码学习
- 清除Eclipse和Myeclipse中的工作空间目录
- 给Java新手的一些建议----Java知识点归纳(J2EE and Web 部分)
- Spring_Spring常见错误_error at ::0 can't find referenced pointcut解决办法
- Eclipse+NDK 环境配置