• Spring注解之@RestControllerAdvice


    前言

        前段时间部门搭建新系统,需要出异常后统一接口的返回格式,于是用到了Spring的注解@RestControllerAdvice。现在把此注解的用法总结一下。

    用法

        首先定义返回对象ResponseDto

     1 package com.staff.points.common;
     2 
     3 import lombok.Data;
     4 
     5 import java.io.Serializable;
     6 
     7 @Data
     8 public class ResponseDto<T> implements Serializable {
     9     private static final long serialVersionUID = -284719732991678911L;
    10 
    11     private String code;
    12 
    13     private String message;
    14 
    15     private T data;
    16 
    17     public static <T> ResponseDto<T> assemblingSuccessResponse(T data) {
    18         ResponseDto<T> responseDto = new ResponseDto<>();
    19         responseDto.setCode(ResponseCodeEnum.SUCCESS.getCode());
    20         responseDto.setMessage(ResponseCodeEnum.SUCCESS.getMessage());
    21         responseDto.setData(data);
    22         return responseDto;
    23     }
    24 
    25     public static <T> ResponseDto<T> assemblingSuccessResponse() {
    26         ResponseDto<T> responseDto = new ResponseDto<>();
    27         responseDto.setCode(ResponseCodeEnum.SUCCESS.getCode());
    28         responseDto.setMessage(ResponseCodeEnum.SUCCESS.getMessage());
    29         responseDto.setData(null);
    30         return responseDto;
    31     }
    32 
    33     public static <T> ResponseDto<T> assemblingFailureResponse(ResponseCodeEnum data) {
    34         ResponseDto<T> responseDto = new ResponseDto<>();
    35         responseDto.setCode(data.FAILURE.getCode());
    36         responseDto.setMessage(data.FAILURE.getMessage());
    37         return responseDto;
    38     }
    39 
    40     public static <T> ResponseDto<T> assemblingFailureResponse() {
    41         ResponseDto<T> responseDto = new ResponseDto<>();
    42         responseDto.setCode(ResponseCodeEnum.FAILURE.getCode());
    43         responseDto.setMessage(ResponseCodeEnum.FAILURE.getMessage());
    44         return responseDto;
    45     }
    46 }

        然后定义返回码的枚举类,此处只定义了两种,有需要可以往下添加很多。

     1 package com.staff.points.common;
     2 
     3 import lombok.AllArgsConstructor;
     4 import lombok.Getter;
     5 
     6 @AllArgsConstructor
     7 @Getter
     8 public enum ResponseCodeEnum {
     9     SUCCESS("00", "成功"),
    10     FAILURE("01", "系统异常");
    11 
    12 
    13     private String code;
    14     private String message;
    15 }

        下面是自定义的异常类

     1 package com.staff.points.common;
     2 
     3 import lombok.Data;
     4 
     5 @Data
     6 public class StaffPointsException extends RuntimeException{
     7     private String code;
     8     private String message;
     9     public StaffPointsException () {}
    10 
    11     public StaffPointsException (Exception e) {
    12         super(e);
    13     }
    14 
    15     public StaffPointsException (String code, String message) {
    16         super(message);
    17         this.code = code;
    18         this.message = message;
    19     }
    20 
    21     public StaffPointsException (ResponseCodeEnum codeEnum) {
    22         super(codeEnum.getMessage());
    23         this.code = codeEnum.getCode();
    24         this.message = codeEnum.getMessage();
    25     }
    26 }

        然后是关键的@RestControllerAdvice修饰的类

     1 package com.staff.points.exception;
     2 
     3 import com.staff.points.common.ResponseCodeEnum;
     4 import com.staff.points.common.ResponseDto;
     5 import com.staff.points.common.StaffPointsException;
     6 import org.slf4j.Logger;
     7 import org.slf4j.LoggerFactory;
     8 import org.springframework.stereotype.Component;
     9 import org.springframework.web.bind.annotation.ExceptionHandler;
    10 import org.springframework.web.bind.annotation.RestControllerAdvice;
    11 
    12 @RestControllerAdvice
    13 @Component
    14 public class UnifyExceptionHandler {
    15     private Logger logger = LoggerFactory.getLogger(UnifyExceptionHandler.class);
    16 
    17     @ExceptionHandler(Exception.class)
    18     public ResponseDto handlerCommonException (Exception e) {
    19         ResponseDto responseDto = new ResponseDto<>();
    20         responseDto.setCode(ResponseCodeEnum.FAILURE.getCode());
    21         responseDto.setMessage(ResponseCodeEnum.FAILURE.getMessage());
    22         logger.info("UnifyExceptionHandler.handlerCommonException exception:" + e);
    23         return responseDto;
    24     }
    25     // 报StaffPointException时,对其进行拦截并处理的方法
    26     @ExceptionHandler(StaffPointsException.class)
    27     public ResponseDto handlerCustomizeException (StaffPointsException e) {
    28         ResponseDto responseDto = new ResponseDto<>();
    29         responseDto.setCode(e.getCode());
    30         responseDto.setMessage(e.getMessage());
    31         logger.info("UnifyExceptionHandler.handlerCustomizeException StaffPointsException:" + e);
    32         return responseDto;
    33     }
    34 }

        运行代码时,如果出现了StaffPointException,那么就会被拦截进入第27行的方法(就是说可以自由的在业务代码里往外throw自定义异常了);如果出现了其他的异常,则进入18行的方法,统一返回。

    验证一下,在代码里造一个NPE异常时,返回结果:

    1 {
    2   "code": "01",
    3   "message": "系统异常",
    4   "data": null
    5 }

        造一个StaffPointsException异常时,返回结果:

    1 {
    2   "code": "99",
    3   "message": "自定义业务异常",
    4   "data": null
    5 }

        它的作用原理,大体是先在spring初始化时将类扫描进容器,出异常后,在DispatcherServlet类的doDispatch方法中调用了对异常的拦截处理。

    小结

        看@RestControllerAdvice源码可以知道,它就是@ControllerAdvice和@ResponseBody的合并。此注解通过对异常的拦截实现的统一异常返回处理,如果大家在项目中有类似的需求,不妨试一下,好用又方便。

  • 相关阅读:
    一起学Vue之表单输入绑定
    简单易懂的单元测试框架-gtest(二)
    简单易懂的单元测试框架-gtest(一)
    最常用设计模式-模板方法模式
    最常用设计模式-简单工厂模式
    最常用设计模式-单例模式
    端口复用后门
    内存取证工具-volatility、foremost
    python的exe反编译
    Linux加密known_hosts文件中的IP
  • 原文地址:https://www.cnblogs.com/zzq6032010/p/11605349.html
Copyright © 2020-2023  润新知