11 回答
TA贡献1780条经验 获得超5个赞
这么写是线程安全的,原因如下:
在controller中注入的request是jdk动态代理对象,ObjectFactoryDelegatingInvocationHandler的实例.当我们调用成员域request的方法的时候其实是调用了objectFactory的getObject()对象的相关方法.这里的objectFactory是RequestObjectFactory.
RequestObjectFactory的getObject其实是从RequestContextHolder的threadlocal中去取值的.
请求刚进入springmvc的dispatcherServlet的时候会把request相关对象设置到RequestContextHolder的threadlocal中去.
参考: 在SpringMVC Controller中注入Request成员域
TA贡献1802条经验 获得超5个赞
首先,原则上 Request 不可以定义为 Controller 的成员,因为二者的生命周期实在是完全脱节的,这样子弄只会造成 Controller 无法调用到正确的 Request 对象。
其次 @Autowire 是一次性赋值的,而 Request 对象有无数多个,所以你这样写的话,Spring 也会不知该如何是好。因为应用启动的时候根本没有 Request 对象,所以这样应该会导致启动失败。
TA贡献1993条经验 获得超5个赞
第一次见过这种写法,为什么不这样写?
@Controller
public class AController{
@RequestMapping("/test")
public Result test(HttpServletRequest request){
System.out.println(request.toString());
request.getHeader("uid");
}
}
实际上在大部分情况下,request都不用作为参数传过来的,比如你想拿到请求头中的uid,可以这样写:
@Controller
public class AController{
@RequestMapping("/test")
public Result test(@RequestHeader("uid") String uid) {
System.out.println(uid); // 相当于request.getHeader("uid")
}
}
20180613补充2年前的回答:
上面的回答没有直接回答题主提出的问题,所以算是不正确的回答。下面补充回答一下:
题主给的这种方式是线程安全的!!这种做法是完全没问题的。
@Autowire
HttpServletRequest request;
首先,Controller的确是单实例的,如果请求并发高会不会导致多个线程用到同一个请求的HttpServletRequest对象?答案是不会的。
实际上Autowire进来的并不是原始的HttpServletRequest对象,而是HttpServletRequest的一个代理类。实际上它会通过
((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest()
这样的方式来获取真正的Request对象。而RequestContextHolder是通过ThreadLocal来实现的,可以保证每个线程获取得到的Request对象一定是当前请求的Request对象,从而保证线程安全。
TA贡献1863条经验 获得超2个赞
任何类实例变量都有潜在的线程安全的风险,代码需要确保该实例变量在多线程下没问题,或者确保该类同时只有一个线程访问。
你这个例子多线程的问题是必然的,你还是根据Spring的教程按照标准的写法写,先把事情搞对了,理解了,然后再搞复杂的。
TA贡献1811条经验 获得超6个赞
httpRequestServlet本来就不是类属性,而是线程变量,所以我认为最好的使用方式是用RequestContextHolder. currentRequestAttributes()来取。
添加回答
举报