一、Spring为什么要整合Struts2
   
Struts2与Spring进行整合的根本目的就是要
Spring为Struts2的Action注入所需的资源对象,
它们整合的原理则是只要导入了struts2的spring插件包,不需要进行
任何额外的配置,Struts2的Action实例对象将由struts2的spring插件创建,该插件会按照Action的属性名称自动从
spring容器中查找相同名称的bean对象对Action进行装配.

显然,Struts2的spring插件需要获得spring容器对象,这个spring容器对象是谁创建出来?Struts2的Spring插件又是如何获得Spring容器的呢?在web开发方面,Spring除了提供自己的spring
mvc这个web框架之外,它也为web开发提供了最基本的支持,以便在不使用spring
mvc的web环境下使用spring,这就是通过
org.springframework.web.context.ContextLoaderListener创建出
WebApplicationContext容器对象,
并将创建出来的WebApplicationContext对象存储进了Web应用程序的application作用域中,存储时的key为
WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE这个常量表示的字符串,以后在Web应用程序中就可以使用
application.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE)
语句, 或Spring提供的工具方法
WebApplicationContextUtils.getWebApplicationContext(application)
来获得
spring容器对象。ContextLoaderListener使用contextConfigLocation这个ServletContext初
始化参数来指定WebApplicationContext容器对象的配置文件,如果没有配置contextConfigLocation这个
ServletContext的初始化参数,ContextLoaderListener则默认使用/WEB-INF
/applicationContext.xml作为配置文件。
为了简便,我们这里采用默认的配置文件,所以,不需要配置contextConfigLocation这个ServletContext的初始化参数,只
需要保证spring配置文件的路径和名称为/WEB-INF/applicationContext.xml即可。

二、整合步骤
 
1、导入struts2的8大核心jar包

  
struts2-core-2.1.6.jar  
xwork-2.1.2.jar 
ognl-2.6.11.jar   
freemarker-2.3.13.jar 
commons-logging-1.1.jar 
commons-fileupload-1.2.1.jar commons-io-2.0.1.jar 
javassist-3.11.0.GA.jar

 说明:strut2的8个核心jar包是使用strut2必须导入的最少jar包

 
2、将struts.xml文件拷贝到src目录下,并配置web.xml
  3、导入Spring的核心jar包
    

spring-core-3.2.0.M2.jar   
spring的核心jar包

commons-logging.jar
  4、初始化Spring容器,有如下两种方式:
   
①利用ContextLoaderListener类,在Web.xml文件中添加:

<!– Spring配置信息加载监听器 Context
Listener,
必要-->
        
<listener>
           
<listener-class>
org.springframework.web.context.ContextLoaderListener
           
</listener-class>
       
</listener>
   
<!-- Spring
防止内存溢出,原因详见:博文底-->
   
<listener>
       
<listener-class>
           
org.springframework.web.util.IntrospectorCleanupListener
       
</listener-class>
   
</listener>
       
该类会在Web启动时自动查找WEB-INF下的applicationContext.xml配置,并且根据该文件来创建Spring容器。当然我们也可以自定义applicationContext.xml的位置,需在web.xml子节点<web-app
>的顶端添加:

    <context-param>
      
<param-name>contextConfigLocation</param-name>

<!-- 此位置相对于:部署后的项目的类路径
。多个文件逗号分隔(因这里用到了Spring-Security)-->
      
<param-value>
classpath:applicationContext.xml,classpath:spring\applicationContext-security.xml

</param-value>
    
<!-- 此位置相对于:部署后的项目的根路径
。多个文件逗号分隔(因这里用到了quartz定时任务框架)-->
   
<param-value>/WEB-INF/applicationContext.xml,/WEB-INF/quartz.xml</param-value>

</context-param>

②如果Web服务器不支持Servlet2.3以上的规范,即不支持Listener利用load-on-startup
Servlet创建ApplicationContext,在Web.xml文件中添加:
       
<servlet>
           
<servlet-name>context</servlet-name>

<servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class>

<load-on-startup>1</load-on-startup>

</servlet>
       
设置该Servlet随Web服务器的启动而启动,load-on-startup的值越小越早调用。但不管该值多小,Listener都比该Servlet更早启动。

因为ContextLoaderServlet与COntextLoaderListener底层都依赖于ContextLoader,因此二者的效果几
乎没有区别。Listener总比所有的Servlet更优先加载,因此,采用ContextLoaderListener创建
ApplicationContext的时机更早。

5、添加spring与struts2整合的插件
   
struts2-spring-plugin-2.1.6.jar(它在strut2框架的jar包中)
 
千万注意:而不是导入spring框架中的spring-struts-3.2.0.M2.jar,否则在strut.xml中无法使用Spring中Bean工厂的Bean了!!!

.jar
的Struts插件,该插件会把Struts自带的ObjectFactory替换为com/opensymphony/xwork2/spring
/SpringObjectFactory,这样所有Action的实例化工作就交给你spring框架,所有的Action既是struts的
action,同时又是spring的bean。在struts的配置中,action的type就不再设置为类型路径,而是bean名称。

 至此整合步骤已完成!!!现在让我们来比较一下整合前后的区别:

整合之前的struts:

<package name="test" extends="strutsTest"
namespace="/">
       
<action name="ActionTest" class="com.test.action.ActionTestAction">

<result
name="input">/ActionTest.jsp</result>

<result name="success"
type="dispatcher">/ActionTest.jsp</result>

</action>
</package>

整合之后的struts:

<package name="test" extends="strutsTest"
namespace="/">
       
<action name="ActionTest" class="actionTestAction">

<result
name="input">/ActionTest.jsp</result>

<result name="success"
type="dispatcher">/ActionTest.jsp</result>

</action>
</package>

这里的class属性actionTestAction就是bean的名称:
<bean id="actionTestAction"
class="com.test.action.ActionTestAction"></bean>

#########################################################
为什么要在web.xml添加如下代码来防止内存泄露呢:
 
  <listener>
       
<listener-class>
           
org.springframework.web.util.IntrospectorCleanupListener
       
</listener-class>
   
</listener>
  
spring的说明如下:
Listener that flushes the JDK's JavaBeans Introspector cache on web
app shutdown. Register this listener in your web.xml to guarantee
proper release of the web application class loader and its loaded
classes.

If the JavaBeans Introspector has been used to analyze application
classes, the system-level Introspector cache will hold a hard
reference to those classes. Consequently, those classes and the web
application class loader will not be garbage-collected on web app
shutdown! This listener performs proper cleanup, to allow for
garbage collection to take effect.

Unfortunately, the only way to clean up the Introspector is to
flush the entire cache, as there is no way to specifically
determine the application's classes referenced there. This will
remove cached introspection results for all other applications in
the server too.

Note that this listener is not necessary when using Spring's beans
infrastructure within the application, as Spring's own
introspection results cache will immediately flush an analyzed
class from the JavaBeans Introspector cache and only hold a cache
within the application's own ClassLoader. Although Spring itself
does not create JDK Introspector leaks, note that this listener
should nevertheless be used in scenarios where the Spring framework
classes themselves reside in a 'common' ClassLoader (such as the
system ClassLoader). In such a scenario, this listener will
properly clean up Spring's introspection cache.

Application classes hardly ever need to use the JavaBeans
Introspector directly, so are normally not the cause of
Introspector resource leaks. Rather, many libraries and frameworks
do not clean up the Introspector: e.g. Struts and Quartz.

Note that a single such Introspector leak will cause the entire web
app class loader to not get garbage collected! This has the
consequence that you will see all the application's static class
resources (like singletons) around after web app shutdown, which is
not the fault of those classes!

This listener should be registered as the first one in web.xml,
before any application listeners such as Spring's
ContextLoaderListener. This allows the listener to take full effect
at the right time of the lifecycle.

其中JavaBeans
Introspector是一个类,位置在Java.bean.Introspector,这个类的用途是发现java类是否符合javaBean规范,也就是这个类是不是javabean。具体用法可以参照jdk文档;

上面的意思就是,如果有的框架或者程序用到了JavaBeans
Introspector了,那么就启用了一个系统级别的缓存,这个缓存会存放一些曾加载并分析过的javabean的引用,当web服务器关闭的时候,
由于这个缓存中存放着这些javabean的引用,所以垃圾回收器不能对web容器中的javaBean对象进行回收,导致内存越来越大。

spring提供的org.springframework.web.util.IntrospectorCleanupListener就解决了这个问题,他会在web服务器停止的时候,清理一下这个Introspector缓存。使那些javabean能被垃圾回收器正确回收。

spring不会出现这种问题,因为spring在加载并分析完一个类之后会马上刷新JavaBeans
Introspector缓存,这样就保证了spring不会出现这种内存泄漏的问题。

但是有很多程序和框架在使用了JavaBeans
Introspector之后,都没有进行清理工作,比如quartz、struts;解决办法很简单,就是上面的那个配置
。这是
因为:对于Web容器来说,最忌讳应用程序私自启动线程,自行进行线程调度,像Quartz这种在web容器内部默认就自己启动了10线程进行异步job
调度的框架本身就是很危险的事情,很容易造成servlet线程资源回收不掉,所以我一向排斥使用quartz。quartz还有一个问题就是不支持
cluster。导致使用quartz的应用都没有办法做群集。

Spring学习6-Spring整合Struts2的更多相关文章

  1. Spring学习(十一)-----Spring使用@Required注解依赖检查

    Spring学习(九)-----Spring依赖检查 bean 配置文件用于确定的特定类型(基本,集合或对象)的所有属性被设置.在大多数情况下,你只需要确保特定属性已经设置但不是所有属性.. 对于这种 ...

  2. Spring学习(六)-----Spring使用@Autowired注解自动装配

    Spring使用@Autowired注解自动装配 在上一篇 Spring学习(三)-----Spring自动装配Beans示例中,它会匹配当前Spring容器任何bean的属性自动装配.在大多数情况下 ...

  3. Spring学习笔记四 整合SSH

    三大框架架构(整合原理) 步骤1:导包 Hibernate包 1.Hibernate包,hibernate/lib/required 2.hibernate/lib/jpa | java persis ...

  4. spring学习 六 spring与mybatis整合

    在mybatis学习中有两种配置文件 :全局配置文件,映射配置文件.mybatis和spring整合,其实就是把mybatis中的全局配置文件的配置内容都变成一个spring容器的一个bean,让sp ...

  5. Spring学习之Spring与Mybatis的两种整合方式

    本机使用IDEA 2020.1.MySql 8.0.19,通过Maven进行构建 环境准备 导入maven依赖包 <dependencies> <dependency> < ...

  6. spring学习07(整合MyBatis)

    10.整合MyBatis 10.1 相关jar包 junit <dependency> <groupId>junit</groupId> <artifactI ...

  7. spring学习(三) ———— spring事务操作

    前面一篇博文讲解了什么是AOP.学会了写AOP的实现,但是并没有实际运用起来,这一篇博文就算是对AOP技术应用的进阶把,重点是事务的处理. --wh 一.jdbcTemplate 什么是JdbcTem ...

  8. spring学习12 -Spring 框架模块以及面试常见问题注解等

    以下为spring常见面试问题: 1.Spring 框架中都用到了哪些设计模式? Spring框架中使用到了大量的设计模式,下面列举了比较有代表性的: 代理模式—在AOP和remoting中被用的比较 ...

  9. Spring学习【Spring概述】

    从本文開始,我们就要一起学习Spring框架,首先不得不说Spring框架是一个优秀的开源框架. 当中採用IoC原理实现的基于Java Beans的配置管理和AOP的思想都是非常值得学习与使用的.以下 ...

  10. Spring学习笔记—Spring之旅

    1.Spring简介     Spring是一个开源框架,最早由Rod Johnson创建,并在<Expert One-on-One:J2EE Design and Development> ...

随机推荐

  1. Android中Intent传值与Bundle传值的区别详解

    Android中Intent传值与Bundle传值的区别详解 举个例子我现在要从A界面跳转到B界面或者C界面   这样的话 我就需要写2个Intent如果你还要涉及的传值的话 你的Intent就要写两 ...

  2. 014医疗项目-模块一:删除用户的功能l

    删除用户的功能我们还是按照:Dao->Service->Action->页面调试这种顺序来写. Dao: 我们使用逆向工程生成的方法就好: SysuserMapper sysuser ...

  3. RelayCommand命令

    原文:http://www.cnblogs.com/xiepeixing/archive/2013/08/13/3255152.html 常用Wpf开发中我们在ViewModel中实现INotifyP ...

  4. Android应用程序窗口(Activity)的窗口对象(Window)的创建过程分析(转)

    在前文中,我们分析了Android应用程序窗口的运行上下文环境的创建过程.由此可知,每一个Activity组件都有一个关联的ContextImpl对象,同时,它还关联有一个Window对象,用来描述一 ...

  5. C++ VS2010 声明没有存储类或类型说明符

    函数外只能定义全局变量或者对象,而不能执行语句及调用函数.

  6. EF实体框架之CodeFirst七

    前面的6篇博客基本把Code First学习的差不多了,今天这篇学习下code first中的并发控制和事务,基本也快学完了,顶多就差数据迁移. 在数据库中也是有锁和事务的概念,在C#中也是存在,当然 ...

  7. C# Winform实现炫酷的透明动画界面

    做过.NET Winform窗体美化的人应该都很熟悉UpdateLayeredWindow吧,UpdateLayeredWindow可以实现窗体的任意透明,效果很好,不会有毛边.不过使用这个API之后 ...

  8. Asp.net MVC 搭建属于自己的框架(一)

    为什么要自己搭框架? 大家伙别急,让我慢慢地告诉你!大家有没有这种感觉,从一家跳槽到另一家公司,公司的框架往往是不相同的,这样你必须就得摒弃原来的,学习新的框架. 问题是你用习惯了一种框架,比如封装的 ...

  9. jquery封装常用方法

    var git = { //true表示格式正确 checkEmail: function (str) { -]{,})(\S*)/g) == null) { return false; } else ...

  10. WPF中资源引用方式汇总

    在WPF应用程序开发中,总是难以记住各种访问资源的方法,遂逐一记下. 先从资源是否编译到程序集分类 一.程序集资源 资源在编译的时候嵌入到程序集中.WPF中的XAML会被编译为BAML,图片等其他资源 ...