SpringBoot之全局异常处理

栏目: Java · 发布时间: 5年前

内容简介:本文主要为了实现全局异常处理的逻辑,只举简单业务某公司部门需增加员工,处理流程:1先根据员工编号查询员工对象,2判断员工对象是否有信息,即是否不为空,3若有信息,则说明已存在,无需再添加,若不是,则直接添加。代码如下:
  • 针对代码中的异常,常规有两种处理方式,一种throws直接抛出,另一种try..catch捕获。

  • java 项目中,有可能存在人为逻辑的异常,也可能为取得异常的详情,或是保证程序在异常时继续向下执行,会采用第二种处理方式。

  • 但是,代码中每一处异常都来捕获,会使代码什么冗余且不利于维护。

解决思路

  • 定义一个全局异常处理类,返回统一规范的异常信息;

  • 处理逻辑是,先判定是否会出现异常,再执行后续具体的业务。

业务举例

本文主要为了实现全局异常处理的逻辑,只举简单业务

某公司部门需增加员工,处理流程:1先根据员工编号查询员工对象,2判断员工对象是否有信息,即是否不为空,3若有信息,则说明已存在,无需再添加,若不是,则直接添加。

代码如下:

public class MyService {
    // 注入dao层
    @Autowired
    EmployeeecMapper employeeecMapper;

    /**
     * 添加员工信息
     * @param employee 员工对象
     * @return 影响的行数
     */
    public int add(Employee employee) {
        // 根据id查询员工对象
        Employeeec emp = employeeecMapper.selectByPrimaryKey(employee.getId());
        // 判断是否已有该员工
        if (emp != null){
            // 已有,抛出异常,异常信息为已有该员工
            throw new RuntimeException("异常代码:1201,错误信息:该员工已存在");
        }
        // 没有,插入该员工
        return employeeecMapper.insert(emp);
    }
}
复制代码

异常处理流程

业务中存在运行时异常和业务逻辑异常,前者不运行时很难察觉,后者在遍及业务时就可以定义出来,因此异常分为不可预知异常和可知异常。流程如下:

@ControllerAdvice
SpringMVC
RuntimeException

可知异常

定义异常信息类,变量为错误代码和错误信息,捕获自定义异常时,直接将该对象返回

不可知异常

定义一个map,将常见的异常存入其中,并定义错误代码。对于其他不常见的异常,即map中没有的,同一一个异常对象返回即可。

异常处理代码流程

可知异常

1、定义打印异常信息与返回结果的接口

public interface ResultCode {
    // 操作是否成功
    boolean success();

    // 操作结果代码
    long code();

    // 提示信息
    String message();
}
复制代码
public interface Response {
    public static final boolean SUCCESS = true;
    public static final int SUCCESS_CODE = 10000;
}
复制代码

2、定义打印异常信息的枚举类和返回结果类

@ToString
public enum  CommonCode implements ResultCode {
    NO_PAGE(false,404,"没有信息"),
    FAIL(false,500,"操作失败!"),
    SUCCESS(true,200,"操作成功!");

    // 结果信息
    boolean success;
    long code;
    String message;
    
    // 带参构造
    CommonCode(boolean success, long code, String message) {
        this.success = success;
        this.code = code;
        this.message = message;
    }

    @Override
    public boolean success() {
        return true;
    }

    @Override
    public long code() {
        return code;
    }

    @Override
    public String message() {
        return message;
    }
}
复制代码
@Data
@ToString
public class ResponseResult implements Response {

    boolean success = SUCCESS;

    long code = SUCCESS_CODE;

    String message;

    public ResponseResult(ResultCode resultCode){
        this.success = resultCode.success();
        this.code = resultCode.code();
        this.message = resultCode.message();
    }
}
复制代码

3、定义错误异常类

public class CustomException extends RuntimeException{

    @Autowired
    ResultCode resultCode;
    
    // 带参构造
    public CustomException(ResultCode resultCode){
        this.resultCode = resultCode;
    }
    
    // getter
    public ResultCode getResultCode(){
        return resultCode;
    }
}
复制代码

4、定义异常抛出类

public class ExceptionCast {

    // 静态方法
    public static void cast(ResultCode resultCode){
        throw new CustomException(resultCode);
    }
}
复制代码

5、定义异常捕获类,使用 ControllerAdvice 控制器增强的注解,并在捕获CustomException异常的方法上加 ExceptionHandler 注解,即可捕获该类的所有异常,返回json数据。

@ControllerAdvice 
public class ExceptionCatch {

    /**
     * 捕获CustomException类异常
     * @param customException
     * @return 结果信息,json数据
     */
    @ExceptionHandler(CustomException.class)
    @ResponseBody
    public ResponseResult customException(CustomException customException){
        ResultCode resultCode = customException.getResultCode();
        return new ResponseResult(resultCode);
    }
}
复制代码

6、在业务中抛出异常

public class MyService {

    @Autowired
    EmployeeecMapper employeeecMapper;

    public int add(Employee employee) {
        Employeeec emp = employeeecMapper.selectByPrimaryKey(employee.getId());
        if (emp != null){
            ExceptionCast.cast(CommonCode.FAIL);
        }
        return employeeecMapper.insert(emp);
    }
}
复制代码

不可知异常处理

1、类似可知异常,先添加错误代码,如

UNAUTHORISE(false,510,"没有权限"),
复制代码

2、在异常捕获类中添加不可知异常的捕获方法。该方法中,定义一个只读的map存储异常类型的错误代码的映射,map中没有的元素,同一用错误代码999来定义。

UNKNOWNERROR(false,999,"未知异常"),
复制代码
@ControllerAdvice
public class ExceptionCatch {

    // 定义map,存贮常见错误信息。该类map不可修改
    private static ImmutableMap<Class<? extends Throwable>,ResultCode> EXCEPTIONS;
    // 构建ImmutableMap
    protected static ImmutableMap.Builder<Class<? extends Throwable>,ResultCode> builder = ImmutableMap.builder();

    @ExceptionHandler(CustomException.class)
    @ResponseBody
    public ResponseResult customException(CustomException customException){
        ResultCode resultCode = customException.getResultCode();
        return new ResponseResult(resultCode);
    }

    /**
     * 捕获非自定义类异常
     * @param exception
     * @return
     */
    @ExceptionHandler(Exception.class)
    @ResponseBody
    public ResponseResult exception(Exception exception){
        // 记录日志
        LOGGER.error("catch exception ==> ",exception.getMessage());
        if (EXCEPTIONS == null){
            EXCEPTIONS = builder.build();
        }
        ResultCode resultCode = EXCEPTIONS.get(exception.getClass());
        if (resultCode != null){
            return new ResponseResult(resultCode);
        }else {
            return new ResponseResult(CommonCode.UNKNOWNERROR);
        }
    }

    static {
        builder.put(HttpMessageNotReadableException.class, CommonCode.INVALID_PARAM);
    }
}
复制代码

完成~~


以上所述就是小编给大家介绍的《SpringBoot之全局异常处理》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

豆瓣,流行的秘密

豆瓣,流行的秘密

黄修源 / 机械工业出版社 / 2009-9 / 29.00

380万人为何会齐聚豆瓣? HIN1和SARS是如何传播扩散开的? 贾君鹏何以快速窜红网络? 通过创新扩散的理论的分析和说明,给出了所有这些问题的答案! 这本书从豆瓣的流行现象说开来,应用了创新扩散等传播学道理来解释了豆瓣如何流行起来,同时作者还同时用创新扩散的理论解释了为何会出现世界变平的现象,长尾理论,SARS病毒的高速传播等。 作者以前任豆瓣设计师的身份以自己亲......一起来看看 《豆瓣,流行的秘密》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具