128

I would like to handle request and session attributes myself rather then leave it to spring @SessionAttributes, for login of cookies handling for example.

I just cant figure out how could I access the HttpRequest from within a controller, I need a way to go a layer above the @RequestAttribute and access the HttpRequest itself. With Stripes in used to do this by implementing an ApplicationContext and calling getAttribute().

Also, passing the HttpServletRequest as parameter seems not to be working:

@RequestMapping(value="/") public String home(HttpServletRequest request){
    System.out.println(""+request.getSession().getCreationTime());
    return "home"; 
}

The above method does not print anything.

Do you have any advice on this?

jjmontes
  • 24,679
  • 4
  • 39
  • 51
JBoy
  • 5,398
  • 13
  • 61
  • 101

4 Answers4

226

Spring MVC will give you the HttpRequest if you just add it to your controller method signature:

For instance:

/**
 * Generate a PDF report...
 */
@RequestMapping(value = "/report/{objectId}", method = RequestMethod.GET)
public @ResponseBody void generateReport(
        @PathVariable("objectId") Long objectId, 
        HttpServletRequest request, 
        HttpServletResponse response) {

    // ...
    // Here you can use the request and response objects like:
    // response.setContentType("application/pdf");
    // response.getOutputStream().write(...);

}

As you see, simply adding the HttpServletRequest and HttpServletResponse objects to the signature makes Spring MVC to pass those objects to your controller method. You'll want the HttpSession object too.

EDIT: It seems that HttpServletRequest/Response are not working for some people under Spring 3. Try using Spring WebRequest/WebResponse objects as Eduardo Zola pointed out.

I strongly recommend you to have a look at the list of supported arguments that Spring MVC is able to auto-magically inject to your handler methods.

MsA
  • 2,599
  • 3
  • 22
  • 47
jjmontes
  • 24,679
  • 4
  • 39
  • 51
  • Hi, thx for the hints, i dont know what i'm doing wrong but this isn't working: it does not prints anything: @RequestMapping(value="/") public String home(HttpServletRequest request){ System.out.println(""+request.getSession().getCreationTime()); return "home"; } This should pring the current amount pof millis but it does not, also annotating the method with @RequestBody does not change anything, any further advice? thx for this – JBoy Dec 14 '11 at 23:47
  • 2
    Thanks @jjmontes for the link to Spring MVC's supported arguments! – Barett Jun 13 '14 at 18:58
  • I know next to nothing about Spring, but I had to add the `@Context` annotation before the argument in order to get them injected. Could be something new, I dunno, but figured I'd mention it. – ivarni Jun 08 '18 at 09:43
91

I know that is a old question, but...

You can also use this in your class:

@Autowired
private HttpServletRequest context;

And this will provide the current instance of HttpServletRequest for you use on your method.

Deividi Cavarzan
  • 10,034
  • 13
  • 66
  • 80
  • 7
    Doesn't doing it this way prevent the controller bean from being a singleton? – jjmontes Oct 30 '13 at 13:07
  • 2
    Spring controllers are always singletons. – Deividi Cavarzan Oct 30 '13 at 13:14
  • 22
    This feels wrong - what if the controller is handling more than one request at the given time? What is "current" request then? – sbk May 30 '14 at 09:10
  • 3
    This question have some explanations about you're asking for: http://stackoverflow.com/questions/17235794/how-does-spring-mvc-handle-multiple-users – Deividi Cavarzan May 30 '14 at 13:47
  • 1
    It would be quite useful to have something like `getThreadLocalRequest()` in GWT's `RemoteServiceServlet` which always returns correct request even if it is executed in highly concurrent environment. – Yuriy Nakonechnyy Jul 01 '14 at 11:14
  • This is imho a better explanation of how application servers make some per-request data accessible to singletons via ThreadLocal variables: http://stackoverflow.com/questions/11139571/scope-of-a-spring-controller-and-its-instance-variables . In any case, Autowiring the context to the controller is imho not the best practice,and I'd rather pass context as an argument to the controller method. – jjmontes Feb 23 '16 at 01:19
  • 1
    @sbk controller methods are handling always single request per invocation. This is how HTTP works, can't even imagine how multiple requests may happen in single invocation. – m1ld Sep 24 '21 at 10:23
5

Another way is to use RequestContextHolder like: (Since: 2.0)

RequestContextHolder Holder class to expose the web request in the form of a thread-bound RequestAttributes object. The request will be inherited by any child threads spawned by the current thread if the inheritable flag is set to true.

HttpServletRequest req = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
sendon1982
  • 9,982
  • 61
  • 44
0
@RequestMapping(value="/") public String home(HttpServletRequest request){
    System.out.println("My Attribute :: "+request.getAttribute("YourAttributeName"));
    return "home"; 
}
4b0
  • 21,981
  • 30
  • 95
  • 142