Пост-обработка ответа Json в spring MVC
У меня есть несколько контроллеров, которые возвращают один и тот же общий объект Response с аннотацией @ResponseBody, например:
@RequestMapping(value = "/status", method = RequestMethod.GET)
@Transactional(readOnly = true)
public @ResponseBody Response<StatusVM> status()
Мне нужно выполнить операцию на каждом контроллере после возвращения ответа. Эта операция обогатит объект Response новыми данными.
Я не хочу дублировать код, поэтому мне нужна единая точка вмешательства. Я думал, что могу сделать это с помощью Interceptors, однако, согласно документам http://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-handlermapping-interceptor, это не работает с @ResponseBody:
Обратите внимание, что метод postHandle для HandlerInterceptor не всегда идеально подходит для использования с методами @ResponseBody и ResponseEntity. В таких случаях HttpMessageConverter записывает и передает ответ до того, как вызывается postHandle, что делает невозможным изменение ответа, например, для добавления заголовка. Вместо этого приложение может реализовать ResponseBodyAdvice и объявить его как @ControllerAdvice bean или настроить его непосредственно на RequestMappingHandlerAdapter.
Я не смог найти пример этой методики, может ли кто-нибудь помочь мне?
В качестве альтернативы я мог бы работать с аспектами, но тогда мне нужно было бы аннотировать каждый контроллер, чего я бы хотел избежать.
Ответы
Ответ 1
В конце я реализовал ResponseBodyAdvice следующим образом:
@ControllerAdvice
public class StatusAdvice implements ResponseBodyAdvice<Response<?>> {
@Override
public boolean supports(MethodParameter returnType,
Class<? extends HttpMessageConverter<?>> converterType) {
if (returnTypeIsReponseVM(returnType)&&responseConverterIsJackson2(converterType)){
return true;
}
return false;
}
....
@Override
public Response<?> beforeBodyWrite(Response<?> body, MethodParameter returnType,
MediaType selectedContentType,
Class<? extends HttpMessageConverter<?>> selectedConverterType,
ServerHttpRequest request, ServerHttpResponse response) {
....
return body;
}
}
Так было легче, чем ожидалось.