Can't understand `@Autowired HttpServletRequest` of spring-mvc well

筅森魡賤 提交于 2019-12-05 00:19:09


In our spring application, we use HttpServletRequest in two ways:

(the code here are simplied, and seems meaningless)

  1. In the controller:

    @RequestMapping(value = "/hello", method = RequestMethod.GET)
    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. In a normal component:

    class RequestService {
        private final HttpServletRequest request;
        public RequestService(HttpServletRequest request) {
            this.request = request;
        public String getHeaderAbc() {
            System.out.println("## service req.hashcode: " + request.hashCode());
            return this.request.getHeader("abc");

At first, I was thinking the 2nd way is totally wrong, because it should only inject the request instance once. So no matter when I invoke getHeaderAbc() method, it should return the same value(of the first request).

But when I try it, I found several interesting things:

  1. The request.hashCode() in controller is always different (as I expected)
  2. The request.hashCode() in RequestService is always the same (as I thought)
  3. But the header value is different if I issue a request with a different header abc !!!

It seems for the singleton RequestService, spring keeps the request instance, but changed the headers it contains!

How to understand it?


Take a look at the scoped proxy. Basically you inject a proxy that keeps a references to the current HttpRequest beans and gives you the right one, selecting it by the request id.

IMHO using HttpRequest outside of the web layer is not a good practice. I would use it only in the controlellrs.