springboot整合之统一异常处理

news2025/1/15 13:53:40

特别说明:本次项目整合基于idea进行的,如果使用Eclipse可能操作会略有不同,不过总的来说不影响。

springboot整合之如何选择版本及项目搭建

springboot整合之版本号统一管理 

springboot整合mybatis-plus+durid数据库连接池

springboot整合swagger

springboot整合mybatis代码快速生成

springboot整合之统一结果返回

springboot整合之统一异常处理

springboot整合之logback日志配置

springboot整合pagehelper分页

springboot整合本地缓存

springboot整合redis + redisson

springboot整合elasticsearch

springboot整合rabbitMq

springboot整合canal实现缓存一致性

springboot整合springSecurity(前后端不分离版本)

一、为什么要进行统一异常处理

首先我们来看一下,如果不对异常进行处理会发生什么问题,我们来修改一下测试接口。我们假设运行过程中接口发生了异常,来看一下接口调用会发生什么问题。

 启动后测试返回结果如下:???这是啥?我们的统一结果返回呢?

 所以这就是为什么我们要对异常进行统一处理的原因了。如果发生了异常我们应该让接口也返回统一的结果。有好的展示给接口调用方。

除了上面的接口统一返回其实异常的拦截也方便我们对异常进行记录,和错误排查。

还有就是有时候我们可能对某些异常比较关注,比如说我们监控某个IP或者用户一天发送短信的数量,当超出一定数量后我们就不再发送然后抛出异常。这个时候我们通过统一异常处理进行全局拦截,然后记录日志甚至是数据库,并且发送短信通知相关负责人。

二、springboot如何处理异常

通过第一步我们可以看出来,我们需要对系统中一些未知的异常进行处理。达到给接口调用方展示有好返回结果的目的,也就是按照我们定义好的返回结果统一的返回。那么在springboot中是如何对异常进行处理的呢?

在springboot中处理异常可以有多种方式,我们这里选择使用相对比较优雅切简单的一种来实现。那就是使用@ControllerAdvice + @ExceptionHandler来进行异常处理。我们先看一下怎么实现以及实现的效果,最后再来说它实现的原理。

首先定义一个全局异常处理类,在类上加上@ControllerAdvice,然后在类里面通过@ExceptionHandler来对异常进行处理。

package com.example.springbootdemo.common.advice;


import com.example.springbootdemo.common.response.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;


/**
 * description: BasicExceptionHandler 对系统报错进行统一处理。<br>
 * @date: 2022/12/27 0027 下午 3:27 <br>
 * @author: William <br>
 * @version: 1.0 <br>
 */
@Slf4j
@ControllerAdvice
public class BasicExceptionHandler {


    /**
     * description: errorHandler 处理全局异常<br>
     * @version: 1.0
     * @date: 2022/12/27 0027 下午 3:37
     * @author: William
     * @param exception   异常
     * @return java.util.Map<java.lang.String,java.lang.Object>
     */
    @ResponseBody
    @ExceptionHandler(value = Exception.class)
    public Result errorHandler(Exception exception) {
        return Result.build(500, exception.getMessage());
    }

}

当前代码拦截了所有的异常,然后定义了异常状态为500,返回的消息是异常提示。我们先来看一下效果。

 可以看到已经按照我们统一返回结果的样式进行返回了。但是这样处理异常,范围有点太大了。如果我们想某种异常进行单独的处理我们可以再添加这种异常处理的方法就好了,也很简单,我们来举个例子说明一下。就拿当前的0不能做除数这种异常来举例。

package com.example.springbootdemo.common.advice;

import com.example.springbootdemo.common.exception.MyException;
import com.example.springbootdemo.common.response.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;


/**
 * description: BasicExceptionHandler 对系统报错进行统一处理。<br>
 * @date: 2022/12/27 0027 下午 3:27 <br>
 * @author: William <br>
 * @version: 1.0 <br>
 */
@Slf4j
@ControllerAdvice
public class BasicExceptionHandler {


    /**
     * description: errorHandler <br>
     * @version: 1.0
     * @date: 2022/12/27 0027 下午 4:44
     * @author: William
     * @param exception 异常
     * @return com.example.springbootdemo.common.response.Result
     */
    @ResponseBody
    @ExceptionHandler(value = ArithmeticException.class)
    public Result errorHandler(ArithmeticException exception) {
        return Result.build(500, "算数运算异常");
    }

    

    /**
     * description: errorHandler 处理全局异常<br>
     * @version: 1.0
     * @date: 2022/12/27 0027 下午 3:37
     * @author: William
     * @param exception   异常
     * @return java.util.Map<java.lang.String,java.lang.Object>
     */
    @ResponseBody
    @ExceptionHandler(value = Exception.class)
    public Result errorHandler(Exception exception) {
        return Result.build(500, exception.getMessage());
    }

}

 按照我们上面的处理结果,如果说发生了0是除数的异常,提示消息应该是:“算数运算异常”。那我们重新启动在来运行一次,看一下效果。

 可以看到,已经变成了我们预期的样子。说明我们的处理生效了。

那么这究竟是怎么实现的呢?其实也非常简单,我们来看一下@ControllerAdvice的注释文档,这里面已经说的非常清楚了。

Specialization of @Component for classes that declare @ExceptionHandler, @InitBinder, or @ModelAttribute methods to be shared across multiple @Controller classes.

这个类是为那些声明了(@ExceptionHandler、@InitBinder 或 @ModelAttribute注解修饰的)方法的类而提供的专业化的@Component , 以供多个 Controller类所共享。

其实说白了,就是aop思想的一种实现,你告诉我需要拦截规则,我帮你把他们拦下来,具体你想做更细致的拦截筛选和拦截之后的处理,你自己通过@ExceptionHandler、@InitBinder 或 @ModelAttribute这三个注解以及被其注解的方法来自定义。还有一点需要说明一下,就是@ControllerAdvice可以通过 @Order / @Priority 来设置优先级。

三、自定义异常

那么我们该如何定义一个自己的异常类呢?其实非常简单,我们只要使用继承就好了。

package com.example.springbootdemo.common.exception;


import com.example.springbootdemo.common.enums.ErrorCodeEnum;
import lombok.Getter;

/**
 *@ClassName MyException
 *@Description 异常处理类,将运行异常交给MyException,将异常信息统一返回
 *@Author William
 *@date: 2022/12/27 0027 下午 3:26
 *@Version 1.0
 */
@Getter
public class MyException extends RuntimeException{

    private ErrorCodeEnum errorCodeEnum;

    public MyException(ErrorCodeEnum errorCodeEnum) {
        this.errorCodeEnum = errorCodeEnum;
    }
}

这样我们就通过继承RuntimeException实现了自己的自定义异常了。通过继承RuntimeException,那么它也就是异常的一种了,我们就能够在抛出异常时使用自己定义的异常了。使用方法如下:在参数校验时,如果发生了参数非法,那我们就抛出参数非法的异常。使用非常的简单。

四、自定义异常处理

对于自定义异常的处理也非常简单,跟我们上面处理算数运算异常时是一样的,我们只要把异常类型换成我们自己定义的异常类型就好了。具体代码如下:

package com.example.springbootdemo.common.advice;

import com.example.springbootdemo.common.exception.MyException;
import com.example.springbootdemo.common.response.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;


/**
 * description: BasicExceptionHandler 对系统报错进行统一处理。<br>
 * @date: 2022/12/27 0027 下午 3:27 <br>
 * @author: William <br>
 * @version: 1.0 <br>
 */
@Slf4j
@ControllerAdvice
public class BasicExceptionHandler {



    /**
     * description: errorHandler 处理算数运算异常<br>
     * @version: 1.0
     * @date: 2022/12/27 0027 下午 4:44
     * @author: William
     * @param exception 异常
     * @return com.example.springbootdemo.common.response.Result
     */
    @ResponseBody
    @ExceptionHandler(value = ArithmeticException.class)
    public Result errorHandler(ArithmeticException exception) {
        return Result.build(500, "算数运算异常");
    }

    /**
     * description: errorHandler 处理自定义异常<br>
     * @version: 1.0
     * @date: 2022/12/27 0027 下午 3:32
     * @author: William
     * @param exception  自定义异常
     * @return java.util.Map<java.lang.String,java.lang.Object>
     */
    @ResponseBody
    @ExceptionHandler(value = MyException.class)
    public Result errorHandler(MyException exception) {
        return Result.error(exception.getErrorCodeEnum());
    }


    /**
     * description: errorHandler 处理全局异常<br>
     * @version: 1.0
     * @date: 2022/12/27 0027 下午 3:37
     * @author: William
     * @param exception   异常
     * @return java.util.Map<java.lang.String,java.lang.Object>
     */
    @ResponseBody
    @ExceptionHandler(value = Exception.class)
    public Result errorHandler(Exception exception) {
        return Result.build(500, exception.getMessage());
    }



}

五、测试统一异常处理

到了这里我们就能够启动项目来测试一下我们的统一异常处理了。

 启动成功,我们访问swagger接口来测试一下:

 可以看到我们抛出的异常也被统一处理了。好了,到这里我们的统一异常处理就完成了。如果文章对你有所帮助的话,烦请点赞关注一下~多谢啦!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

FFmpeg简单使用:过滤器 ---- h264_mp4toannexb

H264有两种封装方式&#xff1a;字节流AnnexB格式 AVCC格式。 1. AnnexB格式 ---- 用于实时播放 开始前缀&#xff08;00000001或000001&#xff09;&#xff0b;NALU数据  绝大部分编码器的默认输出格式   一共有两种起始码start_code    ①3字节0x000001  单帧多s…

C++面向对象特性——多态

C面向对象之多态什么是多态&#xff1f;为什么使用多态&#xff1f;虚函数的定义虚函数的实现机制哪些函数不能被设置为虚函数&#xff1f;虚函数的访问指针访问引用访问对象访问成员函数中的访问构造函数和析构函数中访问纯虚函数抽象类虚析构函数重载、隐藏、覆盖菱形继承虚拟…

spring boot文档阅读笔记——01

目录标题一、文档地址二、第一个spring boot例子三、 Starters&#xff08;spring boot 官方提供的启动器&#xff09;四、SpringBootApplication注释&#xff08;一&#xff09;EnableAutoConfiguration&#xff08;二&#xff09;ComponentScan五、devtools&#xff08;热插拔…

当项目经理看世界杯决赛时…

12月18日&#xff0c;2022卡塔尔世界杯决赛&#xff0c;阿根廷在点球大战中击败卫冕冠军的法国队&#xff0c;捧走大力神杯。这场跌宕起伏的“巅峰对决”&#xff0c;给大家呈现了一场精彩绝伦的比赛。 当阿根廷2-0领先七十多分钟的时候&#xff0c;都以为这局稳了&#xff0c…

跨平台应用开发进阶(五十一):HTML5(富文本内容)连续数字、字母不自动换行问题分析及解决

文章目录一、前言二、问题分析三、解决方法3.1 对 input 标签设置3.2 对 input 标签内的 p 标签设置四、延伸阅读 顶部状态栏穿透问题五、拓展阅读一、前言 项目开发过程中&#xff0c;涉及在Web端维护富文本内容&#xff0c;通过APP端查看的相关的功能&#xff0c;功能描述大…

repo init详解

首先选择manifest源&#xff0c;一般直接使用清华或中科大的镜像源 repo init -u https://aosp.tuna.tsinghua.edu.cn/platform/manifest是清华提供的镜像源 repo init -u git://mirrors.ustc.edu.cn/aosp/platform/manifest是中国科学技术大学的镜像源 repo init推荐使用-b 分…

未来汽车产业新生态高峰论坛在深圳举行

【2022年12月22日发自深圳】汽车产业正面临百年未有之大变局&#xff0c;以数字化技术为特征的智能网联汽车已经成为全球汽车产业转型升级的战略方向。汽车的属性也从一个机械化的交通工具转变成与各个生态相互连通的移动终端和数字空间。12月21日&#xff0c;由工业和信息化部…

【C++初阶】模板进阶

文章目录非类型模板参数模板特化函数模板特化类模板特化全特化偏特化模板的分离编译模板总结所有测试的代码非类型模板参数 模板参数分类类型形参与非类型形参 1.类型形参即&#xff1a;出现在模板参数列表中&#xff0c;跟在class或者typename之类的参数类型名称。 2.非类型形…

创建城市人口总量趋势图

创建城市人口总量趋势图学习目标使用数据人口总量趋势方程数据导入对数据进行处理fct_reorder2的应用对数据进行整理对图像进行可视化操作使用fct_reorder2去掉趋势点内容小结学习目标 我们所采用的学习内容来自B站的Lizongzhang老师的R语言的学习分享 今天学习的主要内容是关…

数据集说明:COCO的两个数据集COCO-stuff和COCO-Caption

数据集图片数量比较 COCO-Caption有33万张图、50万个caption COCO-Stuff有16.4万张图 172个类别(80thing、91stuff、1个未标注类) COCO-stuff的具体类别说明 COCO-Stuff contains 172 classes:80 thing, 91 stuff, and 1 class unlabeled. The 80 thing classes are the same …

群晖nas部署python项目

事件起因是因为想再硬盘里下载小姐姐&#xff0c;在线播放会卡顿很不爽&#xff0c; 开始用一些在线爬的网站&#xff0c;网速非常慢&#xff0c;我发现自己有nas 如果把项目部署再nas上 通过命令行下载就好了 我就开始检索资料&#xff0c;发现网上的都是一些过时的文章&#…

分布式系统关键路径延迟分析实践

作者 | 月色如海 导读 随着对用户体验的不断追求&#xff0c;延迟分析成为大型分布式系统中不可或缺的一环。本文介绍了目前在线服务中常用的延迟分析方法&#xff0c;重点讲解了关键路径分析的原理和技术实现方案&#xff0c;实践表明此方案效果显著&#xff0c;在耗时优化方面…

图解深度学习-提高泛化能力的方法

数据集 在深度学习的训练过程中&#xff0c;神经网络的类型和结构固然重要&#xff0c;但训练样本才是重中之重。 数据增强 当训练样本数量较少时&#xff0c;可以通过数据增强来增加样本的多样性。 数据增强就是通过对样本图像进行平移、旋转、镜像翻转等方式进行变换。除…

【Java】Log4j日志

目录 1.日志概述 日志是什么 为什么会有日志 2.log4j概述 什么是log4j 版本 3.log4j入门案例 步骤 实现 总结 4.log4j1详情&#xff1a;记录器rootLogger 5.log4j1详情&#xff1a;日志级别 6.log4j1详情&#xff1a;输出源appender ConsoleAppender FileAppend…

第二十八章 数论——扩展欧几里德算法与线性同余方程

第二十八章 扩展欧几里德算法一、裴蜀定理1、定理内容2、定理证明二、扩展欧几里德定理1、作用2、思路3、代码三、线性同余方程1、问题2、思路3、代码一、裴蜀定理 1、定理内容 对于任意整数aaa和bbb&#xff0c;一定存在整数xxx&#xff0c;yyy使得axbyaxbyaxby是gcd(a,b)gc…

Linux的基本指令

前言 相对于linux操作系统,其实window也是操作系统&#xff0c;我们这节课说的是Linux的基本指令 那么在window上有没有基本指令呢&#xff0c;答案是有的&#xff0c;我们可以使用windowsr进入cmd就可以用我们的基本指令 基本指令 在本文中&#xff0c;我们基本上都使用类比的…

基于threeJS实现圣诞节孔明灯效果

1.效果图 2.实现思路 使用three.js的套路几乎是固定的&#xff1a; 1 初始化场景&#xff08;scene&#xff09; 2.创建透视相机&#xff08;camera&#xff09; 3.设置相机位置&#xff08;position&#xff09; 4.创建纹理加载器对象&#xff08;texture&#xff09; 5.创建…

【SegNeXt】语义分割中对卷积注意力设计的反思

目录 1.摘要 2.相关工作 2.1语义分割 2.2多尺度网络 2.3注意力机制 3.网络结构 3.1卷积编码器 3.2解码器 4.实验 个人总结&#xff1a; 论文链接&#xff1a;论文 代码链接&#xff1a;代码 论文发表于NeurIPS 2022&#xff0c;值得注意的是&#xff0c;在Transforme…

UVM入门和进阶实验0

一. 概述 UVM学习流程仍然按照SV时候的核心流程&#xff0c;即&#xff1a; 如何搭建验证框架验证组件之间的连接和通信如何编写测试用例&#xff0c;继而完成复用和覆盖率的收敛 我们UVM入门和进阶实验0还是同之前SV验证实验0思想一样&#xff0c;让大家通过简单的实验要求…

学习HTTP协议,这一篇就够啦 ~~

HTTP协议一、什么是HTTP1.1 应用层协议1.2 HTTP1.3 HTTP协议的工作过程二、HTTP协议格式2.1 Fiddler抓包工具2.2 协议格式三、HTTP请求 (Request)3.1 认识 "方法" (method)3.1.1 GET 方法3.1.2 POST 方法3.1.3 GET和POST比较3.1.4 其他方法3.2 认识URL3.2.1 URL基本格…