zoukankan      html  css  js  c++  java
  • SpringMvc中获取Request

    Controller中加参数

    @Controller
    public class TestController {
        @RequestMapping("/test")
        public void test(HttpServletRequest request) {
            ......
        }
    }

    Controller中获取request对象后,如果要在其他方法中(如service方法、工具类方法等)使用request对象,需要在调用这些方法时将request对象作为参数传入

    此时request对象是方法参数,相当于局部变量,毫无疑问是线程安全的。 

    自动注入

    @Controller
    public class TestController{
         
        @Autowired
        private HttpServletRequest request; //自动注入request
         
        @RequestMapping("/test")
        public void test() throws InterruptedException{
            ......
        }
    }

    使用这种方式,当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对象的线程安全性。

    基类中自动注入

    public class BaseController {
        @Autowired
        protected HttpServletRequest request;     
    }
    @Controller
    public class TestController extends BaseController {
    }

    与方法2相比,避免了在不同的Controller中重复注入request;但是考虑到java只允许继承一个基类,所以如果Controller需要继承其他类时,该方法便不再好用。

    手动调用

    @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的一个域,无法保证线程安全。

  • 相关阅读:
    在百度搜索"2012世界末日"所展现的地震效果的源代码
    java笔记:熟练掌握线程技术基础篇之解决资源共享的问题(中)下篇
    系统设计与架构笔记:ETL工具开发和设计的建议
    java笔记:熟练掌握线程技术基础篇之线程的协作和死锁的问题(下)
    java笔记:关于复杂数据存储的问题基础篇:数组以及浅拷贝与深拷贝的问题(上)
    java笔记:熟练掌握线程技术基础篇之解决资源共享的问题(中)中篇
    用javascript写的小键盘
    系统设计与架构笔记:对我新公司网站的技术架构初解
    java笔记:关于复杂数据存储的问题基础篇:数组以及浅拷贝与深拷贝的问题(下)
    使用 jQuery,第 1 部分: 将桌面应用程序引入浏览器
  • 原文地址:https://www.cnblogs.com/wade-luffy/p/8867144.html
Copyright © 2011-2022 走看看