获取当前的请求HttpServletRequest

    技术2022-07-13  90

    1.Controller中加参数 void test(HttpServletRequest request) {...} 2.自动注入 @Autowired private HttpServletRequest request; /* todo 研究 使用这种方式,当Bean(本例的TestController)初始化时,Spring并没有注入一个request对象,而是注入了一个代理(proxy);当Bean中需要使用request对象时,通过该代理获取request对象。request实际上是一个代理:代理的实现参见AutowireUtils的内部类ObjectFactoryDelegatingInvocationHandler。 调用request的方法method时,实际上是调用了由objectFactory.getObject()生成的对象的method方法;objectFactory.getObject()生成的对象才是真正的request对象。 objectFactory的类型为WebApplicationContextUtils的内部类RequestObjectFactory;而RequestObjectFactory要获得request对象需要先调用currentRequestAttributes()方法获得RequestAttributes对象,生成RequestAttributes对象的核心代码在类RequestContextHolder中,生成的RequestAttributes对象是线程局部变量(ThreadLocal),因此request对象也是线程局部变量;这就保证了request对象的线程安全性。 */ 3.加强版的注入, 基类中自动注入!!!!!!!!!!!!!!!!!!!! public class BaseController {//也可以设为抽象类 @Autowired protected HttpServletRequest request; } @Controller public class TestController extends BaseController { } //思考 基类Controller中自动注入request, 配合泛型就可以封装一套所有controller可以直接复用的一堆方法, 最好是能把基类变成接口, 就不会使用掉单继承这个机会 1.只要基类controller注入就行, 避免了所有Controller中重复注入request; 2.但是考虑到java只允许继承一个基类,继承这个机会被用掉了 3. todo 思考继承的替代方法, 用接口可以注入吗, 方法作为default,直接注入静态成员?(静态成员只初始一次, 肯定不行, 那我就用后文提到的方法, 手动调用一个放回request的方法)+默认方法, 或者变为其他设计模式 4.其余情况如下 手动调用 @Controller public class TestController { @RequestMapping("/test") public void test() throws InterruptedException { HttpServletRequest request = ((ServletRequestAttributes(RequestContextHolder.currentRequestAttributes())).getRequest(); ....... } } 通过自动注入实现与通过手动方法调用实现原理差不多。因此本方法也是线程安全的。 优点:可以在非Bean中直接获取。缺点:如果使用的地方较多,代码非常繁琐;因此可以与其他方法配合使用。 @ModelAttribute方法 @Controller public class TestController { private HttpServletRequest request; 此处线程不安全 @ModelAttribute public void bindRequest(HttpServletRequest request) { this.request = request; 此处request线程安全 } @RequestMapping("/test") public void test() throws InterruptedException { ...... } } @ModelAttribute注解用在Controller中修饰方法时,其作用是Controller中的每个@RequestMapping方法执行前,该方法都会执行。bindRequest()的作用是在test()执行前为request对象赋值。虽然bindRequest()中的参数request本身是线程安全的,但由于TestController是单例的,request作为TestController的一个域,无法保证线程安全。//todo 研究一下不安全问题
    Processed: 0.009, SQL: 9