Spring MVC:用于包装API响应的适当扩展点 [英] Spring MVC: Appropriate extension point for wrapping API Responses

查看:125
本文介绍了Spring MVC:用于包装API响应的适当扩展点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个简单的REST API,使用Spring MVC @Controller @RequestMapping 进行构建。我想开始包装响应以提供额外的元数据。

I have a simple REST API, build using Spring MVC @Controllers and @RequestMapping. I'd like to start wrapping responses to provide additional with metadata.

例如,给定一个将返回的调用

For example, given a call that would return

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

我想将其换行,如下所示:

I'd like to wrap it, as follows:

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

此外,我想支持管理列表的标准参数集( limit offset )。

Additionally, I'd like to support standard set of parameters for managing lists (limit and offset).

由于这涉及所有api方法,我想将它作为一些弹簧的装饰器来实现内部服务,所以方法本身可以专注于他们的实际逻辑,并保持这个样板的东西集中。

As this touches all the api methods, I'd like to implement it as a decorator of some spring internal service, so the methods themselves can focus on their actual logic, and keep this boilerplate stuff centralized.

我已经开始了de的道路编制已注册的 HttpMessageConverter ,并用装饰器包装它们。

I've started down the path of decorating the HttpMessageConverter's that are registered, and wrapping them with a decorator.

但是,这不是让我可以访问未声明 @RequestBody 的方法的入站请求。 (很多人没有)

However, this doesn't provide me access to the inbound request for methods that don't declare a @RequestBody. (Many don't)

理想情况下,我需要在堆栈中更高 - RequestResponseBodyMethodProcessor.writeWithMessageConverters()看起来像个好人,但我不知道如何在这里挂钩。

Ideally, I need to be higher in the stack - RequestResponseBodyMethodProcessor.writeWithMessageConverters() looks like a good candidate, but I don't know how to hook in here.

Spring MVC可以使用哪些选项来实现这种类型的API-Wide处理请求/回复?

What options are available with Spring MVC to implement this type of API-Wide processing of request / responses?

推荐答案

以下是我使用的实现:

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

}

这篇关于Spring MVC:用于包装API响应的适当扩展点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆