无法理解spring-mvc的`@Autowired HttpServletRequest`

时间:2015-01-19 07:19:20

标签: spring httprequest autowired spring-bean

在我们的spring应用程序中,我们以两种方式使用HttpServletRequest

(这里的代码简洁,似乎毫无意义)

  1. 在控制器中:

    @RequestMapping(value = "/hello", method = RequestMethod.GET)
    @ResponseBody
    public ResponseEntity<String> hello(HttpServletRequest request) {
        System.out.println("## controller req.hashcode: " + request.hashCode());
        System.out.println("## header 'abc': " + request.getHeader("abc"));
        return new ResponseEntity<String>("OK", HttpStatus.OK);
    }
    
  2. 在正常组件中:

    @Component
    class RequestService {
        private final HttpServletRequest request;
        @Autowired
        public RequestService(HttpServletRequest request) {
            this.request = request;
        }
        public String getHeaderAbc() {
            System.out.println("## service req.hashcode: " + request.hashCode());
            return this.request.getHeader("abc");
        }
    }
    
  3. 起初,我认为第二种方式是完全错误的,因为它应该只注入一次request实例。因此,无论何时调用getHeaderAbc()方法,它都应返回相同的值(第一个请求)。

    但是当我尝试它时,我发现了几件有趣的事情:

    1. 控制器中的request.hashCode()始终不同(正如我所料)
    2. request.hashCode()中的RequestService始终相同(我认为)
    3. 但是如果我使用不同的标头abc !!!
    4. 发出请求,则标头值会有所不同

      对于单例RequestService,spring保留request实例,但更改了它包含的标题!

      如何理解?

1 个答案:

答案 0 :(得分:8)

看一下范围代理。 http://www.java-allandsundry.com/2012/08/spring-scoped-proxy.html 基本上,您注入一个代理,该代理保留对当前HttpRequest bean的引用,并为您提供正确的代理,并按请求ID选择它。

恕我直言,在网络层之外使用HttpRequest不是一个好习惯。我只会在控制者中使用它。