Spring整合Struts2 之 深度解析
来源:互联网 发布:新歌2016网络红歌榜 编辑:程序博客网 时间:2024/06/05 00:39
一、启动Spring
对于使用Spring的Web应用,无须手动创建Spring容器,而是通过配置文件声明式的创建Spring容器。在Web应用中创建Spring容器有如下两种方式:
- 直接在web.xml文件中配置创建Spring容器
- 利用ServletContextListener实现
- 采用load-on-startup Servlet实现
- 利用第三方MVC框架的扩展点,创建容器
1.1 在web.xml中利用ServletContextListener监听器
这种方式最常见,为了让Spring容器随Web应用的启动而自动启动,借助于ServletContextListener监听器即可完成,该监听器可以在Web应用启动时回调自定义方法(该方法就可以启动Spring容器)。
Spring提供了一个ContextLoaderListener,该监听器类实现了ServletContextListener接口。该类可以作为Listener使用,它会在创建时自动查找WEB-INF/下的applicationContext.xml文件。因此,如果只有一个配置文件,并且文件名为applicationContext.xml,则只需在web.xml文件中增加如下配置片段即可:
<listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener>如果有多个配置文件需要载入,则需要使用<context-param.../>元素来确定配置文件的文件名。ContextLoaderListener加载时,会查找名为contextConfigLocation的初始化参数。因此,配置<context-param.../>时应制定参数名为contextConfigLocation。如下:
<!-- 指定多个配置文件 --><context-param><!-- 参数名为contextConfigLocation --><param-name>contextConfigLocation</param-name><!-- 多个配置文件之间以","隔开 --><param-value>WEB-INF/SpringConfig/*.xml,/WEB-INF/A.xml,/WEB-INF/applicationContext.xml</param-value></context-param><listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener>注意:如果没有用contextConfigLocation制定配置文件,则Spring会自动查找WEB-INF/路径下的applicationContext.xml配置文件;如果有contextConfigLocation,则使用该参数确定的配置文件。如果无法找到合适的配置文件,Spring将无法正常初始化。
Spring根据指定的配置文件创建WebApplicationContext对象,并将其保存在Web应用的ServletContext中。在大部分情况下,应用中的Bean无须感受到ApplicationContext的存在,只要利用ApplicationContext的IoC即可。如果需要在应用中获取ApplicationContext实例,则可以通过如下代码获取:
// 获取当前Web应用启动的Spring容器WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(ServletContex);当然也可以通过ServletContext的getAttribute方法获取ApplicationContext,但是用WebApplicationContextUtils类更方便。
1.2 采用load-on-startup Servlet机制
- load-on-startup元素标记容器是否在启动的时候就加载这个servlet(实例化并调用其init()方法)
- 它的值必须是一个整数,表示servlet应该被载入的顺序。当值为0或者大于0时,表示容器在应用启动时就加载并初始化这个servlet
- 当值小于0或者没有指定时,则表示容器在该servlet被选择时才会去加载
- 正数的值越小,该servlet的优先级越高,应用启动时就越先加载
- 当值相同时,容器就会自己选择顺序来加载
- <load-on-startup>x</load-on-startup>中x的取值1,2,3,4,5代表的是优先级,而非启动延迟时间。
<servlet> <servlet-name>context</servlet-name> <servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class> <load-on-startup>1</load-on-startup></servlet>
1.3 利用第三方MVC框架的扩展点
Struts有一个扩展点PlugIn,spring正是利用了PlugIn这个扩展点,从而提供了与Struts的整合。spring提供了PlugIn的实现类org.springframework.web.struts.ContextLoadPlugIn,这个实现类可作为struts的PlugIn配置,Struts框架启动时,将自动创建Spring容器为了利用struts的PlugIn创建Spring容器,只需要在struts配置文件struts-config.xml中增加如下片段即可:<plug-in className="org.springframework.web.struts.ContextLoaderPlugIn"> <set-property property="contextConfigLocation" value="/WEB-INF/applicationContext.xml,/WEB-INF/action-servlet.xml" /> </plug-in>其中,指定contextConfigLocation属性值时,即可以指定一个spring配置文件的位置,可以指定多个spring配置文件的位置。
二、MVC框架与Spring整合
控制器应该如何获得业务逻辑组件?在实际开发中,很少采用new关键字来创建业务逻辑组件,然后调用业务逻辑组件的方法,原因如下:
- 控制器直接创建业务逻辑组件,导致控制器和业务逻辑组件的耦合降低到代码层次,不利于高层次解耦
- 控制器不应该负责业务逻辑组件的创建,控制器只是业务逻辑组件的使用者,无须关心业务逻辑组件的实现
- 每次创建新的业务逻辑组件将导致性能下降
对于轻量级的JavaEE应用,工厂模式则是更实际的策略。因为在轻量级的JavaEE中,业务逻辑组件不是EJB,通常就是一个POJO,业务逻辑组件的生成通常应由工厂负责,而且工厂可以保证该组件的实例只需要一个就够了,可以避免重复实例化造成的系统开销。
采用工厂模式,将控制器与业务逻辑组件的实现分离,从而提供更好的解耦。在采用工厂模式的访问策略中,所有的业务逻辑组件的创建由工厂负责,业务逻辑组件的运行也由工厂负责,而控制器只需要定位工厂实例即可,而采用Spring框架,则Spring称为最大的工厂。
为了让Action访问到Spring的业务逻辑组件,有两种策略:
- Spring容器负责管理控制器Action,并利用依赖注入为控制器注入业务逻辑组件
- 利用Spring的自动装配,Action将会自动从Spring容器中获取所需的业务逻辑组件
2.1 让Spring管理控制器
让Spring容器来管理应用中的控制器,可以充分利用Spring的IoC特性,但需要将配置Struts2的控制器部署在Spring容器中,因此导致配置文件冗余。Struts2提供的Spring插件提供了一种伪Action,在struts.xml文件中配置Action时,指定class属性时,不再指定Action的实际实际类,而是指定为Spring容器中的Bean ID,这样Struts2不再自己负责创建Action实例,而是直接通过Spring容器去获取Action对象。
代码示例详见:codes\08\8.7\spring-manage-action
注意:当Spring管理Struts2的Action时,一定要配置scope属性,因为Action里包含了请求的状态信息,必须为每个请求对应一个Action,所以不能将该Action实例配置成singleton行为,指定scope属性为prototype或request。
部署项目后,再启动过程中会有如下显示:
四月 05, 2017 2:50:18 下午 org.apache.struts2.spring.StrutsSpringObjectFactory info信息: Initializing Struts-Spring integration...四月 05, 2017 2:50:18 下午 com.opensymphony.xwork2.spring.SpringObjectFactory info信息: Setting autowire strategy to name四月 05, 2017 2:50:18 下午 org.apache.struts2.spring.StrutsSpringObjectFactory info信息: ... initialized Struts-Spring integration successfully很简单,Struts-Spring集成初始化——>指定自动装配策略为byname——>Struts-Spring集成初始化成功
2.2 使用自动装配
在自动装配下,Action还是由Spring插件创建,Spring插件在创建Action实例时,利用Spring的自动装配策略,将对应的业务逻辑组件注入Action实例中。这种整合配置策略的配置文件简单,但控制器和业务逻辑组件耦合又提升到了代码层次,耦合较高。如果不指定自动装配,则系统默认使用byName自动装配,如上。所谓自动装配,即让Spring自动管理Bean与Bean之间的依赖关系,无须使用ref显式指定依赖Bean。Spring容器会自动检查XML配置文件的内容,为主调Bean注入依赖Bean。自动装配可以减少配置文件的工作量,但会降低依赖关系的透明性和清晰性。
通过使用自动装配,可以让Spring插件自动将业务逻辑组件注入Struts2的Action实例中。通过设置struts.objectFactFactory.spring.autoWrite常量可以改变Spring插件的自动装配策略,该常量可以接受如下几个值:
- name:使用byName自动装配(默认值)
- type:使用byType自动装配
- auto:Spring插件会自动检测需要时使用哪种自动装配方式
- constructor:与type类似,区别是constructor使用构造器来构造注入所需的参数,而不是使用设值注入方式
示例代码采用的是byName自动装配策略(默认值),而Struts2的配置文件与原来相同,Action的class属性指定实现类来创建Action实例,而使用Spring进行依赖注入,注入时采用的byName方式,因此只需要将Bean的ID与注入元素的名称一样,就可以进行自动注入了。
注意:整合Spring框架与不整合时当然存在区别,只是这个区别不在这个配置文件中体现,而是在创建该Action实例时体现出来的。如果不整合Spring框架,则Struts2框架负责创建Action实例,创建成功后就结束了;如果整合Spring框架,则当Action实例创建完成后,Spring插件还会负责将Action所需的业务逻辑组件注入给该Action实例。
这种方式的缺点:
- Action与业务逻辑组件的耦合低到代码层次,必须在配置文件中配置与Action所需控制器同名的业务逻辑组件。这不利于高层次解耦。
- Action接收Spring容器的自动装配,代码的可读性较差
《轻量级JavaEE企业应用实战 第四版》
************************************************************************结束语************************************************************************
我在写这篇博客的时候也是一名初学者,有任何疑问或问题请留言,或发邮件也可以,邮箱为:fanxiaobin.fxb@qq.com,我会尽早的进行更正及更改。
在我写过的博客中有两篇博客是对资源的整理,可能对大家都有帮助,大家有兴趣的话可以看看!!
下载资料整理——目录:http://blog.csdn.net/fanxiaobin577328725/article/details/51894331
这篇博客里面是我关于我见到的感觉不错的好资源的整理,里面包含了书籍及源代码以及个人搜索的一些资源,如果有兴趣的可以看看,我会一直对其进行更新和添加。
优秀的文章&优秀的学习网站之收集手册:http://blog.csdn.net/fanxiaobin577328725/article/details/52753638
这篇博客里面是我对于我读过的,并且感觉有意义的文章的收集整理,纯粹的个人爱好,大家感觉有兴趣的可以阅读一下,我也会时常的对其进行更新。
************************************************************************感谢************************************************************************
- Spring整合Struts2 之 深度解析
- Spring整合Struts2之启动Spring容器
- spring学习之---spring整合struts2
- 深度解析struts2结果类型之chain
- spring struts2整合之action产生问题
- struts2学习笔记之spring整合
- Struts2+Spring3+Hibernate4整合之Spring配置文件
- 框架整合之Spring + Struts2 + MyBatis
- SSH之IDEA2017整合Struts2+Spring+Hibernate
- spring整合struts2之web.xml配置
- SSH之IDEA2017整合Struts2+Spring+Hibernate
- Spring -- spring整合struts2
- Spring:Spring整合Struts2
- 【Spring】Spring整合Struts2
- SSH框架整合之Struts2和Spring整合
- 《struts2权威指南》学习笔记之struts2整合Spring
- spring整合struts2时作用域scope解析
- Spring+Struts2+Hibernate三大框架整合常见问题解析
- MongoDB:将Json数据直接写入MongoDB的方法
- Python标准库
- 高性能的内核 Socket 实现 Fastsocket
- Mac下安装mysql5.7 完整步骤
- 基础练习 时间转换
- Spring整合Struts2 之 深度解析
- 测试内容(水杯为例)
- 邮票分你一半
- Android TelephonyManager类
- Java 抽象类的使用 接口的使用, 区别等
- NYOJ-21 三个水杯(BFS)
- Turla黑客团体继续改进其Carbon后门
- 【codeforce】C. Functions again 最大子段和
- 从ad_type.json文件获取动态option