springboot系列三:@ControllerAdvice实现全局响应结果格式化处理

定义ResultCode

这里先简单定义四个状态:101,102,103,200,如下

@AllArgsConstructor
@NoArgsConstructor
@Getter
public enum ResultCode {
    FAILURE(100, "请求失败"),
    TOKEN_EXPIRED(101, "请登录"),
    NO_PERMISSION(102, "无权限"),
    SUCCESS(200, "请求成功");

    private Integer code;
    private String description;
}

构造响应数据结构

数据结构分为两种,一种带分页,一种不带分页。

/**
*
* @author  yangyile
* @since 2023-03-18
*/
@AllArgsConstructor
@NoArgsConstructor
@Getter
public class ResultInfo implements Serializable {
    private Object data;
    private Integer code;
    private String msg;
    private Integer total;

    public ResultInfo(Object data, Integer code, String msg) {
        this.data = data;
        this.code = code;
        this.msg = msg;
    }

    public static ResultInfo success(Object data) {
        return new ResultInfo(data, ResultCode.SUCCESS.getCode(), "success");
    }

    public static ResultInfo success(Object data, Integer total) {
        return new ResultInfo(data, ResultCode.SUCCESS.getCode(), "success", total);
    }

    public static ResultInfo success(Object data, Integer code, String msg) {
        return new ResultInfo(data, code, msg);
    }

    public static ResultInfo success(Object data, Integer code, String msg, Integer total) {
        return new ResultInfo(data, code, msg, total);
    }

    public static ResultInfo fail(Object data, Integer code, String msg) {
        return new ResultInfo(data, code, msg);
    }
}

定义响应格式化注解

该注解放在类上。告诉spring容器,该类下所有http请求方法返回的数据都会被包装。

@ControllerAdvice(annotations = {ResponseFormat.class})
public class GlobalResponseInterceptor implements ResponseBodyAdvice<Object> {
    @Override
    public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
        return true;
    }

    @Override
    public Object beforeBodyWrite(Object body,
                                  MethodParameter methodParameter,
                                  MediaType mediaType,
                                  Class<? extends HttpMessageConverter<?>> aClass,
                                  ServerHttpRequest serverHttpRequest,
                                  ServerHttpResponse serverHttpResponse) {
        final String returnTypeName = methodParameter.getParameterType().getName();

        if("void".equals(returnTypeName)) {
            // 返回类型为void
            return ResultInfo.success(null);
        } else if(!mediaType.includes(MediaType.APPLICATION_JSON) || "com.yyl.system.response.ResultInfo".equals(returnTypeName)) {
            // 返回类型为json字符串或者为ResultInfo
            return body;
        } else if(body instanceof ArrayList) {
            // 返回结果为List,但没有分页
            return ResultInfo.success(body, ((ArrayList<?>) body).size());
        } else if(body instanceof HashMap && (Boolean) ((HashMap<?, ?>) body).get("total")) {
            // 返回结果带有分页
            return ResultInfo.success(body, (Integer) ((HashMap<?, ?>) body).get("total"));
        }

        return ResultInfo.success(body);
    }
}

@ControllerAdvice注解

@ControllerAdvice注解是Spring3.2中新增的注解,学名是Controller增强器,作用是给Controller控制器添加统一的操作或处理。
@ControllerAdvice(annotations = {ResponseFormat.class}),改行代码的意思就是以@ResponseFormat注解为切入点,@ResponseFormat注解的类的所有controller方法都要经过处理后返回。

重写beforeBodyWrite方法

参数说明:

  • body:controller方法返回的数据;
  • methodParameter:controller方法的有关信息,参数、返回类型等等;
  • aClass:报文信息转换器,可将java对象转化为JSON格式的响应报文,在这里可以对响应体进行改写;
  • serverHttpRequest:请求体;
  • serverHttpResponse:响应体;
    该方法体中有5个分支来处理响应结果返回:
  • 返回类型为void,data直接返回null;
  • 如果返回格式化的json数据或者ResultInfo格式数据,那么直接返回body;
  • 如果返回ArrayList,但没有分页,那么返回body和数据总数;
  • 如果返回ArrayList,并带有分页,则返回分页数据及数据总数;
  • 其它情况,则返回body;

使用示例

@Api(tags = {"系统用户"})
@RestController
@RequestMapping("/user")
@ResponseFormat
public class UserController {
    @Autowired
    private IuserService userService;

    @ApiOperation(value = "获取用户列表", notes = "获取用户列表,支持分页和根据userName关键字查询")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "page", value = "", paramType = "query", dataType = "Integer"),
            @ApiImplicitParam(name = "limit", value = "", paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "userName", value = "用户名", paramType = "query", dataType = "String")
    })
    @GetMapping("/getUserList")
    public List<Map<String,Object>> getUserList() {
        return userService.getUserList();
    }

    @ApiOperation(value = "添加用户", notes = "添加用户")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "userName", required = true, value = "用户名", paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "password", required = true, value = "密码", paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "isEnable", required = true, value = "是否启用", paramType = "query", dataType = "Integer"),
            @ApiImplicitParam(name = "nickName", value = "别名", paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "avatar", value = "头像", paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "age", value = "年龄", paramType = "query", dataType = "Integer"),
            @ApiImplicitParam(name = "birthday", value = "生日", paramType = "query", dataType = "Date"),
            @ApiImplicitParam(name = "hobby", value = "爱好", paramType = "query", dataType = "String")
    })
    @GetMapping("/addUser")
    public Integer addUser(UserEntity user) {
        return userService.addUser(user);
    }
}

给UserController类添加注解@ResponseFormat,表示其方法返回数据会被全局处理,然后返回。

效果

{
  "data": [
    {
      "id": 2,
      "userName": "test",
      "password": "123",
      "isEnable": 1,
      "nickName": null,
      "avatar": null,
      "age": null,
      "birthday": null,
      "hobby": null,
      "updateTime": "2023-03-18T12:27:26.000+0000",
      "createTime": "2023-03-18T12:27:26.000+0000"
    },
    {
      "id": 3,
      "userName": "test",
      "password": "123",
      "isEnable": 1,
      "nickName": null,
      "avatar": null,
      "age": null,
      "birthday": null,
      "hobby": null,
      "updateTime": "2023-03-18T12:35:26.000+0000",
      "createTime": "2023-03-18T12:35:26.000+0000"
    }
  ],
  "code": 200,
  "msg": "success",
  "total": 2
}

你可能感兴趣的:(#,springboot,java,全局响应处理,springboot)