Is there a thread safety problem when injecting request into controller in Springmvc?

@Controller
public class AController{

    @Autowire
    HttpServletRequest request;
    
    @RequestMapping("/test")
    public Result test(){
        System.out.println(request.toString());
        request.getHeader("uid");
    }
}

for example,
I use Autowire to inject request , and then directly use request in the controller method.
since controller is singleton by default, I wonder if there will be thread safety problems.
because I output hashcode of request and find that every request hashcode is the same.
then will the following request overwrite the current request , resulting in information distortion?

add

1. I want to use HttpServletRequest in every method of controller , so I think it"s troublesome to declare it every time in the method? I don"t know how to solve this problem.
2. The reason I write this is that I want to make request a member variable of the parent class by inheriting a parent class, so that it can be used directly in the method.
3. I did it downstairs (that"s what I wrote before)

public Result test(HttpServletRequest request){

    System.out.println(request.toString());
}

is also accessed continuously, or with different clients. It is found that the hashcode of each requested request printed out is the same, why?


Thank you for your answers
after my testing and exploration.
concludes that
using @ autowire to inject HttpServletRequest is thread-safe.
specific verification process I wrote blog
interested can see, if there is anything wrong, please point it out.
thanks again to the programmers upstairs who are eager to answer my questions

fromerr=XhvpvVTi" rel=" nofollow noreferrer "> blog address stamp me

ps: what is discussed above is

when Controller is in singleton mode.


it is thread-safe to write this for the following reasons:

  1. the request injected into controller is a jdk dynamic proxy object, an instance of ObjectFactoryDelegatingInvocationHandler. When we call the method of the member domain request, we actually call the related method of the getObject () object of objectFactory. The objectFactory here is RequestObjectFactory.
  2. the getObject of RequestObjectFactory is actually taken from the threadlocal of RequestContextHolder.
  3. when you first enter the dispatcherServlet of springmvc, the request-related objects will be set to the threadlocal of RequestContextHolder.

reference: injecting Request member domains into SpringMVC Controller


well, I made a fool of myself, preoccupied with solving the secondary request the same problem every time, and forgot the theme.
add @ ModelAttribute indeed there will be thread safety problems !
.

if you want to use object properties and deal with thread safety, there is a simple way to deal with thread safety, but is very rough , just use @ Scope ("prototype") to have Spring MVC generate a new entity class every time you request.
but why does Spring MVC default to singleton? Naturally, because of the performance and overhead advantages of the singleton, writing @ Scope ("prototype") means giving up the advantage of the singleton.

so it's really a way, but it's not good. I'm sorry to make a fool of you.

@Controller
// @Scope("prototype")
public class AController{

    //@Autowired //autowried
    protected HttpServletRequest request;
    protected HttpServletResponse response;
    
    @ModelAttribute
    public void bindRequestObject(HttpServletRequest request, HttpServletResponse response) {
        this.request = request;
        this.response = response;
    }
    
    @RequestMapping("/test")
    public Result test(){
        System.out.println(request.toString());
        request.getHeader("uid");
    }
}

1. After Autowire is injected into request, there will be security problems in using instance variables
2, overwriting request
3, same hashcode or an object

feel that it is troublesome to write parameters in the method, so you can:

@Controller
public class AControllre extends AbstractController {

    @RequestMapping("/test")
    public String test(){
        //
        String name = getRequest().getParameter("username");
        return "";
    }
}

class AbstractController {
    protected HttpServletRequest getRequest() {
        return ((ServletRequestAttributes) 
                RequestContextHolder.getRequestAttributes()).getRequest();
    }
    protected HttpServletResponse getResponse() {
        return new ServletWebRequest(((ServletRequestAttributes) 
                RequestContextHolder.getRequestAttributes()).getRequest()).getResponse();
    }
}

I have seen this way of writing for the first time, why not write it this way?

@Controller
public class AController{
    
    @RequestMapping("/test")
    public Result test(HttpServletRequest request){
        System.out.println(request.toString());
        request.getHeader("uid");
    }
}

in fact, in most cases, request does not have to be passed as a parameter. For example, if you want to get the uid, in the request header, you can write:

@Controller
public class AController{
    
    @RequestMapping("/test")
    public Result test(@RequestHeader("uid") String uid) {
        System.out.println(uid); // request.getHeader("uid")
    }
}
< hr >

20180613 complements the answer made two years ago:
the above answer does not directly answer the question raised by the subject, so it can be regarded as an incorrect answer. The following supplementary answer:

the way given by the subject is thread-safe! There is no problem with this approach.

  

httpRequestServlet is not a class attribute, but a thread variable, so I think the best way to use it is to use RequestContextHolder. CurrentRequestAttributes () will pick it up.

Menu