2012-11-01 15 views
9

私は、Spring MVC @Controller@RequestMappingを使用して簡単なREST APIを構築しています。私はメタデータを追加するための応答をラップしてみたいと思います。例えばSpring MVC:APIレスポンスの適切な拡張ポイント

、次のように私は、それをラップしたいと思います

HTTP GET: /users/1 
{ 
    "userName" : "Jack Jackerson" 
} 

を返します呼び出し与えられた:

{ 
    "metadata" : 
    { 
     "callLimit" : "50", 
     "callsRemaining" : "49" 
    }, 
    "result" : 
    { 
     "userName" : "Jack Jackerson" 
    } 
} ..etc.. 

また、私はパラメータの標準セットをサポートしたいと思いますがリストを管理する(limitおよびoffset)。

これはすべてのapiメソッドに触れているので、私はいくつかのスプリング内部サービスのデコレータとして実装したいので、メソッド自体は実際のロジックに焦点を当てて、この定型文を集中管理してください。

登録されているHttpMessageConverterをデコレートしてデコレータでラップする方法を開始しました。

ただし、@RequestBodyを宣言していないメソッドの受信リクエストにはアクセスできません。 (多くはありません)

理想的には、私はスタック内で高くなる必要があります - RequestResponseBodyMethodProcessor.writeWithMessageConverters()は良い候補のように見えますが、ここにフックする方法はわかりません。

リクエスト/レスポンスのこの種のAPIワイド処理を実装するためにSpring MVCでどのようなオプションを利用できますか?

答えて

6

ここで私が使用される実装です:

public class MetadataInjectingReturnValueHandler implements HandlerMethodReturnValueHandler { 

    private final HandlerMethodReturnValueHandler delegate; 

    public MetadataInjectingReturnValueHandler(HandlerMethodReturnValueHandler delegate) 
    { 
     this.delegate = delegate; 
    } 
    @Override 
    public boolean supportsReturnType(MethodParameter returnType) { 
     return delegate.supportsReturnType(returnType); 
    } 

    @Override 
    public void handleReturnValue(Object returnValue, 
      MethodParameter returnType, ModelAndViewContainer mavContainer, 
      NativeWebRequest webRequest) throws Exception { 
     returnValue = wrapResult(returnValue); //Omitted 
     delegate.handleReturnValue(returnValue, returnType, mavContainer, webRequest); 
    } 
} 



@Component 
public class MetadataInjectionFactoryBean implements InitializingBean { 

    @Autowired 
    private RequestMappingHandlerAdapter adapter; 
    @Override 
    public void afterPropertiesSet() throws Exception { 
     HandlerMethodReturnValueHandlerComposite returnValueHandlers = adapter.getReturnValueHandlers(); 
     List<HandlerMethodReturnValueHandler> handlers = Lists.newArrayList(returnValueHandlers.getHandlers()); 
     decorateHandlers(handlers); 
     adapter.setReturnValueHandlers(handlers); 
    } 
    private void decorateHandlers(List<HandlerMethodReturnValueHandler> handlers) { 
     for (HandlerMethodReturnValueHandler handler : handlers) { 
      if (handler instanceof RequestResponseBodyMethodProcessor) 
      { 
       MetadataInjectingReturnValueHandler decorator = new MetadataInjectingReturnValueHandler(handler); 
       int index = handlers.indexOf(handler); 
       handlers.set(index, decorator); 
       log.info("Metadata Injecting decorator wired up"); 
       break; 
      } 
     }  
    } 

} 
+0

は完全に働きました。ありがとう! –

+0

私は['@ ControllerAdvice'](http://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-ann-controller-advice)を使うことができると思います。このソリューションを簡素化するために['ResponseBodyAdvice'](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/servlet/mvc/method/annotation/ResponseBodyAdvice.html)と組み合わせてください。 –

+0

@AmirAbiriでは、応答のタイプを変更することはできません。あなたはいくつかのデータで応答を豊かにすることができますが、他の構造とオブジェクトを包むことはできません。 –

関連する問題