How can I set correct Last-Modified header value for Spring Web Service that is cached using Spring Cache?

10,346

Solution 1

How about this:

@Controller
@RequestMapping(value = "/user")
class UserController {

    @Cacheable(value = "users", key = "#id")
    @RequestMapping(value = "/get", method = RequestMethod.GET)
    @ResponseBody
    public ResponseEntity<User> getUser(Long id) {
        HttpHeaders headers = new HttpHeaders();
        headers.set("Last-Modified", dateFormat.format(new Date()));
        return new ResponseEntity<SecurityProperties.User>(headers, userService.get(id), HttpStatus.OK);
    }
}

Solution 2

Spring has an already build in support to handle the last-modified and If-Modified-Since header in for driven request handler methods.

It is based on WebRequest.checkNotModified(long lastModifiedTimestamp)

This example is just taken from the java doc:

This will also transparently set the appropriate response headers, for both the modified case and the not-modified case. Typical usage:

 @RequestMapping(value = "/get", method = RequestMethod.GET)
 public String myHandleMethod(WebRequest webRequest, Model model) {
    long lastModified = // application-specific calculation
    if (request.checkNotModified(lastModified)) {
      // shortcut exit - no further processing necessary
      return null;
    }
    // further request processing, actually building content
    model.addAttribute(...);
    return "myViewName";
}

But your @Cacheable annotation is a problem, because it prevent that the method is executed (for the second invocation) and therefore the request.checkNotModified is not invoked. - If the caching is important then you could remove the @Cacheable annotation from the controller method and put it on an inner method that is invoked after request.checkNotModified is done.

 //use selfe in order to use annotation driven advices
 @Autowire
 YourController selfe;

 @RequestMapping(value = "/get", method = RequestMethod.GET)
 public String myHandleMethod(WebRequest webRequest, Model model) {
    long lastModified = // application-specific calculation
    if (request.checkNotModified(lastModified)) {
      // shortcut exit - no further processing necessary
      return null;
    } else {  
      return selfe.innerMyHandleMethod(model);
    }
}

@Cacheable(value = "users", key = "#id")
public String innerMyHandleMethod(Model model) {   
    model.addAttribute(...);
    return "myViewName";
}
Share:
10,346
Nazar
Author by

Nazar

Updated on June 18, 2022

Comments

  • Nazar
    Nazar almost 2 years

    I have such Spring MVC Controller:

    @Controller
    @RequestMapping(value = "/user")
    public class UserController {
       .....      
       @Cacheable(value = "users", key = "#id")
       @RequestMapping(value = "/get", method = RequestMethod.GET)
       @ResponseBody
       public User getUser(Long id){
           return userService.get(id);
       }
       ....
    }
    

    I want to add header Last-Modified to HTTP Response of GetUser web service.
    How can I get proper date when cache was added to my store?
    How can I add header Last-Modified with this date to response of my Spring Controller Method?