美文网首页
SpringBoot全局异常处理

SpringBoot全局异常处理

作者: vincent_wujia | 来源:发表于2020-05-16 17:10 被阅读0次

    1、创建自定义异常类

    这里我们继承的是运行时异常类,我们可以在这里按需求定义自己想要返回的异常类型。
    我们在使用时,可以使用try{}catch(){}来进行自定义异常的使用。

    /**
     * 自定义异常,继承运行时异常
     * @author MyException
     */
    public class BusinessException extends RuntimeException{
    
        private static final long serialVersionUID = 1L;
        /**
         * 自定义返回异常状态参数
         */
        private int code;
        /**
         * 自定义返回异常状态信息
         */
        private String errorMessage;
        /**
         * 构造方法,可以自定义返回信息
         */
        public BusinessException(String errorMessage) {
            super(errorMessage);
            this.code = HttpStatus.INTERNAL_SERVER_ERROR.value();
            this.errorMessage = errorMessage;
        }
        /**
         * 构造方法,自定义返回状态与信息
         */
        public BusinessException(Integer code, String errorMessage) {
            super(errorMessage);
            this.code = code;
            this.errorMessage = errorMessage;
        }
        /**
         * 构造方法,自己的(封装的参数)
         */
        public BusinessException(AbstractBusinessException exception) {
            super(exception.getMessage());
            this.code = exception.getCode();
            this.errorMessage = exception.getMessage();
        }
    
        public Integer getCode() {
            return code;
        }
    
        public void setCode(Integer code) {
            this.code = code;
        }
    
        public String getErrorMessage() {
            return errorMessage;
        }
    
        public void setErrorMessage(String errorMessage) {
            this.errorMessage = errorMessage;
        }
    
    }
    

    2、创建统一异常返回对象

    自定义返回模型,方便返回的数据类型管理操作,代码规范等
    这里要注意ResUtilAbstractBusinessException是封装的数据类或接口,便于数据的管理操作,代码规范等
    可以根据个人需求来进行本类的方法增加或删除

    import org.springframework.http.HttpStatus;
    import org.springframework.http.ResponseEntity;
    
    /**
     * 自定义返回模型
     * @author MyException
     */
    public class ResponseModel {
    
        /**
         * 操作成功返回的方法
         * ResUtil是我个人封装的返回数据类型
         */
        public static ResponseEntity<ResUtil> success(){
            return ResponseEntity.ok(ResUtil.success());
        }
    
        /**
         * 操作成功返回的方法
         * @param resUtil 封装类
         */
        public static ResponseEntity<ResUtil> success(ResUtil resUtil){
            return ResponseEntity.ok(resUtil);
        }
        /**
          * 操作错误返回的方法,AbstractBusinessException 也是自己写的接口
          */
        public static ResponseEntity<ResUtil> fail(AbstractBusinessException ex){
            return ResponseEntity
                    //返回服务器异常状态
                    .status(HttpStatus.INTERNAL_SERVER_ERROR)
                    //返回服务器异常数据
                    .body(ResUtil.fail(ex.getMessage()));
        }
    }
    
    

    3、创建Controller层异常控制器类

    创建异常控制器类@ControllerAdvice@ExceptionHandler注解必不可少
    这里我捕获了三个异常类型,大家可以按需求进行各自的异常类型细化抛出
    ExceptionEnum这是自定义的异常枚举类

    import lombok.extern.slf4j.Slf4j;
    import org.springframework.http.ResponseEntity;
    import org.springframework.web.bind.annotation.ControllerAdvice;
    import org.springframework.web.bind.annotation.ExceptionHandler;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    /**
     * controller层异常统一管理类
     * @author MyException
     */
    @Slf4j 
    @ControllerAdvice
    public class ExceptionControllerAdvice {
        /**
         * 这里是捕获的顶级异常,所有异常的父类
         * 当我们没有捕获细化异常时,系统或把捕获到的异常直接在这里进行返回
         */
        @ResponseBody
        @ExceptionHandler(value = Exception.class)
        public ResponseEntity<ResUtil> errorHandler(Exception e){
            //输出枚举类中的自定义异常信息,再输出异常
            log.error(ExceptionEnum.EXCEPTION_MSG.getMessage(),e);
            return ResponseModel.fail(ExceptionEnum.EXCEPTION_MSG);
        }
        /**
         * 这里是捕获的自定义异常,继承的是运行时异常类(运行时异常继承顶级异常类)
         * 当出现运行时异常以及他的子类异常的时候我们会在这里进行捕获并返回
         * 这里主要用于用户自己抛出的异常捕获
         */
        @ResponseBody
        @ExceptionHandler(value = BusinessException.class)
        public ResponseEntity<ResUtil> errorHandler(BusinessException ex){
            //输出枚举类中的自定义异常信息,再输出异常
            log.error(ExceptionEnum.EXCEPTION_MSG.getMessage(),ex);
            return ResponseModel.fail(ExceptionEnum.EXCEPTION_MSG);
        }
        /**
         * 这里是捕获的运算异常,继承的是运行时异常类(运行时异常继承顶级异常类)
         * 当出现运算异常的时候我们会在这里进行捕获并返回
         * 本次测试也是使用运算异常测试
         */
        @ResponseBody
        @ExceptionHandler(value = ArithmeticException.class)
        public ResponseEntity<ResUtil> errorHandler(ArithmeticException ax){
            //输出枚举类中的自定义异常信息,再输出异常
            log.error(ExceptionEnum.EXCEPTION_MSG.getMessage(),ax);
            return ResponseModel.fail(ExceptionEnum.EXCEPTION_MSG);
        }
    }
    
    

    全局异常首先捕获的是最小的异常,当你没有捕获这个异常时,会捕获他的父类异常,如果这个父类异常你也没有捕获,那就会捕获到爷爷类(父类的父类),最终捕获到Exception这个最大的异常类

    4、创建一些必备类

    然后这里是我demo里面的一些必须要使用到的类

    • 异常枚举类
    /**
     * 异常枚举类
     * @author MyException
     */
    public enum ExceptionEnum implements AbstractBusinessException {
        //系统繁忙异常
        EXCEPTION_MSG(500,"系统繁忙"),
        ;
    
        private int code;
        private String message;
    
        ExceptionEnum(int code,String message){
            this.code = code;
            this.message = message;
        }
    
        public int getCode() {
            return this.code;
        }
    
        public void setCode(int code) {
            this.code = code;
        }
    
        public String getMessage() {
            return this.message;
        }
    
        public void setMessage(String message) {
            this.message = message;
        }
    }
    
    
    • 抽象业务异常接口
    /**
     * 抽象业务异常
     * @author MyException
     */
    public interface AbstractBusinessException {
    
        /**
         * 获取异常状态码
         * @return 数值
         */
        int getCode();
    
        /**
         * 获取异常信息
         * @return 字符
         */
        String getMessage();
    }
    
    
    • 统一返回封装类
      这里可以更具自己的需求创建或修改自己需要的方法,配合使用
    import lombok.Data;
    import org.springframework.http.HttpStatus;
    
    import java.util.UUID;
    
    /**
     * 统一返回封装类
     * @author MyException
     */
    @Data
    public class ResUtil {
    
        private static final long serialVersionUID = 1L;
        /**
         * 数据体
         */
        private Object data;
        /**
         * 提示消息
         */
        private String msg;
        /**
         * 总条数
         */
        private int allCount;
        /**
         * 状态码
         */
        private String code;
        /**
         * 毫秒级时间
         */
        private long time;
        /**
         * uuid
         */
        private String token;
        /**
         * 请求是否成功
         */
        private boolean success;
        /**
         * 请求状态
         */
        private int is;
    
        private ResUtil(){}
    
        public static ResUtil success(){
            ResUtil res = new ResUtil();
            res.setIs(ResConstant.RET_YES);
            res.setMsg(SystemConstant.OPERATION_SUCCESS);
            res.setAllCount(0);
            res.setData("");
            res.setCode(String.valueOf(HttpStatus.OK.value()));
            res.setTime(System.currentTimeMillis());
            res.setToken(UUID.randomUUID().toString());
            res.setSuccess(true);
            return res;
        }
    
        public static ResUtil fail(BusinessException ex) {
            ResUtil res = new ResUtil();
            res.setIs(ResConstant.RET_NO);
            res.setMsg(ex.getErrorMessage());
            res.setAllCount(0);
            res.setData("");
            res.setCode(String.valueOf(ex.getCode()));
            res.setTime(System.currentTimeMillis());
            res.setToken(UUID.randomUUID().toString());
            res.setSuccess(false);
            return res;
        }
    
        public static ResUtil fail(String msg) {
            ResUtil res = new ResUtil();
            res.setIs(ResConstant.RET_NO);
            res.setMsg(msg);
            res.setAllCount(0);
            res.setData("");
            res.setCode(String.valueOf(HttpStatus.BAD_REQUEST.value()));
            res.setTime(System.currentTimeMillis());
            res.setToken(UUID.randomUUID().toString());
            res.setSuccess(false);
            return res;
        }
    }
    
    
    • 系统常量
    /**
     * 系统常量
     * @author MyException
     */
    public class SystemConstant {
    
        /**
         * 请求操作成功返回提示
         */
        public static final String OPERATION_SUCCESS = "操作成功";
        /**
         * 请求操作失败返回提示
         */
        public static final String OPERATION_FAIL = "操作失败";
    }
    
    /**
     * 参数常量
     * @author MyException
     */
    public class ResConstant {
    
        /**
         * 返回值--失败
         */
        public static final int RET_NO = 0;
        /**
         * 返回值--成功
         */
        public static final int RET_YES = 1;
        /**
         * 返回值--超时
         */
        public static final int RET_OVER = 2;
    }
    

    小吾的分割线


    5、华丽丽的测试

    import lombok.extern.slf4j.Slf4j;
    import org.springframework.http.ResponseEntity;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    /**
     * @author MyException
     */
    @Slf4j
    @RestController
    @RequestMapping("/exceptionController")
    public class ExceptionController {
          /**
           * 这里直接会抛出运算异常,并且被捕获
           */
        @GetMapping("/test1Exception")
        public ResponseEntity<ResUtil> test1Exception(){
            log.debug("**************");
            int x = 2/0;
            return ResponseModel.success();
        }
          /**
           * 这里直接会抛出自定义异常,并且被捕获
           */
        @GetMapping("/test2Exception")
        public ResponseEntity<ResUtil> test2Exception(){
            log.debug("**************");
            try{
                int x = 2/0;
            }catch (Exception e){
                throw new BusinessException("异常111");
            }
            return ResponseModel.success();
        }
    }
    

    这里附上两张测试截图


    运算异常捕获测试
    自定义异常测试

    至此SpringBoot全局异常就写完了,如有不懂可以加SpringBoot技术交流群14群号:719099151我是小吾,有问题可以直接在群里@我

    相关文章

      网友评论

          本文标题:SpringBoot全局异常处理

          本文链接:https://www.haomeiwen.com/subject/ejqrohtx.html