Spring MVC的Controller是线程安全的么
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring MVC的Controller是线程安全的么相关的知识,希望对你有一定的参考价值。
SpringMVC 是基于单例模式的,所以如果有类的实例全局变量,这个会出现问题。但是根据SpringMVC的设计要求,不推荐存在全局变量,出现的类引用也不过是Service层中的对象,这个对象不具备保存请求数据信息的功能,如果有保存信息也直接传入了函数内部。函数内部定义的变量时线程安全的。所以应该是可以放心使用的。SpringMVC和Sturts2设计的不同是请求的信息是否保存才Controller层中。Struts2的Action是需要保存请求信息的。而SpringMVC是不保存的。所以Struts2是用prototype,SpringMVC是singleton。整体来说,SpringMVC的Controller是线程不安全的,但是对设计有规定要求,这样可以避免线程安全问题。不只是Controller,包括Service和Dao都是不安全的。 参考技术A 如果是方法的话,能不能调用还真不知道,没有尝试过。 如果是控制器,可以肯定是不能直接调用的,只能跳转。 如果你需要掉的是方法,请抽离出来,不要放在Controller里面,因为这不符合MVC设计的理念。 如果可以,不是线程安全的。 参考技术B 参考如下内容:
Spring MVC的Controller用的是Servlet的思想,单例性能好,但线程不安全,如果用其它的Scope,性能会下降。
建议用默认单例方式,实现要共享对象属性,可以用ThreadLocal保护。
controller默认是单例的,不要使用非静态的成员变量(service无所谓,因为它不会变),否则会发生数据逻辑混乱。比如a线程将int i=3,b线程将 i = 4,然后a再访问 i 时, i的值为4
事务:事务配置的规律-Spring MVC+ mybatis 环境
事务隔离特性和传播特性
基于上一篇文章,我们使用 Spring MVC+mybatis+mysql 的环境,通过在 Controller 层增加多线程的方式,实验并发环境下事务的传播特性和隔离特性。
注意事项
事务是数据库的特性, 需要数据库开启事务配置,而 mybatis 和 Spring 都可以“接管”具体的事务配置。
对于controller 访问,实际上服务器是按照多线程模式处理的,即两次访问互不影响,但是如果使用同一个浏览器做连续访问,服务器会做出串行访问的处理,造成访问速度下降,而且,当首次访问时间超时的时候,后面的访问会被安排开始执行。所以我们采取 Controller 层增加多线程的方式,运用单例模式共享变量的方式控制多个线程之间访问的事务,以模拟多种事务并发或者传播的规律。
mybatis 有一级缓存默认开启,即同一个Mapper方法在一个事务里执行多次实际上只查询了一次,由于事务是锁定于数据库的数据的,我们可以通过写冗余方法来简单规避这个问题,否则不可重复读就无法出现
一般的事务都是加在 Service 层,本文就直接论述为 Service层配置事务
传播特性的规律
多次调用同一个Service,从传播特性来说,二者的事务相互独立,互相不影响。
分开访问两个不同的Service也是相互独立的,二者的事务相互独立,互相不影响。
事务的传播特性仅在Service调用Service的情况时才需要将两个 Service 合起来考虑,而且是出于调用本Service的来源是否具有事务配置的出发点来考虑的。比如已存在事务则共享,如果没有事务则报错
对于 Service 来说如果存在事务,一旦程序执行失败,或者主动抛出未捕获的异常,事务都会回滚,而且,事务内所有程序要么全部执行并提交,要么全部回滚。
Service1调用了Service2,从传播特性上来说,Service2可以和Service1保持为同一事务,也可以新起事务,也可以不使用事务,也可以检查事务。
事务1调用事务2,如果事务1配置为有事务,事务2配置为和事务1保持为同一事务,则任何一个报异常,两个Service的事务都会回滚,而且,后面的事务可以读取前面事务的未提交数据,即两个Service 之间的隔离特性失效。
隔离特性的规律
一个事务内,隔离特性失效,如果两个Service使用同一个事务,隔离特性就失效了。
两个事务单独访问,读未提交,允许本事务别取其他事务的未提交数据。无法避免脏读、不可重复读、幻读
两个事务单独访问,读已提交,本事务只能读取其他事务已经提交的数据。可以避免脏读,无法避免不可重复读、幻读
两个事务单独访问,可重复读,本事务内重复读取某一条数据结果始终不变,期间允许其他事务对该数据进行修改和删除。可以避免脏读、不可重复读,无法避免幻读
两个事务单独访问,序列化,涉及到本事务操作的数据或者表,只有本事务提交后,其他事务才可以执行,反之,如果其他事务正在执行,本事务需要等待,需要强调的是,序列化并不是完全意义的串行,而是在涉及到表操作的时候串行,其他代码是并行的关系,这算是一种优化吧。序列化设置可以避免脏读、不可重复读和幻读。
对于常规事务配置的建议
对于普通查询
@Transactional(readOnly=true,isolation=Isolation.READ_COMMITTED,
propagation=Propagation.SUPPORTS,rollbackFor=Exception.class)
1
2
对于普通新增或者修改
@Transactional(readOnly=false,isolation=Isolation.READ_COMMITTED,
propagation=Propagation.REQUIRED,rollbackFor=Exception.class)
以上是关于Spring MVC的Controller是线程安全的么的主要内容,如果未能解决你的问题,请参考以下文章
事务:事务配置的规律-Spring MVC+ mybatis 环境