9

Spring MVC@Controllerとを使用してビルドした単純な REST API があり@RequestMappingます。応答のラッピングを開始して、追加のメタデータを提供したいと思います。

たとえば、次の呼び出しが返されるとします。

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

次のようにラップしたいと思います。

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

limitさらに、リストを管理するためのパラメータの標準セット (および)をサポートしたいと考えていますoffset

これはすべての API メソッドに関係するため、Spring の内部サービスのデコレータとして実装したいと考えています。これにより、メソッド自体が実際のロジックに集中し、この定型文を集中管理できるようになります。

私は、HttpMessageConverter登録されている を装飾し、それらをデコレーターでラップする道を歩み始めました。

ただし、これでは、@RequestBody. (多くはそうではありません)

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

このタイプの API 全体のリクエスト/レスポンス処理を実装するために、Spring MVC で使用できるオプションは何ですか?

4

1 に答える 1

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

}
于 2012-11-01T11:24:40.167 に答える