2014-11-05 18 views
14

Ich habe mehrere Controller, die das gleiche allgemeine Response-Objekt mit @ResponseBody Anmerkung, wie dies zurück:Nachbearbeitung einer Json Antwort im Frühjahr MVC

@RequestMapping(value = "/status", method = RequestMethod.GET) 
    @Transactional(readOnly = true) 
    public @ResponseBody Response<StatusVM> status() 

Ich brauche eine Operation auf jedem Controller auszuführen, nachdem die Antwort wird zurückgegeben. Diese Operation wird das Response-Objekt mit neuen Daten anreichern.

Ich möchte Code nicht duplizieren, also brauche ich einen einzigen Interventionspunkt. Ich dachte, ich könnte dies tun, mit Interceptor jedoch nach dem docs http://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-handlermapping-interceptor dies nicht gut mit @ResponseBody funktioniert:

Beachten Sie, dass die postHandle Methode des HandlerInterceptor ist nicht immer ideal für den Einsatz mit @ResponseBody und ResponseEntity Methoden . In solchen Fällen schreibt und schreibt ein HttpMessageConverter die Antwort, bevor postHandle aufgerufen wird, was es unmöglich macht, die Antwort zu ändern, um beispielsweise einen Header hinzuzufügen. Stattdessen kann eine Anwendung ResponseBodyAdvice implementieren und entweder als @ControllerAdvice-Bean deklarieren oder direkt auf RequestMappingHandlerAdapter konfigurieren.

Ich konnte kein Beispiel für diese Technik finden, könnte mir jemand helfen?

Als Alternative könnte ich mit Aspekten arbeiten, aber dann müsste ich jeden Controller kommentieren, was ich gerne vermeiden würde.

Antwort

22

Am Ende implementiert ich ResponseBodyAdvice wie folgt aus:

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

} 

So war es einfacher als erwartet.