Spring MVC中的自定义HttpMessageConverter [英] Custom HttpMessageConverter in Spring MVC
问题描述
实现RESTful API时,我将所有数据包装在一个对象中,使它看起来像这样。
When implementing RESTful API I wrap all my data in an object so it looks like this.
{error: null, code: 200, data: {...actual data...}}
这导致重复代码我在任何地方用来包装数据:
This results in repetitive code I use everywhere to wrap data:
@Transactional
@RequestMapping(value = "/", method = RequestMethod.GET)
public @ResponseBody Result<List<BookShortDTO>> books() {
List<Book> books = booksDao.readBooks();
return Result.ok(books); // this gets repeated everywhere
}
所以问题是如何修改它(也许使用自定义HttpMessageConverter可能还有其他方法吗?)只返回booksDao.readBooks()并自动包装。
So the question is how do I modify this (maybe with use of custom HttpMessageConverter maybe some other ways?) to just return booksDao.readBooks() and to get it wrapped automatically.
推荐答案
像@Ralph建议您可以使用 HandlerMethodReturnValueHandler
来包装处理程序的返回值。
Like @Ralph suggested you can use a HandlerMethodReturnValueHandler
to wrap your handlers return value.
最简单的方法实现这一点是通过扩展 RequestResponseBodyMethodProcessor
并稍微改变它的行为。最好的方法是创建一个自定义注释来标记处理程序方法。这将确保默认情况下将调用 HandlerMethodReturnValueHandler
而不是 RequestMappingHandlerAdapter
所包含的其他内容。
The easiest way to achieve this is by extending RequestResponseBodyMethodProcessor
and alter it's behavior a bit. Best is to create a custom annotation to mark your handler methods with. This will make sure your HandlerMethodReturnValueHandler
will be called instead of others included by RequestMappingHandlerAdapter
by default.
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ResultResponseBody {}
以下是自定义 HandlerMethodReturnValueHandler
的简单实现 ResultResponseHandlerMethodProcessor
,它将支持从使用 ResultResponseBody
注释的方法返回的值。这很简单。只需覆盖 supportsReturnType()
和 handleReturnValue()
方法以满足您的需求(将返回值包装到结果
类型)。
Here is a simple implementation of the custom HandlerMethodReturnValueHandler
named ResultResponseHandlerMethodProcessor
which will support values returned from methods annotated with ResultResponseBody
. It's pretty simple. Just override the supportsReturnType()
and handleReturnValue()
methods to suit your needs (wrap the return value into a Result
type).
public class ResultResponseHandlerMethodProcessor extends RequestResponseBodyMethodProcessor {
public ResultResponseHandlerMethodProcessor(final List<HttpMessageConverter<?>> messageConverters) {
super(messageConverters);
}
public ResultResponseHandlerMethodProcessor(final List<HttpMessageConverter<?>> messageConverters, final ContentNegotiationManager contentNegotiationManager) {
super(messageConverters, contentNegotiationManager);
}
@Override
public boolean supportsReturnType(final MethodParameter returnType) {
return returnType.getMethodAnnotation(ResultResponseBody.class) != null;
}
@Override
public void handleReturnValue(final Object returnValue, final MethodParameter returnType, final ModelAndViewContainer mavContainer, final NativeWebRequest webRequest) throws IOException, HttpMediaTypeNotAcceptableException {
super.handleReturnValue(Result.ok(returnValue), returnType, mavContainer, webRequest);
}
}
唯一剩下的就是将此类添加到自定义 HandlerMethodReturnValueHandler
列表,并提供 MappingJackson2HttpMessageConverter
实例。
The only thing left is to add this class to the list of custom HandlerMethodReturnValueHandler
s and provide it with a MappingJackson2HttpMessageConverter
instance.
@EnableWebMvc
@Configuration
public class ApplicationConfiguration extends WebMvcConfigurerAdapter
@Override
public void addReturnValueHandlers(final List<HandlerMethodReturnValueHandler> returnValueHandlers) {
List<HttpMessageConverter<?>> messageConverters = new ArrayList<>();
messageConverters.add(new MappingJackson2HttpMessageConverter());
returnValueHandlers.add(new ResultResponseHandlerMethodProcessor(messageConverters));
}
}
这篇关于Spring MVC中的自定义HttpMessageConverter的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!