SpringBoot之全局异常解决

作者 : 开心源码 本文共4529个字,预计阅读时间需要12分钟 发布时间: 2022-05-12 共165人阅读

异常解决问题分析

异常如何解决

问题引入

  • 针对代码中的异常,常规有两种解决方式,一种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);    }}

异常解决流程

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

  1. 自己设置全局异常类,使用@ControllerAdvice,控制器加强
  2. 自己设置错误代码及错误信息,两种异常最终会采用统一的信息格式来表示,错误代码+错误信息。
  3. 对于可预知的异常由程序员在代码中主动抛出,由SpringMVC统一捕获。
  4. 不可预知异常通常是因为系统出现bug、或者少量外界因素(如网络波动、服务器宕机等),异常类型为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、定义打印异常信息的枚举类和返回结果类

@ToStringpublic 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@ToStringpublic 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、相似可知异常,先在CommonCode类中增加错误代码,如

UNAUTHORISE(false,510,"没有权限"),

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

UNKNOWNERROR(false,999,"未知异常"),
@ControllerAdvicepublic 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);    }}

读者分享

在这给大家推荐一个微信公众号,那里每天都会有技术干货、技术动向、职业生涯、行业热点、职场趣事等一切有关于程序员的内容分享。更有海量Java架构、移动互联网架构相关源码视频,面试资料,电子书籍截止于4月28日免费发放。我看了觉得资源还不错,假如你们有需要的话,扫描下方二维码关注wx公众号免费获取↓↓↓

资源大本营↓↓↓

Java架构资料
Java源码解析,到各种框架学习,再到项目实战,一应俱全,包括但不限于:Spring、Mybatis等源码、Java进阶、Java架构师、虚拟机、性能优化、并发编程、数据结构和算法。

Java架构视频资料
Java架构视频资料
java架构面试专题资料

移动互联网架构资料
Android进阶、Android架构、APP开发、NDK板块开发、小程序开发、微信开发。

Android架构资料

说明
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » SpringBoot之全局异常解决

发表回复