0
votes

Code:

package com.test.controllers;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.util.concurrent.TimeUnit;

@RestController
@RequestMapping("/")
public class Controller {
    private HttpServletRequest request;

    public HttpServletRequest getRequest() {
        return request;
    }
    @Autowired
    public void setRequest(HttpServletRequest request) {
        this.request = request;
    }
    @RequestMapping("safe-read")
    public void threadSafeRead() throws InterruptedException {
        System.out.println(request.getHeader("user-agent"));
        Thread.sleep(TimeUnit.MILLISECONDS.convert(5,TimeUnit.SECONDS));
        System.out.println(request.getHeader("user-agent"));
    }
}

When I do two request in same time ,result of this execution is :

  1. Mozilla/5.0 (Windows NT 6.1; WOW64; rv:26.0) Gecko/20100101 Firefox/26.0
  2. Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.102 Safari/537.36
  3. Mozilla/5.0 (Windows NT 6.1; WOW64; rv:26.0) Gecko/20100101 Firefox/26.0
  4. Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.102 Safari/537.36

In runtime field have type com.sun.proxy.$Proxy45. How spring make it thread-safe for read?

1
It injects a proxy of the actual object and does a lookup when needed (the actual request is bound to the current executing thread). However why would you want to inject the HttpServletRequest? You can simply add it to your method as an argument. I would consider the latter a better approach then injecting it. - M. Deinum
Thanks,I thought so.It was interesting how it works. - user2187298

1 Answers

0
votes

Just to expand a little on the comment by M. Deinum above, there are a few approaches you could use to avoid holding a reference to the request as part of the controller's state.

1) As already mentioned, directly inject the request as part of the method signature.

2) Only work with the request params that you are directly interested in by using the @RequestParam annotations in your method signatures.

3) Take a look at the Spring api doc for the RequestContextHolder class. You can do things like:

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

which may or may not be useful to you.

Hope this helps :-)