方式一:Controller方法参数
@GetMapping("/test")
public void test(HttpServletRequest request) {}
方式二:通过RequestContextHolder手动获取
@GetMapping("/test")
public void test(HttpServletRequest request) {
// 从请求上下文里获取Request对象
ServletRequestAttributes requestAttributes = ServletRequestAttributes.class.
cast(RequestContextHolder.getRequestAttributes());
HttpServletRequest contextRequest = requestAttributes.getRequest();
或者
HttpServletRequest request = ((ServletRequestAttributes)
(RequestContextHolder.currentRequestAttributes())).getRequest();
}
RequestContextHolder内部是使用ThreadLocal来维护Request的,线程间隔离,所以不存在线程安全问题,这样使用是没有问题的。
方式三:自动注入@Autowired
@Autowired
HttpServletRequest httpServletRequest;
@GetMapping("/hello")
public String hello() {
return "hello:" + simpleDateFormat.format(new Date());
}
tomcat是多线线程的,通过@Autowired注入的Request对象虽然看起是一个全局的共享变量,但是它实际上却是线程安全的。Spring底层通过一个代理对象让客户端去操作了ThreadLocal中的request,即每个线程都只操作自己的request,是线程隔离的,所以也就不存在并发安全问题了。
参考:
从Spring源码分析@Autowired注入的request是否线程安全_程序员小潘的博客-CSDN博客_autowired 线程安全