Spring Boot 中如何统一 API 接口响应格式?( 三 )

返回的数据格式是下面这样:
{"username":"javaboy","address":"www.javaboy.org"}现在我希望返回的数据格式变成下面这样:
{"status":"ok","data":{"username":"javaboy","address":"www.javaboy.org"}}就这样一个简单需求,我们一起来看下怎么实现 。
3.1 RequestResponseBodyMethodProcessor在开始定义之前,先给大家介绍一下 RequestResponseBodyMethodProcessor,这是 HandlerMethodReturnValueHandler 的实现类之一,这个主要用来处理返回 JSON 的情况 。
我们来稍微看下:
@Overridepublic boolean supportsReturnType(MethodParameter returnType) { return (AnnotatedElementUtils.hasAnnotation(returnType.getContainingClass(), ResponseBody.class) ||   returnType.hasMethodAnnotation(ResponseBody.class));}@Overridepublic void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,  ModelAndViewContainer mavContainer, NativeWebRequest webRequest)  throws IOException, HttpMediaTypeNotAcceptableException, HttpMessageNotWritableException { mavContainer.setRequestHandled(true); ServletServerHttpRequest inputMessage = createInputMessage(webRequest); ServletServerHttpResponse outputMessage = createOutputMessage(webRequest); writeWithMessageConverters(returnValue, returnType, inputMessage, outputMessage);}

  • supportsReturnType:从这个方法中可以看到,这里支持有 @ResponseBody 注解的接口 。
  • handleReturnValue:这是具体的处理逻辑,首先 mavContainer 中设置 requestHandled 属性为 true,表示这里处理完成后就完了,以后不用再去找视图了,然后分别获取 inputMessage 和 outputMessage,调用 writeWithMessageConverters 方法进行输出,writeWithMessageConverters 方法是在父类中定义的方法,这个方法比较长,核心逻辑就是调用确定输出数据、确定 MediaType,然后通过 HttpMessageConverter 将 JSON 数据写出去即可 。
有了上面的知识储备之后,接下来我们就可以自己实现了 。
3.2 具体实现首先自定义一个 HandlerMethodReturnValueHandler:
public class MyHandlerMethodReturnValueHandler implements HandlerMethodReturnValueHandler {    private HandlerMethodReturnValueHandler handler;    public MyHandlerMethodReturnValueHandler(HandlerMethodReturnValueHandler handler) {        this.handler = handler;    }    @Override    public boolean supportsReturnType(MethodParameter returnType) {        return handler.supportsReturnType(returnType);    }    @Override    public void handleReturnValue(Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {        Map<String, Object> map = new HashMap<>();        map.put("status", "ok");        map.put("data", returnValue);        handler.handleReturnValue(map, returnType, mavContainer, webRequest);    }}由于我们要做的功能其实是在 RequestResponseBodyMethodProcessor 基础之上实现的,因为支持 @ResponseBody,输出 JSON 那些东西都不变,我们只是在输出之前修改一下数据而已 。所以我这里直接定义了一个属性 HandlerMethodReturnValueHandler,这个属性的实例就是 RequestResponseBodyMethodProcessor,supportsReturnType 方法就按照 RequestResponseBodyMethodProcessor 的要求来,在 handleReturnValue 方法中,我们先对返回值进行一个预处理,然后调用 RequestResponseBodyMethodProcessor#handleReturnValue 方法继续输出 JSON 即可 。
接下来就是配置 MyHandlerMethodReturnValueHandler 使之生效了 。由于 SpringMVC 中 HandlerAdapter 在加载的时候已经配置了 HandlerMethodReturnValueHandler(这块松哥以后会和大家分析相关源码),所以我们可以通过如下方式对已经配置好的 RequestMappingHandlerAdapter 进行修改,如下:
@Configurationpublic class ReturnValueConfig implements InitializingBean {    @Autowired    RequestMappingHandlerAdapter requestMappingHandlerAdapter;    @Override    public void afterPropertiesSet() throws Exception {        List<HandlerMethodReturnValueHandler> originHandlers = requestMappingHandlerAdapter.getReturnValueHandlers();        List<HandlerMethodReturnValueHandler> newHandlers = new ArrayList<>(originHandlers.size());        for (HandlerMethodReturnValueHandler originHandler : originHandlers) {            if (originHandler instanceof RequestResponseBodyMethodProcessor) {                newHandlers.add(new MyHandlerMethodReturnValueHandler(originHandler));            }else{                newHandlers.add(originHandler);            }        }        requestMappingHandlerAdapter.setReturnValueHandlers(newHandlers);    }}


推荐阅读