java实现统一异常处理的示例

 更新时间:2021年06月19日 14:14:11   作者:迷路人~  
一个全局异常处理类需要处理三类异常1.业务类异常,2.运行时异常 ,3.Error,本文给大家介绍java实现统一异常处理的示例,感兴趣的朋友一起看看吧

对于Dao层 和Service产生的异常要一直网上抛,直至Controller层,但是对于controller层不能处理的异常也不能直接抛给前端。

为什么不能在service处理异常?

答:Service 层往往涉及数据库事务,出现异常同样不适合捕获,否则事务无法自动回滚。此外 Service 层涉及业务逻辑,有些业务逻辑执行中遇到业务异常,可能需要在异常后转入分支业务流程。如果业务异常都被框架捕获了,业务功能就会不正常。【引用:极客时间的Java业务开发常见错误100例】

实现统一异常处理:

在spring框架下实现一个异常处理的类,用 @RestControllerAdvice + @ExceptionHandler

进行修饰:

即@RestControllerAdvice默认会拦截 controller类上抛出的不能处理的异常

一个全局异常处理类需要处理三类异常: 1.业务类异常,2.运行时异常 ,3.Error

1.运行时异常

/**
 * @创建人: liup
 * @创建时间: 2021/6/18
 * @描述   全局异常捕获处理类
 */
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
 
    
    /**
    * @Author:  liup
    * @date:  2021/6/18 14:34
      方法实现说明:  拦截运行时异常
    */
    @ExceptionHandler(value = RuntimeException.class)
    public R runtimeExceptionHandle(RuntimeException e){
        log.error("捕捉到运行时异常",e);
        return R.failed("未知错误");
    }
}

目前仅是拦截运行时异常

R 是返回的消息体:

那如果不使用GlobalExceptionHandler,会报出什么错误呢?

这个错误是在service层抛出的,当从redis 通过key获取一个已删除的value时,redis返回的是null,但是我没有判断这个value是否为null,就将其打印出来:

log.info(authInfoVo.toString());

注意:这是要返回给前端的,msg的内容,是对用户十分不友好的。

2.Error

RuntimeException只是异常中的一个类,不能包含所有的异常体系,还有一大类是叫Error(系统级异常),所以需要有一个兜底的异常捕获:

/**
    * @Author:  liup
    * @date:  2021/6/18 15:01
      方法实现说明: 捕获系统级异常
    */
    @ExceptionHandler(value = Throwable.class)
    public R  throwableHandle(Throwable th){
        log.error("捕捉到Throwable异常",th);
        return R.failed("系统异常");
    }

和上面那个运行时异常同时存在 。

3.业务类异常

【自己定义的异常】

首先创建业务异常类

/**
 * @创建人: liup
 * @创建时间: 2021/6/18
 * @描述  业务类异常
 */
public class BusinessException extends RuntimeException{
 
      @Getter
       private final String code;
 
      /**
      * @Author:  liup
      * @date:  2021/6/18 15:10
        方法实现说明:  根据消息码【可用枚举类】 构造业务类异常
      */
    public BusinessException(String code) {
        this.code = code;
    }
 
    /**
    * @Author:  liup
    * @date:  2021/6/18 15:08
      方法实现说明:  自定义消息体构造业务类异常
    */
    public BusinessException(String code,String message) {
        super(message);
        this.code = code;
    }
 
    /**
    * @Author:  liup
    * @date:  2021/6/18 15:09
      方法实现说明:  根据异常 构造业务类异常
    */
    public BusinessException(String code,Throwable cause) {
        super(cause);
        this.code = code;
    }
 
}

三种异常拦截同时存在;

/**
 * @创建人: liup
 * @创建时间: 2021/6/18
 * @描述   全局异常捕获处理类
 */
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
 
 
    /**
    * @Author:  liup
    * @date:  2021/6/18 15:14
      方法实现说明:  拦截业务类异常
    */
    @ExceptionHandler(value = BusinessException.class)
    public R businessExceptionHandle(BusinessException e){
 
        log.error("捕获业务类异常:",e);
        return R.failed("业务类异常:"+e.getMessage());
    }
 
 
    /**
    * @Author:  liup
    * @date:  2021/6/18 14:34
      方法实现说明:  拦截运行时异常
//    */
    @ExceptionHandler(value = RuntimeException.class)
    public R runtimeExceptionHandle(RuntimeException e){
        log.error("捕捉到运行时异常",e);
        return R.failed("未知错误:");
    }
 
    /**
    * @Author:  liup
    * @date:  2021/6/18 15:01
      方法实现说明: 捕获系统级异常
    */
    @ExceptionHandler(value = Throwable.class)
    public R  throwableHandle(Throwable th){
        log.error("捕捉到Throwable异常",th);
        return R.failed("系统异常");
    }
}

4.对服务器友好:

以上是对前端友好,但是在服务器上,不是容易定位错误,

但是若是在参数上添加上HttpServletRequest req, HandlerMethod method,就很容易定位到错误

 private static int GENERIC_SERVER_ERROR_CODE = 2000;
    private static String GENERIC_SERVER_ERROR_MESSAGE = "服务器忙,请稍后再试";
 
    @ExceptionHandler
    public R handle(HttpServletRequest req, HandlerMethod method, Exception ex) {
        if (ex instanceof BusinessException) {
            BusinessException exception = (BusinessException) ex;
            log.warn(String.format("访问 %s -> %s 出现业务异常!", req.getRequestURI(), method.toString()), ex);
            return R.failed(GENERIC_SERVER_ERROR_MESSAGE);
        } else if (ex instanceof RuntimeException){
            log.error(String.format("访问 %s -> %s 出现运行时异常!", req.getRequestURI(), method.toString()), ex);
            return R.failed(GENERIC_SERVER_ERROR_MESSAGE);
        }
 
        else {
            log.error(String.format("访问 %s -> %s 出现系统异常!", req.getRequestURI(), method.toString()), ex);
            return R.failed(GENERIC_SERVER_ERROR_MESSAGE);
        }
    }

到此这篇关于java实现统一异常处理的文章就介绍到这了,更多相关java异常处理内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java concurrency之公平锁(二)_动力节点Java学院整理

    Java concurrency之公平锁(二)_动力节点Java学院整理

    这篇文章主要为大家详细介绍了Java concurrency之公平锁的第二篇内容,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-06-06
  • 一篇文章带你入门Java接口

    一篇文章带你入门Java接口

    这篇文章主要介绍了JAVA中接口的定义和接口的实现,文中讲解非常细致,配合代码更好的帮大家学习参考,感兴趣的朋友可以了解下
    2021-08-08
  • springboot RESTful以及参数注解的使用方式

    springboot RESTful以及参数注解的使用方式

    这篇文章主要介绍了springboot RESTful以及参数注解的使用方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-10-10
  • SpringBoot+Ant Design Vue实现数据导出功能方式

    SpringBoot+Ant Design Vue实现数据导出功能方式

    这篇文章主要介绍了SpringBoot+Ant Design Vue实现数据导出功能方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-01-01
  • 通过Java修改游戏存档的实现思路

    通过Java修改游戏存档的实现思路

    这篇文章主要介绍了通过Java修改游戏存档的实现思路,实现方法也很简单,因为植物大战僵尸游戏的数据文件存储在本地的存储位置是已知的,因此我们可以将实现过程拆分为三个步骤,需要的朋友可以参考下
    2021-10-10
  • JDK15正式发布(新增功能预览)

    JDK15正式发布(新增功能预览)

    这篇文章主要介绍了JDK15正式发布,新增功能预览,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2020-09-09
  • 浅谈Mybatis #和$区别以及原理

    浅谈Mybatis #和$区别以及原理

    这篇文章主要介绍了浅谈Mybatis #和$区别以及原理,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-07-07
  • struts2中simple主题下<s:fieldError>标签默认样式的移除方法

    struts2中simple主题下<s:fieldError>标签默认样式的移除方法

    这篇文章主要给大家介绍了关于struts2中simple主题下<s:fieldError>标签默认样式的移除方法,文中通过示例代码介绍的非常详细,需要的朋友可以参考借鉴,下面随着小编来一起学习学习吧
    2018-10-10
  • Java实现经典游戏超级玛丽的示例代码

    Java实现经典游戏超级玛丽的示例代码

    在你的童年记忆里,是否有一个蹦跳、顶蘑菇的小人?本文将用java语言实现经典游戏《超级玛丽》,文中采用了swing技术进行了界面化处理,需要的可以参考一下
    2022-02-02
  • 浅析java class 文件

    浅析java class 文件

    以下是对java中的class文件进行了详细的介绍,需要的朋友可以过来参考下
    2013-08-08

最新评论