Springboot接口返回值的统一格式

本文介绍了SpringBoot中接口返回值的统一格式化,包括String、Object、void和Exception四种类型的返回,并提出了接口返回值应遵循统一标准以方便客户端处理。通过创建ApiResult类和状态码枚举类实现返回值封装。进一步地,利用Spring AOP思想,通过实现ResponseBodyAdvice接口和使用@ControllerAdvice注解,实现了Controller方法返回值的全局统一处理,增强了Controller的拓展功能,包括响应体格式化和全局异常处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • springboot 默认情况下的返回数据类型包括以下几种:

    • String型 :返回字符串

      @GetMapping(value="/getstr/{id}")
      public String getstr(@PathVariable("id") Integer id){
          ...
          return "index";
      }
      
    • Object型:返回一个Json表示对象

      @GetMapping(value="/getObject")
      public UserVO getObject(){
          UserVO vo=new UserVO();
          vo.setUsername("agan");
          return vo;
      }
      
    • void型:返回空值

      @GetMapping(value="/empty")
      public void  empty(){
      
      }
      
    • Exception型:返回错误信息或异常信息

      @GetMapping(value="/error")
      public void  error(  ){
          int i=9/0;
      }
      

      如下:

      {
        "timestamp": "2019-09-07T10:35:56.658+0000",
        "status": 500,
        "error": "Internal Server Error",
        "message": "/ by zero",
        "path": "/user/error"
      } 
      

若是所有的接口按照以上四种方式实现,当你和客户端开发人员联调接口,会造成很大的麻烦,因为这些接口返回值没有统一的格式,客户端开发人员处理返回值将无从下手。

所以我们应该统一 response 标准格式。

  • response 代码封装(使用一个网上的常用案例)

    • 创建用于统一处理返回值的 ApiResult

      // 这是我们需要返回的内容
      {
         "status":0, // 状态码
         "desc":"成功",  // 状态信息
         "data":"test" // 返回值
      }
      
      

      开始转换后成一个 Result 处理类

      public class ApiResult<T>{
          // status:状态码
          private Integer status;
          // desc:对状态码的描述
          private String desc;
          // data:采用泛型,表示返回值
          private T data;
          
          /*构造函数 + getter + setter 太多了,这里我就省略掉了,自己试验的时候记着补上*/
          
          // 成功创建Result,没有data值
          public static ApiResult suc(){
              ApiResult result = new ApiResult();
              result.setResultCode(ResultCode.SUCCESS);
              return result;
          }
          
          // 成功创建Result,有data值
          public static ApiResult suc(Object data){
              ApiResult result = new ApiResult();
              result.setResultCode(ResultCode.SUCCESS);
              result.setData(data);
              return result;
          }
          
          // 失败,指定status,desc
          public static Result fail(Integer status, String desc) {
              Result result = new Result();
              result.setStatus(status);
              result.setDesc(desc);
              return result;
          }
      
          // 失败,指定ResultCode枚举
          public static Result fail(ResultCode resultCode) {
              Result result = new Result();
              result.setResultCode(resultCode);
              return result;
          }
      
          // 把ResultCode枚举转换为ResResult
          private void setResultCode(ResultCode code) {
              this.status = code.code();
              this.desc = code.message();
          }
      }
      

      创建状态码枚举类:相关的 Codedesc 可以自定义一个格式。

      public enum ResultCodeEnum  {
      
      	// 成功状态码
      	SUCCESS("000", "操作成功"),
      
      	SYSTEM_ERROR("001", "系统异常,请稍后重试"),
      	UNAUTHORIZED("002", "验证失败"),
       
      	PARAM_IS_INVALID("003", "参数无效"),
      
      	USER_HAS_EXISTED("004", "用户名已存在"),
      	USER_NOT_FIND("005", "用户名不存在");
      	
          private String code;
      	private String message;
      
      	private ResultCodeEnum(String code, String message) {
      		this.code = code;
      		this.message = message;
      	}
      
      	public String code() {
      		return this.code;
      	}
      
      	public String message() {
      		return this.message;
      	}
      
      }
      
      

      测试类

      @RestController
      @RequestMapping("/user")
      public class UserController {
      
          @GetMapping(value="/getResult")
          public Result getResult(  ){
              return Result.suc("test");
          }
      }
      
      
      

在这里插入图片描述
最终浏览器接收到的结果是一个 JSON 格式的字符串,做相应处理就好。

  • 对于这种封装风格的进一步优化

    • 为了方便理解,这里我们可以带入 Spring AOP 的思想,可以看到如果 Controller 中的接口处理方法增多,我们将对每一个接口的返回值手动的调用 Result.suc() 统一处理方法。那么我们可以把这些重复出现的代码当做 AOP 中的 横切逻辑代码通过注解的方式,省去这部分代码。

    • 这里我们需要去实现 ResponseBodyAdvice 这个接口,它会拦截 Controller 方法的返回值,统一处理返回值/响应体,一般用来做 response 的统一格式、加解密、签名等等。

    • 另外,我们还需要给 ResponseBodyAdvice实现类 加上注解 @ControllerAdvice 这个注解的作用是增强 Controller 的拓展功能类,包括两个方面的增强:

      • Controller全局数据进行统一处理
      • Controller全局异常进行统一处理

      ResponseBodyAdvice 实现类代码:

      @ControllerAdvice(basePackages = "com.miger.module.controller") // backPackages属性是用于定位controller的位置
      public class RrsultAdvice implements ResponseBodyAdvice<Object> {
      
          // 确认是否支持 advice 功能,true 表示支持,false 表示不支持
          @Override
          public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
              return true;
          }
      
          // 处理 response 的具体业务的方法
          @Override
          public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
              if (o instanceof String) {
                  return JSON.toJSONString(ApiResult.suc(o));
              }
              return ApiResult.suc(o);
          }
      }
      
      

参考链接https://blog.youkuaiyun.com/shenhuxi10000/article/details/104622770/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值