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
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
好的,您想了解关于使用 @ExceptionHandler + @ControllerAdvice +枚举实现全局异常统一处理的内容,这是一个常用的方案,可以实现全局异常的捕获和处理,让程序更加健壮和稳定。 @ExceptionHandler注解用于标记一个方法,该方法用于处理指定的异常类型。@ControllerAdvice注解用于标记一个类,该类用于处理全局异常。枚举则可以用于定义异常类型,方便异常处理时的统一管理。 在实现全局异常处理时,我们可以通过 @ExceptionHandler 注解来捕获指定的异常类型,并在方法中进行相应的处理。@ControllerAdvice注解可以让我们在一个类中定义多个 @ExceptionHandler方法,用于处理不同类型的异常。同时,我们也可以使用枚举来定义不同的异常类型,方便管理和调用。 下面是一个简单的示例,演示如何使用 @ExceptionHandler + @ControllerAdvice +枚举实现全局异常统一处理: ```java @ControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(value = BusinessException.class) @ResponseBody public ResultVO handleBusinessException(BusinessException e) { return ResultVO.error(e.getCode(), e.getMessage()); } } public enum ExceptionEnum { PARAMETER_ERROR(1001, "参数错误"), DATA_NOT_FOUND(1002, "数据不存在"), SYSTEM_ERROR(5000, "系统错误"); private final int code; private final String message; ExceptionEnum(int code, String message) { this.code = code; this.message = message; } public int getCode() { return code; } public String getMessage() { return message; } } public class BusinessException extends RuntimeException { private final int code; public BusinessException(int code, String message) { super(message); this.code = code; } public BusinessException(ExceptionEnum exceptionEnum) { super(exceptionEnum.getMessage()); this.code = exceptionEnum.getCode(); } public int getCode() { return code; } } ``` 在上面的示例中,GlobalExceptionHandler类标记了@ControllerAdvice注解,用于全局异常处理。其中,handleBusinessException方法用于处理BusinessException异常,返回一个ResultVO对象,其中包含错误码和错误信息。 BusinessException则是一个自定义的异常类,它包含一个code属性和一个message属性,用于表示异常的错误码和错误信息。同时,它还提供了一个构造方法,可以根据ExceptionEnum来构造一个BusinessException对象。 ExceptionEnum则是一个枚举类,包含了不同的异常类型,每个异常类型都有一个对应的错误码和错误信息。 在实际开发中,我们可以根据实际需求来定义不同的异常类型和错误码,以便更好地管理和调用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码上飞跃

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值