异常统一捕获处理

  • Post author:
  • Post category:其他




1、异常的类型:

首先,我们明白异常分为

可预知异常(如空指针)



不可预知异常(如数据库连接异常)

  • 其中,可预知异常由我们主动抛出,由SpringMVC统一捕获;
  • 而不可预知异常有SpringMVC统一捕获Exception类型的异常;

而所谓异常统一捕获处理就是将可预知异常和不可预知异常

采用统一的信息格式

来表示,并且随请求响应给客户端。这样我们就可以

避免大量使用try/catch而导致的代码冗余



区别具体的错误信息



2、可预知异常实现:

下面就来讲讲如何实现可预知异常异常统一处理:

  • 1、首先我们需要定义一个自定义异常类去继承RuntimeException类:


    注:1、使用RuntimeException类而不使用Exception类是因为RuntimeException类不具有侵入性,即当我们使用throw new RuntimeException()时不需要进行异常捕获,也不需要进行异常声明;

    2、ResultCode为异常信息(code,success,错误信息)的接口,由多个子类异常对象实现

/**
 * 自定义异常类型
 * @author LR
 * @version 1.0
 **/
public class CustomException extends RuntimeException {

	//错误代码
    ResultCode resultCode;

    public CustomException(ResultCode resultCode){
        this.resultCode = resultCode;
    }
    
    //得到错误对象
    public ResultCode getResultCode(){
        return resultCode;
    }
}
  • 2、定义一个异常抛出类:


    这样我们就可以使用Exception.cast(ResultCode子类对象(异常信息对象))来抛出异常,也不会对代码有侵入性;
/**
 * @className ExceptionCast
 * @Description 异常抛出类
 * @Author RJin
 * @Date 2020/3/25 14:47
 * @Version 1.0
 */
public class ExceptionCast {

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

  • 3、定义统一异常捕获类:


    这样我们的客户端就可以拿到异常信息了
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;


/**
 * @className ExceptionCatch
 * @Description 异常捕获类
 * @Author RJin
 * @Date 2020/3/25 14:51
 * @Version 1.0
 */
@ControllerAdvice  //代表控制器增强,只要使用@ExceptionHandler(指定异常类)捕获相对应的异常类,就会进入指定的方法
public class ExceptionCatch {

    private static final Logger LOGGER = LoggerFactory.getLogger(ExceptionCatch.class);

	//捕获我们自定义的可预知异常CustomException
    @ExceptionHandler(CustomException.class)
    @ResponseBody //将返回的错误信息转换为json数据格式
    public ResponseResult customException(CustomException customException){
        //记录日志
        LOGGER.error("catch exception:{}",customException.getMessage());
        ResultCode resultCode = customException.getResultCode();   //获得异常信息对象
        return new ResponseResult(resultCode);  //请求信息的返回封装
    }
}



3、不可预知异常实现:

思路流程:在Map集合中定义异常类型对应的错误代码和错误信息,如果在Map中找到了该异常我们就将该异常对应的错误信息返回,如果没有找到,就统一返回不可预知异常(如{code: 1888, success: true, message: “未知异常”})。

实现步骤:

  • 在统一异常捕获类中定义一个ImmutableMap(google工具包中的一个Map类型,数据一旦放入该Map,将不可更改,并且该Map线程安全),其中该Map的键为Throwable的子类泛型,值为ResultCode。

    private static ImmutableMap<Class<? extends Throwable>,ResultCode> EXCEPTIONS;
    
  • 定义一个ImmutableMap的builder对象,去构建ImmutableMap:

    protected static ImmutableMap.Builder<Class<? extends Throwable>,ResultCode> builder = ImmutableMap.builder();
    
  • 定义一个static静态代码块,在builder对象中put添加异常类型对应的错误代码:

    static {
       builder.put(HttpMessageNotReadableException.class, CommonCode.FAIL);
    }
    
  • 再在统一异常捕获类中定义一个捕获Exception类的异常捕获方法:

    	//捕获Exception此类异常
        @ExceptionHandler(Exception.class)
        @ResponseBody //将返回的错误信息转换为json数据格式
        public ResponseResult exception(Exception exception){
            //记录日志
            LOGGER.error("catch exception:{}",exception.getMessage());
            if (EXCEPTIONS == null){ //如果EXCEPTIONS等于空,证明EXCEPTIONS还未构建,执行EXCEPTIONS的构建方法
                builder.build();//EXCEPTIONS构建方法
            }
            //从EXCEPTIONS中找到异常类型所对应的错误代码,如果找到了将错误代码响应给用户,如果找不到给用户响应统一返回不可预知异常
            ResultCode resultCode = EXCEPTIONS.get(exception.getClass());
            if (resultCode != null){
                return new ResponseResult(resultCode);  //请求信息的返回封装
            }else {
                return new ResponseResult(CommonCode.SERVER_ERROR);  //请求信息的返回封装
            }
        }
    

这样,我们的不可预知异常也实现了异常统一处理。

以上,就是对异常进行统一捕获处理。



版权声明:本文为weixin_43303530原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。