我有一个简单的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响应的适当扩展点
发布评论