首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

由Spring管理的Struts2的Action的单实例有关问题

2012-10-10 
由Spring管理的Struts2的Action的单实例问题背景?:1)?Struts2?会对每一个请求,产生一个Action的实例来处理

由Spring管理的Struts2的Action的单实例问题

背景?:


1)?Struts2?会对每一个请求,产生一个Action的实例来处理.

2) Spring的Ioc容器管理的bean默认是单实例的.


当Struts2与Spring整合后,由spring来管理Struts2的Action,会遇到什么问题??如何解决??

----------------------------


会遇到什么问题?


Struts2与Spring整合后,由spring来管理Struts2的Action,? bean默认是单实例有情况下,会有如下问题:

1) Action是单例,其中的FieldError,actionerror中的错误信息 会累加, 即使再次输入了正确的信息,也过不了验证.

2)?Struts2的Action是有状态的,他有自己的成员属性, 所以在多线程下,会有问题.


----------------------------

?

如何解决?


方案一: 就是不用单例, spring中bean的作用域设为prototype,每个请求对应一个实例.

或者取消单例模式,如配置文件修改为(Spring版本的不同,在DTD文件约束也不同):

方案二: spring中bean的作用域设为session ,每个session对应一个实例,解决了多线程问题.

?

<bean id="authgroupact" singleton="false">        <property name="ibser">            <ref bean="ibser" />        </property>    </bean>
?

再写一个拦截器,? 清空FieldError与actionerror

?

public class ClearFieldErrorInterceptor extends AbstractInterceptor {     @Override  public String intercept(ActionInvocation invocation) throws Exception {   ActionSupport actionSupport = (ActionSupport)invocation.getAction();   actionSupport.clearErrorsAndMessages();   String resultCode = invocation.invoke();   return resultCode;   }   

?

?

总结?:

?

方案一 ,bean的作用域设为prototype,? 担心性能不好, 但没实际测试过,不好说话,也只是担心而已.


方案二:? 由于对方案一有担心, 所有才有了方案二, 不知比方案一性能 能高多少


我们知道在Struts中Action是从map中拿出来的,是单实例的。那么在多线程调用的时候会出问题。

那么在Spring中通过getBean方法每调用一次,spring都会new一个实例给我们,所以可以利用这一点把Struts中action的创建交给Spring来处理。

Spring Bean的作用域:

Bean作用域

作用域描述

singleton

在每个Spring IoC容器中一个bean定义对应一个对象实例。

prototype

一个bean定义对应多个对象实例。

request

在一次HTTP请求中,一个bean定义对应一个实例;即每次HTTP请求将会有各自的bean实例, 它们依据某个bean定义创建而成。该作用域仅在基于web的Spring ApplicationContext情形下有效。

session

在一个HTTP Session中,一个bean定义对应一个实例。该作用域仅在基于web的Spring ApplicationContext情形下有效。

global session

在一个全局的HTTP Session中,一个bean定义对应一个实例。典型情况下,仅在使用portlet context的时候有效。该作用域仅在基于web的Spring ApplicationContext情形下有效。

继续之前先回顾一下==与equals的用法

我们说==比较的是两个对象的地址,而equals比较的是两个对象的内容。所以

String s1 = new String("sfsf");
String s2 = new String("sfsf");
System.out.println(s1==s2);
System.out.println(s1.equals(s2));

?上面打印的结果为:

false
true

?

说明:s1,s2分别在栈中分配内存,即两个局部变量。那么他们的值存放的是地址。

new String的时候会在堆中分配对象的空间,显然调用了两次new分配了两个对象的地址。所以s1与s2的值即地址是不一样的,所以s1==s2返回为false.

而s1.equals(s2)比较的是两个对象的内容,显然对象内容都是sfsf所以返回为true.

?

相关知识如:

String s = new String("xyz");创建了几个String Object

  答:"xyz"本身作为字符常量,在汇编语言中应该作为常量放在数据段,Java有一个类似数据段的constant pool保存这个常量,在classloader加载这个类的时候就把"xyz"和这个类的其他一些信息放在constant pool new String("xyz")根据常量"xyz"在heap上创建String对象所以,一共两个对象
String(String original) Initializes a newly created String object so that it represents the same sequence of characters as the argument; in other words, the newly created string is a copy of the argument string.

?

那么现在我们对从spring得到的对象进行测试。

?

测试代码:

package com.lwf.bean;

public class Bean1 {

}

?配置文件:

<?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.5.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsdhttp://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"><bean id="bean1" scope="prototype"></bean>

?

测试上面代码:

结果为:

2010-05-19 16:05:47,353 INFO [org.springframework.context.support.ClassPathXmlApplicationContext] - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@1c78e57: display name [org.springframework.context.support.ClassPathXmlApplicationContext@1c78e57]; startup date [Wed May 19 16:05:47 CST 2010]; root of context hierarchy
2010-05-19 16:05:47,524 INFO [org.springframework.beans.factory.xml.XmlBeanDefinitionReader] - Loading XML bean definitions from file [D:\workdirlocal\SpringBean\bin\applicationContext.xml]
2010-05-19 16:05:47,899 INFO [org.springframework.context.support.ClassPathXmlApplicationContext] - Bean factory for application context [org.springframework.context.support.ClassPathXmlApplicationContext@1c78e57]: org.springframework.beans.factory.support.DefaultListableBeanFactory@80fa6f
2010-05-19 16:05:47,931 INFO [org.springframework.beans.factory.support.DefaultListableBeanFactory] - Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@80fa6f: defining beans [bean1]; root of factory hierarchy
false
false

?

可以看到返回为false,false即每次创建的实例是不同的。我们在使用这一特性解决struts action单实例时就要这样配置。

?

Prototype作用域的bean会导致在每次对该bean请求(将其注入到另一个bean中,或者以程序的方式调用容器的getBean()方法)时都会创建一个新的bean实例。根据经验,对有状态的bean应该使用prototype作用域,而对无状态的bean则应该使用singleton作用域。

1 楼 瞬息万变 2012-04-20   讲的挺好的,实用。 2 楼 dmy110 2012-08-25   貌似如果不需要使用spring的其他AOP功能的话,可以不使用spring来管理action.至于action中需要注入的依赖,会通过autowired自动注入.

When an object is to be created, it uses the class attribute in the Struts configuration to correspond to the id attribute in the Spring configuration. If not found, the class will try to be created as usual, then be autowired by Spring.
这是struts2-spring plugin中的介绍.

热点排行