SpringBoot全局Controller返回值格式统一

作者:TianXinCoord 时间:2022-09-12 14:07:52 

一、返回值格式统一

1.返回值介绍

在使用controller对外提供服务的时候,很多时候都需要统一返回值格式,例如


{
"status": true,
"message": null,
"code": "200",
"data": {
"name": "json",
"desc": "json返回值"
}
}

如果不使用全局统一返回,就需要写一个工具类,然后controller返回对应的对象


@Data
public class ResponseData {
   private boolean status;
   private String message;
   private String code;
   private Object data;
}

@RequestMapping("/foo")
public ResponseData foo() {
   // 或者使用工具类返回,根据业务设置值
   return new ResponseData();
}

除了上述方法,可以对返回值进行统一处理,不需要对所有controller都使用一个返回值,controller只需要返回原始值,处理器会对返回值进行封装

同时也可以添加自定义注解,此注解用于忽略返回值封装,按照controller原始值返回

2.基础类功能

org.springframework.web.method.support.HandlerMethodReturnValueHandler

  • 使用不同策略处理从调用处理程序方法的返回值

  • 策略处理顶层接口,自定义返回值格式需要实现此接口

  • supportsReturnType:设置支持返回值类型

  • handleReturnValue:处理返回值基础参数

SpringBoot全局Controller返回值格式统一

org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter

  • 请求映射处理适配,包含了参数、返回值处理器等信息

  • HandlerMethodReturnValueHandlerComposite内部维护了HandlerMethodReturnValueHandler列表

SpringBoot全局Controller返回值格式统一SpringBoot全局Controller返回值格式统一

可以自定义注解,用于类或者方法级别忽略返回值封装


@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface IgnoreResponseWrapper {

}

org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor

  • 属于HandlerMethodReturnValueHandler子类

  • 主要功能是对请求和响应体的做处理的方法

  • 所有属于RequestResponseBodyMethodProcessor的子类都需要替换为自定义返回值处理

实现原理就是,在bean初始化的时候,获取到所有处理器数组,然后将所有是RequestResponseBodyMethodProcessor处理器子类对返回值处理的过程替换为自定义处理器

处理这样当调用对应返回值处理器时,将会使用到自定义的返回值处理器,也就是所有返回值都会按照规定的进行处理

3.基础实现

创建普通springboot项目,项目创建在此不做说明

创建类实现HandlerMethodReturnValueHandler接口,主要用于实现自定义返回值内容,不需要注入容器


import com.codecoord.unifyreturn.annotation.IgnoreResponseWrapper;
import com.codecoord.unifyreturn.domain.ResponseBase;
import org.springframework.core.MethodParameter;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.method.support.ModelAndViewContainer;

public class ResponseBodyWrapHandler implements HandlerMethodReturnValueHandler {
   private final HandlerMethodReturnValueHandler delegate;

public ResponseBodyWrapHandler(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 {
       // 如果类或者方法含有不包装注解则忽略包装
       IgnoreResponseWrapper wrapper = returnType.getDeclaringClass().getAnnotation(IgnoreResponseWrapper.class);
       if (wrapper != null) {
           delegate.handleReturnValue(returnValue, returnType, mavContainer, webRequest);
           return;
       }
       wrapper = returnType.getMethodAnnotation(IgnoreResponseWrapper.class);
       if (wrapper != null) {
           delegate.handleReturnValue(returnValue, returnType, mavContainer, webRequest);
           return;
       }

// 自定义返回格式
       ResponseBase responseBase = new ResponseBase();
       responseBase.setStatus(true);
       responseBase.setCode("200");
       responseBase.setData(returnValue);
       delegate.handleReturnValue(responseBase, returnType, mavContainer, webRequest);
   }
}

创建类实现InitializingBean,在初始化时调用,需要注入到容器中,否则Spring无法管理


import java.util.ArrayList;
import java.util.List;

@Component
public class ResponseBodyWrapFactoryBean implements InitializingBean {
   private final RequestMappingHandlerAdapter adapter;

@Autowired
   public ResponseBodyWrapFactoryBean(RequestMappingHandlerAdapter adapter) {
       this.adapter = adapter;
   }

@Override
   public void afterPropertiesSet() throws Exception {
       List<HandlerMethodReturnValueHandler> returnValueHandlers = adapter.getReturnValueHandlers();
       if (returnValueHandlers.size() > 0) {
       // 将内置的返回值处理器进行替换
           List<HandlerMethodReturnValueHandler> handlers = new ArrayList<>(returnValueHandlers);
           decorateHandlers(handlers);
           adapter.setReturnValueHandlers(handlers);
       }
   }

/**
    * 将所有RequestResponseBodyMethodProcessor返回值处理器替换为自定义的返回值处理器
    *
    * @author tianxincode@163.com
    * @since 2020/10/12
    */
   private void decorateHandlers(List<HandlerMethodReturnValueHandler> handlers) {
       for (HandlerMethodReturnValueHandler handler : handlers) {
           if (handler instanceof RequestResponseBodyMethodProcessor) {
           // 替换为自定义返回值处理器
               ResponseBodyWrapHandler decorator = new ResponseBodyWrapHandler(handler);
               int index = handlers.indexOf(handler);
               handlers.set(index, decorator);
               break;
           }
       }
   }
}

创建controller信息,例如此处map不需要封装,按照原来格式响应


@RestController
@RequestMapping("/unify")
public class UnifyReturnValueController {

@RequestMapping("string")
   public String stringHandler(){
       return "接收成功了";
   }

@RequestMapping("/json")
   public JSONObject jsonHandler(){
       JSONObject object = new JSONObject();
       object.put("name", "json");
       object.put("desc", "json返回值");
       return object;
   }

@RequestMapping("/map")
   @IgnoreResponseWrapper
   public Map<String, Object> mapHandler(){
       Map<String, Object> map = new HashMap<>(10);
       map.put("name", "map");
       map.put("desc", "map返回值");
       return map;
   }

@RequestMapping("/list")
   public List<Object> listHandler(){
       List<Object> data = new ArrayList<>();
       data.add(100);
       data.add(95);
       data.add(99);
       return data;
   }
}

4.测试信息 测试json(有封装)


{
"status": true,
"message": null,
"code": "200",
"data": {
"name": "json",
"desc": "json返回值"
}
}

测试map(无封装)


{
"name": "map",
"desc": "map返回值"
}

别的方法测试一样

二、附录说明

项目结构参考红框部分,别的忽略

SpringBoot全局Controller返回值格式统一

除了对返回值进行全局统一,也可以对异常进行全局处理和按照统一格式返回

来源:https://blog.csdn.net/sinat_34104446/article/details/109032687

标签:SpringBoot,返回,格式,统一
0
投稿

猜你喜欢

  • Java8特性使用Function代替分支语句

    2021-09-05 07:29:09
  • JDK源码分析之String、StringBuilder和StringBuffer

    2022-01-23 00:10:20
  • Android 文件存储系统原理

    2021-12-24 05:10:57
  • Java内存模型(JMM)及happens-before原理

    2023-11-25 00:41:05
  • Spring mvc拦截器实现原理解析

    2023-06-06 15:26:33
  • 详解如何在Java中加密和解密zip文件

    2022-12-07 12:26:46
  • C#生成word记录实例解析

    2023-09-10 00:17:33
  • Java中二维数组的正确使用方法介绍

    2023-11-19 16:14:18
  • Git工具 conflict冲突问题解决方案

    2023-07-27 10:27:30
  • java微信公众号支付开发之现金红包

    2023-09-01 17:28:38
  • C# web.config之<customErrors>节点说明案例详解

    2023-07-06 20:20:15
  • C#使用CallContext缓存线程数据

    2022-03-27 17:45:55
  • Java使用DateFormatter格式化日期时间的方法示例

    2021-07-15 15:29:23
  • Mybatis实现分表插件

    2023-07-23 12:41:54
  • Android开发Compose集成高德地图实例

    2022-09-05 01:44:28
  • 解决MyBatis @param注解参数类型错误异常的问题

    2023-12-01 06:41:45
  • Spring Cloud + Nacos + Seata整合过程(分布式事务解决方案)

    2021-08-31 04:26:52
  • Java异常 Factory method'sqlSessionFactory'rew exception;ested exception is java.lang.NoSuchMethodError:

    2022-03-25 15:06:42
  • java+opencv实现人脸识别功能

    2023-02-20 21:52:58
  • System.currentTimeMillis()计算方式与时间的单位转换详解

    2022-08-09 04:55:43
  • asp之家 软件编程 m.aspxhome.com