SpringBoot 之全局异常处理

  • 前言:service方法在执行过程出现异常在哪捕获?在service中需要都加try/catch,如果在controller也需要添加 try/catch,代码冗余严重且不易维护。 这时候需要在统一异常处理类中去捕获异常,无需controller捕获异常,向用户返回统一规范的响应信息。

  • 异常分两种:可预知的异常(业务判断等)由程序员在代码中主动抛出自定义异常,由SpringMVC统一捕获。

    不可预知的异常(系统bug等)由SpringMVC统一捕获Exception类型的异常。

    一、可预知的异常处理

    1.1 统一返回给前端的结果

    public interface ResultCode {
        //操作是否成功,true为成功,false操作失败
        boolean success();
        //操作代码
        int code();
        //提示信息
        String message();
    }

    1.2 定义错误代码

    @ToString
    public enum CommonCode implements ResultCode{
        SUCCESS(true,10000,"操作成功!"),
        FAIL(false,11111,"操作失败!"),
        CUSTOM(false,10003,"测试自定义异常!"),
    ​
        //操作是否成功
        boolean success;
        //操作代码
        int code;
        //提示信息
        String message;
        private CommonCode(boolean success,int code, String message){
            this.success = success;
            this.code = code;
            this.message = message;
        }
    ​
        @Override
        public boolean success() {
            return success;
        }
        @Override
        public int code() {
            return code;
        }
    ​
        @Override
        public String message() {
            return message;
        }
        
    }

    1.3在common工程定义异常类型。

    (实现RuntimeException是因为secrice有异常时不需要throws异常)

    /**
     * 自定义异常类型
     **/
    public class CustomException extends RuntimeException {
        //错误代码
        ResultCode resultCode;
    ​
        public CustomException(ResultCode resultCode){
            this.resultCode = resultCode;
        }
        public ResultCode getResultCode(){
            return resultCode;
        }
    }
    ​

    1.4 异常抛出类

    public class ExceptionCast {
        //使用此静态方法抛出自定义异常
        public static void cast(ResultCode resultCode){
            throw new CustomException(resultCode);
        }
    }
    ​

    1.5 异常捕获类

    使用 @ControllerAdvice和@ExceptionHandler注解来捕获指定类型的异常

    /**
     * 统一异常捕获类
     **/
    @ControllerAdvice   //控制器增强
    public class ExceptionCatch {
    ​
        private static final Logger LOGGER = LoggerFactory.getLogger(ExceptionCatch.class);
        //捕获CustomException此类异常
        @ExceptionHandler(CustomException.class)
        @ResponseBody
        public ResponseResult customException(CustomException customException){
            customException.printStackTrace();
            //记录日志
            LOGGER.error("catch exception:{}",customException.getMessage());
            ResultCode resultCode = customException.getResultCode();
            return new ResponseResult(resultCode);
        }
        
    }

    1.6 测试异常(在controller、service、 dao中都可以抛出异常。 )

    1.6.1 手动抛异常

    int a=1;
    if(a ==1){  //如果a等于1时
        ExceptionCast.cast(CommonCode.CUSTOM); //手动抛出自定义异常
    }

    1.6.2启动工程,扫描到异常捕获的类ExceptionCatch

    在springBoot的启动类中添加

    @ComponentScan(basePackages="com.framework")//扫描common工程下的异常类

二、不可预知异常处理 (用空指针异常测试)

1.在通用错误代码类CommCode中配置空指针异常

NULL_POINTER(false,10003,"控制针异常!"),
SERVER_ERROR(false,99999,"抱歉,系统繁忙,请稍后重试!");

2.在异常捕获类(ExceptionCatch)中添加对Exception异常的捕获:

   //捕获Exception此类异常
    @ExceptionHandler(Exception.class)
    @ResponseBody
    public ResponseResult exception(Exception exception){
       exception.printStackTrace();
        //记录日志
        LOGGER.error("catch exception:{}",exception.getMessage());
        if(EXCEPTIONS == null){
            EXCEPTIONS = builder.build();//EXCEPTIONS构建成功
        }
        //从EXCEPTIONS中找异常类型所对应的错误代码,如果找到了将错误代码响应给用户,如果找不到给用户响应99999异常
        ResultCode resultCode = EXCEPTIONS.get(exception.getClass());
        if(resultCode !=null){
            return new ResponseResult(resultCode);
        }else{
            //返回99999异常
            return new ResponseResult(CommonCode.SERVER_ERROR);
        }
​
​
    }
    static {
        //定义异常类型所对应的错误代码
        builder.put(NullPointerException.class,CommonCode.NULL_POINTER);
    }

你可能感兴趣的:(Spring,Boot,异常)