Java – Custom httpmessageconverter in spring MVC
When implementing the restful API, I wrap all the data in one object to make it look like this
{error: null,code: 200,data: {...actual data...}}
This leads me to wrap data with duplicate code anywhere:
@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 }
So the question is how to modify it (you may use a custom httpmessageconverter, and there may be other methods?) Return only booksdao Readbooks () and automatically wrap it
Solution
As @ Ralph suggests, you can use handlermethodreturnvaluehandler to wrap the return value of your handler
The easiest way to achieve this is to extend the requestresponsebodymethodprocessor and change its behavior slightly The best way is to create a custom comment to mark the handler method This ensures that the handlermethodreturnvaluehandler will be called by default instead of the other handlermethodreturnvaluehandler contained in the requestmappinghandleradapter
@Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface ResultResponseBody {}
The following is a simple implementation of a custom handlermethodreturnvaluehandler named resultresponsehandlermethodprocessor, which will support values returned from methods annotated with resultresponsebody It's simple Just override the supportsreturntype () and handlereturnvalue () methods to meet your needs (wrap the return value in the 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); } }
The only thing left is to add this class to the custom handlermethodreturnvaluehandlers list 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)); } }