Как установить правильное значение заголовка Last-Modified для веб-службы Spring, которая кэшируется с помощью Spring Cache?

У меня есть такой контроллер Spring MVC:

@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);
   }
   ....
}

Я хочу добавить заголовок Last-Modified в HTTP-ответ веб-службы GetUser.
Как я могу получить правильную дату, когда кеш был добавлен в мой магазин?
Как я могу добавить заголовок Last-Modified с этой датой в ответ от мой метод контроллера Spring?


person Nazar    schedule 11.04.2014    source источник


Ответы (2)


Как насчет этого:

@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);
    }
}
person Dave Syer    schedule 11.04.2014
comment
эта реализация противоречит цели повторной проверки с последними изменениями. Если данные изменяются, устаревшие данные по-прежнему будут обслуживаться из кеша со старой датой последнего изменения. - person dschulten; 14.04.2016
comment
Разве добавление @Cacheable к @RequestMapping уже не противоречит этой цели? - person Dave Syer; 14.04.2016

Spring уже имеет встроенную поддержку для обработки заголовков last-modified и If-Modified-Since для управляемых методов обработчика запросов.

Он основан на WebRequest.checkNotModified(long lastModifiedTimestamp)

Этот пример только что взят из документа Java:

Это также прозрачно установит соответствующие заголовки ответов как для модифицированного, так и для немодифицированного случая. Типичное использование:

 @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";
}

Но проблема с вашей аннотацией @Cacheable, поскольку она предотвращает выполнение метода (для второго вызова) и, следовательно, request.checkNotModified не вызывается. – Если кэширование важно, вы можете удалить аннотацию @Cacheable из метода контроллера и поместить ее во внутренний метод, который вызывается после выполнения request.checkNotModified.

 //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";
}
person Ralph    schedule 18.03.2016
comment
@dschulten: это работает для контроллера на основе аннотаций - я его использую! - person Ralph; 14.04.2016