Autowiring Httpservletrequest in Spring Controller

Autowiring HttpServletRequest in Spring controller

if it works that means spring doesn't inject exactly http request but a proxy. the proxy delegates calls to current http request

Spring MVC - Can I autowire HttpServletRequest in RestController

I have used this and it works fine. But unfortunately I did not find any official documentation which mentions that this should work.

Here is the explanation based on my understanding from debugging the code with running multiple requests with different headers/payload etc.:

Whether we autowire on field or through the constructor, servletRequest acts like a Proxy object which delegates the call to Current HttpServletRequest which is different for each request. Thus, even though it's injected through constructor in a Singleton RestController, it will still have the call delegated to corresponding HttpServletRequest for each new request. This utilizes AutowireUtils.ObjectFactoryDelegatingInvocationHandler to access the current HttpServletRequest object. The java doc for it also says Reflective InvocationHandler for lazy access to the current target object.

Thus even if the autowired Proxy object is always the same for all requests, the underlying target object to which the call is delegated is the current HttpServletRequest object which is per-request.


There is another way you can get HttpServletRequest is using RequestContextHolder as mentioned in this answer

HttpServletRequest currentRequest = 
((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes())
.getRequest();

Note: As this explanation is based on my understanding, please do share any official documentation about this if anyone has it.

@Autowired HttpServletRequest vs passing as parameter - best practice

Both are ok.

@Autowired HttpServletRequest and passing as a parameter are the same things.

Before passing HttpServletRequest to invocation method responding to @RequestMapping function, Spring stores the HttpServletRequest into a ThreadLocal type variable.

That ThreadLocal variable is a thread-safe map that keeps HttpServletRequest in the current thread context. The @Autowired HttpServletRequest proxy bean gets the correct request from that ThreadLocal variable.

Where is autowiring of HttpServletRequest into arbitrary Spring components documented?

That possibility of autowiring the proxy for HttpServletRequest's is a part of Spring MVC, and sadly it's not documented properly.

The best you can find about it is in some release notes of spring-web:3.0.0. For example, take a look at the release notes of 3.0.0.M4 and especially at this issue where Juergen Hoeller (one of the main developers of String) talks about how it works since this version.

Also, feel free to check the sources (WebApplicationContextUtils, RequestContextHolder), they're well documented.

Spring: how do I inject an HttpServletRequest into a request-scoped bean?

Request-scoped beans can be autowired with the request object.

private @Autowired HttpServletRequest request;

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

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.

How to inject current HttpServletRequest into any Spring service?

You can get HttpServletRequest in this way if you don't want to use @Autowired in the controller:

HttpServletRequest request = 
((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes())
.getRequest();

SpringBoot forward request by @Autowired HttpServletRequest result in StackOverFlow Exception

Remove the @Autowired request/response fields and use your request/response parameters.

@GetMapping(path = "forward")
public void forward(
HttpServletRequest request,
HttpServletResponse response,
@RequestParam String name) {
try {
request.getRequestDispatcher ( "/test/hello" )
.forward (request, response);
} catch (ServletException e) {
e.printStackTrace ();
} catch (IOException e) {
e.printStackTrace ();
}
}

The request/response fields injection is causing an odd behavior due to Spring Beans annotated with @Controller has scope singleton by default, therefore each request will be handle by a singleton TestController instance.

Read HttpServletRequest object from Spring Boot controller method

First, remove the @Autowired field. It's wrong and you're not using it anyway.

Now you have two choices:

  1. Let Spring process the request body for you, by using the @RequestBody annotation:

    @PostMapping(path = "/abc")
    public String createAbc(@RequestBody String requestBody) throws IOException {
    logger.info("Request body: " + requestBody);
    return "abc";
    }
  2. Process it yourself, i.e. don't use the @RequestBody annotation:

    @PostMapping(path = "/abc")
    public String createAbc(HttpServletRequest request) throws IOException {
    StringBuilder builder = new StringBuilder();
    try (BufferedReader in = request.getReader()) {
    char[] buf = new char[4096];
    for (int len; (len = in.read(buf)) > 0; )
    builder.append(buf, 0, len);
    }
    String requestBody = builder.toString();
    logger.info("Request body: " + requestBody);
    return "abc";
    }

Don't know why you'd use option 2, but you can if you want.



Related Topics



Leave a reply



Submit