1.Springboot线程安全性
默认下Springboot注入的对象都是单例的,对于全局的共享变量它是线程不安全的。
- springboot 和spring一样,默认采用的是单例模式。
- 若每个线程中对静态变量(类变量)、实例变量(对象变量)只有读操作,而无写操作,一般来说,这个全局变量是线程安全的。
- 若有多个线程同时执行写操作,一般都需要考虑线程同步,否则就可能影响线程安全。
2.如果保证Springboot线程安全性
Spring本身并没有解决并发访问的问题。如果bean的范围不是线程安全的(例如定义在controller中的成员变量或者静态变量就是线程不安全的),但其方法包含一些您总是希望安全运行的关键代码或者使用了静态字段需要对其进行并发修改。
- 可以在该方法上使用synchronized关键字。
- 使用一些有提供线程安全的集合进行相应的多线程操作(ConcurrentHashMap,CopyOnWriteArrayList,CopyOnWriteArraySet或者java.util.concurrent包下的集合)
- 使用private ThreadLocal<Company> tc = new ThreadLocal<>()方式创建对象。
3.HttpServletRequest 安全性
HttpServletRequest 本身不是线程安全的的,但是可以通过一些办法让它是线程安全的。
1. 使用 @Autowired 注入 HttpServletRequest
虽然 @Autowired 注入的 HttpServletRequest 在 Controller 中是线程安全的,但建议不要将其作为类的成员变量使用,而是应该在方法参数中使用,这样可以确保每次请求都有一个新的 HttpServletRequest 对象
2. 使用 RequestContextHolder:可以通过 RequestContextHolder.getCurrentRequest() 获取当前的 HttpServletRequest 对象。这种方式可以确保每次获取的都是当前请求的 HttpServletRequest 对象,从而避免线程安全问题
ServletRequestAttributes requestAttributes = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes());
HttpServletRequest httpServletRequest = requestAttributes.getRequest();
HttpServletResponse httpServletResponse = requestAttributes.getResponse();
3.使用 ThreadLocal:可以将 HttpServletRequest 封装在一个 ThreadLocal 变量中,这样每个线程都会有自己的 HttpServletRequest 副本,从而避免线程安全问题
参考: