首页 文章资讯内容详情

Springmvc 并发访问的线程安全性问题

2026-06-01 2 花语

本文内容纲要:

-第一部分:验证Spring生成对象默认是单例的。 -第二部分:SpringMVC和Struts2中是并发访问否会存在线程安全问题。 -第三部分:springMVC与struts2的区别。 -第四部分:那么对于Struts2+Spring来管理注入的时候呢?

首先对于spring的IOC来说,对象是由Spring来帮我们管理,也就是在Spring启动的时候,在Spring容器中,由Spring给我们创建的,Spring会帮我们维护,一般都是单例的,也就是一个对象。

spring生成对象默认是单例的。通过scope属性可以更改为多例。

第一部分:验证Spring生成对象默认是单例的。

下面我们来一个网上的例子验证一下:

[html]viewplaincopyprint?

[java]viewplaincopyprint?

packagetest; importjava.util.Date; importorg.springframework.context.ApplicationContext; importorg.springframework.context.support.ClassPathXmlApplicationContext; importcom.opensymphony.xwork2.ActionContext; publicclassTestScope{ publicstaticvoidmain(String[]args){ ApplicationContextcontext=newClassPathXmlApplicationContext("applicationContext-web.xml"); Dates1=(Date)context.getBean("singleton"); Datep1=(Date)context.getBean("prototype"); Dates2=(Date)context.getBean("singleton"); Datep2=(Date)context.getBean("prototype"); System.out.println("单例:"+(s1==s2)); System.out.println("非单例:"+(p1==p2)); } }

输出结果:

结果

单例:true

非单例:false

注:复合数据类型的“==”对比的是内存中存放的地址,所以此处我们采用“==”去对比

因为object中的equals初始行为是比较内存中的地址,但在一些类库中被覆盖掉了如(String,Integer,Date等)

第二部分:SpringMVC和Struts2中是并发访问否会存在线程安全问题。

对于使用过SpringMVC和Struts2的人来说,大家都知道SpringMVC是基于方法的拦截,而Struts2是基于类的拦截。

对于Struts2来说,因为每次处理一个请求,struts就会实例化一个对象;这样就不会有线程安全的问题了;

而Spring的controller默认是Singleton的,这意味着每一个request过来,系统都会用原有的instance去处理,这样导致两个结果:

一是我们不用每次创建Controller,二是减少了对象创建和垃圾收集的时间;由于只有一个Controller的instance,当多个线程调用它的时候,它里面的instance变量就不是线程安全的了,会发生窜数据的问题。

当然大多数情况下,我们根本不需要考虑线程安全的问题,比如dao,service等,除非在bean中声明了实例变量。因此,我们在使用springmvc的contrller时,应避免在controller中定义实例变量。

如:

[java]viewplaincopyprint?

publicclassControllerextendsAbstractCommandController{ protectedCompanycompany; protectedModelAndViewhandle(HttpServletRequestrequest,HttpServletResponseresponse,Objectcommand,BindExceptionerrors)throwsException{ company=................; } }

解决方案:

有几种解决方法:

1、在Controller中使用ThreadLocal变量

2、在spring配置文件Controller中声明scope="prototype",每次都创建新的controller

所在在使用spring开发web时要注意,默认Controller、Dao、Service都是单例的。

例如:

[java]viewplaincopyprint?

@Controller @RequestMapping("/fui") publicclassFuiControllerextendsSpringController{ //这么定义的话就是单例 @Controller @Scope("prototype") @RequestMapping("/fui") publicclassFuiControllerextendsSpringController{ //每次都创建

第三部分:springMVC与struts2的区别。

下面是从网络上摘抄的一段对比,大家可以看看

点击打开链接

机制:springmvc的入口是servlet,而struts2是filter,这样就导致了二者的机制不同。

性能:spring会稍微比struts快。springmvc是基于方法的设计,而sturts是基于类,每次发一次请求都会实例一个action,每个action都会被注入属性,而spring基于方法,粒度更细,但要小心把握像在servlet控制数据一样。spring3mvc是方法级别的拦截,拦截到方法后根据参数上的注解,把request数据注入进去,在spring3mvc中,一个方法对应一个request上下文。而struts2框架是类级别的拦截,每次来了请求就创建一个Action,然后调用settergetter方法把request中的数据注入;struts2实际上是通过settergetter方法与request打交道的;struts2中,一个Action对象对应一个request上下文。

参数传递:struts是在接受参数的时候,可以用属性来接受参数,这就说明参数是让多个方法共享的。

设计思想上:struts更加符合oop的编程思想,spring就比较谨慎,在servlet上扩展。

intercepter的实现机制:struts有以自己的interceptor机制,springmvc用的是独立的AOP方式。这样导致struts的配置文件量还是比springmvc大,虽然struts的配置能继承,所以我觉得论使用上来讲,springmvc使用更加简洁,开发效率SpringMVC确实比struts2高。springmvc是方法级别的拦截,一个方法对应一个request上下文,而方法同时又跟一个url对应,所以说从架构本身上spring3mvc就容易实现restfulurl。struts2是类级别的拦截,一个类对应一个request上下文;实现restfulurl要费劲,因为struts2action的一个方法可以对应一个url;而其类属性却被所有方法共享,这也就无法用注解或其他方式标识其所属方法了。spring3mvc的方法之间基本上独立的,独享requestresponse数据,请求数据通过参数获取,处理结果通过ModelMap交回给框架方法之间不共享变量,而struts2搞的就比较乱,虽然方法之间也是独立的,但其所有Action变量是共享的,这不会影响程序运行,却给我们编码,读程序时带来麻烦。

另外,spring3mvc的验证也是一个亮点,支持JSR303,处理ajax的请求更是方便,只需一个注解@ResponseBody,然后直接返回响应文本即可。

总结:

这样也说明了SpringMVC还有Servlet都是方法的线程安全,所以在类方法声明的私有或者公有变量不是线程安全的,而struts2的确实是线程安全的。

第四部分:那么对于Struts2+Spring来管理注入的时候呢?

Struts2它是多实例的,对于每个请求都会生成1个实例,spring默认是单实例的(下面针对Struts与Spring集成的两种方式分别来介绍struts2和spring的两种整合方式)

一:对于无Spring插件(Struts2-spring-plugin-XXX.jar)的整合方式,需要在spring的actionBean中加业务逻辑控制器类配scope="prototype"。

[java]viewplaincopyprint?

二:对于有Spring插件(Struts2-spring-plugin-XXX.jar)的整合方式:反编译StrutsSpringObjectFactory以及相关的代码才发现,如果在strutsaction的配置文件中中class写的如果是完整的包名和类名的话就是struts创建action对象,也就是多实例的;

总结:如果是spring配置文件中的bean的名字的话就是spring创建,那么单实例还是多实例就由spring的actionBean中的业务逻辑控制器类是否配置为scope=”prototype”,有就是多实例的,没有就是单实例的,顺序是先从spring中找,找不到再从struts配置文件中找。

转自:http://blog.csdn.net/hejingyuan6/article/details/50363647

本文内容总结:第一部分:验证Spring生成对象默认是单例的。,第二部分:SpringMVC和Struts2中是并发访问否会存在线程安全问题。,第三部分:springMVC与struts2的区别。,第四部分:那么对于Struts2+Spring来管理注入的时候呢?,

原文链接:https://www.cnblogs.com/AmbitiousMice/p/5955700.html