Answering an old and accepted question here.
comparison
The HttpServletRequest
is one of the supported controller method arguments as specified in the Spring Web MVC docs
The @Autowired
way, on which I don't find much on the official sites from my searching results. But many SO answers mention that "Spring stores the HttpServletRequest into a ThreadLocal variable ... it would be injected per thread" based on inspecting the source code.
some inspection I made
The assumption is reasonable, but where is the entry point? I tried printing the runtime class name of the autowired HttpServletRequest
bean:
// ... imports ...
@RestController
@Slf4j
public class K {
@Autowired private HttpServletRequest request;
@GetMapping public ResponseEntity<String> getIt() {
log.info("GET request rt class is {}", request.getClass().getName());
return ResponseEntity.ok("k");
}
}
The output is something like jdk.proxy2.$Proxy77
, right, it's a proxy injected. Then should use Proxy.getInvocationHandler(request).getClass().getName()
. Now the output is org.springframework.beans.factory.support.AutowireUtils$ObjectFactoryDelegatingInvocationHandler
, a private nested class within AutowireUtils, which has a field of type ObjectFactory
. The ObjectFactory
has 16 implementations (you can use an IDE to check it out), the most likely one (by assumption) that gives the ServletRequest
is the private nested class RequestObjectFactory
within WebApplicationContextUtils
:
//...
private static ServletRequestAttributes currentRequestAttributes() {
RequestAttributes requestAttr = RequestContextHolder.currentRequestAttributes();
if (!(requestAttr instanceof ServletRequestAttributes)) {
throw new IllegalStateException("Current request is not a servlet request");
}
return (ServletRequestAttributes) requestAttr;
}
/**
* Factory that exposes the current request object on demand.
*/
@SuppressWarnings("serial")
private static class RequestObjectFactory implements ObjectFactory<ServletRequest>, Serializable {
@Override
public ServletRequest getObject() {
return currentRequestAttributes().getRequest();
}
// ...
}
// ...
As you can see, it comes to the RequestContextHolder
, a Holder class to expose the web request in the form of a thread-bound RequestAttributes
object. Now it makes some sense.
See also