-
前言: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); }