SpringBoot自定义全局异常处理器

文章目录

  • 一、介绍
  • 二、实现
      • 1. 定义全局异常处理器
      • 2. 自定义异常类
  • 三、使用
  • 四、疑问

一、介绍

Springboot框架提供两个注解帮助我们十分方便实现全局异常处理器以及自定义异常

  • @ControllerAdvice@RestControllerAdvice(推荐)
  • @ExceptionHandler

二、实现

1. 定义全局异常处理器

定义GlobalExceptionHandler类,拦截所有异常。
@RestControllerAdvice注解使得你可以在GlobalExceptionHandler 中处理异常,@ExceptionHandle注解用于将指定异常绑定到处理的函数上。如下使用@ExceptionHandler(Exception.class)即对所有异常进行捕获处理。

@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public RestErrorResponse exception(Exception e){
        //record log
        log.error("系统异常{}", e.getMessage(),e);
        //decode errorException
        String errMessage = "系统异常";
        return new RestErrorResponse(errMessage);
    }
}
@Data
@AllArgsConstructor
public class RestErrorResponse implements Serializable {
    private String errMessage;
}

事实上,写到这里已经可以用了,RestErrorResponse 用来承载错误信息到前端,因为@RestControllerAdvice已经包含了@ResponseBody

2. 自定义异常类

继承RuntimeException 异常类写一个自定义的异常类。这么做主要是能够使用自定义的枚举类来更优雅的抛出错误。

@Data
public class XueChengPlusException extends RuntimeException {

    private String errMessage;

    public XueChengPlusException() {
        super();
    }

    public XueChengPlusException(String errMessage) {
        super(errMessage);
        this.errMessage = errMessage;
    }

    public static void cast(CommonError commonError){
        throw new XueChengPlusException(commonError.getErrMessage());
    }
    public static void cast(String errMessage){
        throw new XueChengPlusException(errMessage);
    }

}
@Getter
public enum CommonError {
    UNKOWN_ERROR("执行过程异常,请重试。"),
    PARAMS_ERROR("非法参数"),
    OBJECT_NULL("对象为空"),
    QUERY_NULL("查询结果为空"),
    REQUEST_NULL("请求参数为空");

    private String errMessage;

    private CommonError( String errMessage) {
        this.errMessage = errMessage;
    }
}

同时,对于GlobalExceptionHandler 也要做一些修改,一方面处理自定义异常,另一方处理其余异常。

@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

    @ExceptionHandler(XueChengPlusException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public RestErrorResponse customException(XueChengPlusException e){
        //record log
        log.error("系统异常{}", e.getErrMessage(),e);
        //decode errorException
        String errMessage = e.getErrMessage();
        return new RestErrorResponse(errMessage);
    }

    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public RestErrorResponse exception(Exception e){
        //record log
        log.error("系统异常{}", e.getMessage(),e);
        //decode errorException
        String errMessage = CommonError.UNKOWN_ERROR.getErrMessage();
        return new RestErrorResponse(errMessage);
    }
}

三、使用

在程序中任意地方抛出异常,controllerservicedao层都可以,比如

throw new RuntimeException("价格不能为空且必须大于0");

这时走的就是

	@ExceptionHandler(Exception.class)
    public RestErrorResponse exception(Exception e)

除此之外,可以这样抛出自定义异常,比如

XueChengPlusException.cast(CommonError.PARAMS_ERROR);
XueChengPlusException.cast("其他的消息");
throw new XueChengPlusException(CommonError.OBJECT_NULL.getErrMessage());
throw new XueChengPlusException("其他的消息");

这时走的就是

	@ExceptionHandler(XueChengPlusException.class)
    public RestErrorResponse customException(XueChengPlusException e)

四、疑问

Q:疑问,XueChengPlusException异常类继承自RuntimeException ,而RuntimeException 继承自Exception,为什么触发customException而不是exception?

在这个全局异常处理器中,当抛出一个XueChengPlusException异常时,它会被customException(XueChengPlusException e)方法处理,而不是exception(Exception e)方法。

这是因为Spring框架的异常处理机制会优先匹配最具体的异常类型。在您的代码中,XueChengPlusExceptionRuntimeException(以及Exception)的子类,因此它更具体。所以,当抛出一个XueChengPlusException异常时,Spring会优先调用处理XueChengPlusException的方法,而不是处理Exception的方法。

这种行为确实表明全局异常处理器有一定的优先级和覆盖逻辑。具体来说,处理器会优先处理更具体的异常类型,如果没有找到匹配的处理器,那么它会寻找处理更一般异常类型的处理器。
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/351631.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

学习gin框架知识的注意点

这几天重新学习了一遍gin框架:收获颇多 Gin框架的初始化 有些项目中 初始化gin框架写的是: r : gin.New() r.Use(logger.GinLogger(), logger.GinRecovery(true)) 而不是r : gin.Default() 为什么呢? 点击进入Default源码发现其实他也是…

如何在有或没有备份的 iPhone 上检索已删除的短信

iPhone 清理垃圾短信时不小心删除了一些重要短信?想知道如何找回 iPhone 上已删除的短信吗?如果您已将设备备份到 iCloud 或 iTunes,则可以从备份恢复 iPhone 上的短信。如果没有备份,您可以尝试第三方iPhone短信恢复程序来恢复它…

记一个信息泄露到RCE

打点 开局一个登录框 信息收集 发现了一处接口泄露了部分信息 不过只有支付宝密钥的信息无法扩大危害,此时尝试寻找了一下其他同类型系统同样的接口,查看一下是否泄露的信息相同 因为如果相同就说明是静态的,没有价值横向收集 此时访问其他…

RabbitMQ概念

一 、RabbitMQ概念 1 架构图 2 相关概念 Publisher - ⽣产者:发布消息到RabbitMQ中的Exchange Consumer - 消费者:监听RabbitMQ中的Queue中的消息 Broker:接收和分发消息的应用,RabbitMQ Server就是 Message Broker&#xf…

力扣日记1.27-【回溯算法篇】131. 分割回文串

力扣日记:【回溯算法篇】131. 分割回文串 日期:2023.1.27 参考:代码随想录、力扣 131. 分割回文串 题目描述 难度:中等 给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是 回文串 。返回 s 所有可…

Android App开发-简单控件(2)——视图基础

2.2 视图基础 本节介绍视图的几种基本概念及其用法,包括如何设置视图的宽度和高度,如何设置视图的外部间距和内部间距,如何设置视图的外部对齐方式和内部对齐方式等等。 2.2.1 设置视图的宽高 手机屏幕是块长方形区域,较短的那…

Unknown encoder ‘libmp3lame

环境: macos m1 , python3.10.x 背景 做视频切片, 使用moviepy 中VideoFileClip进行截取视频。 报错: Unknown encoder libmp3lameThe audio export failed because FFMPEG didnt find the specified codec for audio encoding …

ppt背景图片怎么设置?让你的演示更加出彩!

PowerPoint是一款广泛应用于演示文稿制作的软件,而背景图片是演示文稿中不可或缺的一部分。一个好的背景图片能够提升演示文稿的整体效果,使观众更加关注你的演示内容。可是ppt背景图片怎么设置呢?本文将介绍ppt背景图片设置的三个方法&#…

浪花 - 添加队伍业务开发

一、接口设计 1. 请求参数:封装添加队伍参数 TeamAddRequest package com.example.usercenter.model.request;import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.ann…

STM32 freertos 使用软件模拟串口uart

如题,为什么要这样做? 最近做的一个项目上使用了74HC595作为指示灯板使用; 这个灯板与驱动板是通过排线连接,排线约25cm长; 在实验室测试一切正常,发到客户手上使用就出现了某个LED跳动情况;…

Spring Boot 中 Service 层依赖注入问题

目录 问题描述 产生错误 问题原因 解决方法 手动注入方法 1、使用工具集 hutool,引入 Maven 依赖 2、编写 SpringUtil 工具类 问题描述 Controller 层方法为 static 静态,引入 Service 层时使用 Autowired 注解自动装配,Controller层方…

2017年认证杯SPSSPRO杯数学建模D题(第二阶段)教室的合理设计全过程文档及程序

2017年认证杯SPSSPRO杯数学建模 D题 教室的合理设计 原题再现: 某培训机构租用了一块如图(见附件)所示的场地,由于该机构开设了多种门类的课程,所以需要将这块场地通过加入一些隔墙来分割为多个独立的教室和活动区。…

手把手教学:AD09制作BOM及小技巧

BOM(Bill of Material)物料清单,是以数据格式来描述产品结构的文件,即生产一件产品所需的子零件及其产品中零件数量的完全组合。这里生成BOM表用作对你制作的pcb板进行成本预估和制作生产资料文件。同时也是样品制作时&#xff0c…

pytest参数化

一、pytest.mark.parametrize介绍 pytest.mark.parametrize(argnames, argvalues, indirectFalse, idsNone)参数说明: argnames: 一个或多个参数名,用逗号分隔的字符串,如"arg1,arg2,arg3",参数名与用例入参数一致。 a…

TensorFlow2实战-系列教程2:神经网络分类任务

🧡💛💚TensorFlow2实战-系列教程 总目录 有任何问题欢迎在下面留言 本篇文章的代码运行界面均在Jupyter Notebook中进行 本篇文章配套的代码资源已经上传 1、Mnist数据集 下载mnist数据集: %matplotlib inline from pathlib imp…

shell常用命令,参数传递,函数,挂载磁盘

1、ls 功能:显示文件和目录的信息ls 以默认方式显示当前目录文件列表 ls -a 显示所有文件包括隐藏文件 ls -l 显示文件属性,包括大小,日期,符号连接,是否可读写及是否可执行 ls -lh 显示文件的大小,以…

BOSS 直聘:日增10亿数据的历史库,如何通过OceanBase节省70%存储成本?

BOSS 直聘是在全球范围内首创互联网“直聘”模式的在线招聘产品,目前已经成为了中国最大的招聘平台。本文谈到的 BOSS 直聘的业务场景主要是通过数据库对招聘过程中的聊天记录信息进行存储,数据量极大,且每天都有 5 亿到 10 亿的增量数据。和…

Linux入门攻坚——14、实战软件安装-搭建Python3.8环境-2

上一篇解决了openssl和pip问题,这一篇来解决sqlite问题 创建app时出现错误,模块_sqlite3找不到,查询sqlite相关的包: 在python2.6的lib-dynload路径下,有_sqlite3.so,这个应该就是Python需要的sqlite模块&a…

Redis 实际项目中的整合,记录各种用法

Redis缓存餐厅数据 我们来看主要的流程 很简单,就是在数据库和接口之间加了一层缓冲,在redis之前其实还可以加其他的缓存 例如 nginx的缓存 接下来,就是结合我的业务,来做缓存 我这里的业务逻辑是,按了分类的按钮,分别以不同的 分类为一组缓存数据 所以,这里的缓存粒度是分类…

一个人永远无法赚到认知以外的钱

做交付、做产品,从来都不是一件容易的事情。在营销和服务的过程中,我充分见证了人生百态。 前一段时间,小灰创建了一个自媒体陪伴群,群里邀请了各个领域的自媒体大佬,每周都会在群里进行分享,大家的学习气氛…