In our spring application, we use HttpServletRequest
in two ways:
(the code here are simplied, and seems meaningless)
In the controller:
@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); }
In a normal component:
@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"); } }
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:
- The
request.hashCode()
in controller is always different (as I expected) - The
request.hashCode()
inRequestService
is always the same (as I thought) - 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. http://www.java-allandsundry.com/2012/08/spring-scoped-proxy.html 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.