Spring Boot 使用断言抛出自定义异常,优化异常处理机制
文章目录
- 什么是断言?
- 什么是异常?
- 基于断言实现的异常处理机制
- 创建自定义异常类
- 创建全局异常处理器
- 创建自定义断言类
- 创建响应码类
- 创建工具类
- 测试效果
什么是断言?
实际上,断言(Assertion)是在Java 1.4 版本引入的特性,它为开发人员提供了一种简单的机制来进行代码预期条件的验证和调试。
Java 1.4 版本于2002年发布,它引入了许多新功能和改进,其中之一就是断言。断言的目的是在程序中进行可验证的内部检查,以确保代码的正确性和可靠性。
断言最早是在1989年由美国计算机科学家C.A.R. Hoare提出的概念,称为"断言语句"。然后,在Java 1.4版本中,Sun Microsystems将其引入到Java编程语言中,并添加了关键字assert
用于表示断言。
使用assert
关键字,开发人员可以在代码中编写断言语句,以检查程序的状态或条件是否满足预期。如果断言失败,会抛出一个AssertionError
异常,提示开发人员该断言点存在问题。
例如org.springframework.util.Assert
是Spring Framework中的一个工具类,用于进行参数校验和断言判断。它是一个包含静态方法的最终类。
在org.springframework.util.Assert
类中,提供了一系列静态方法用于进行断言操作,例如notNull()
、isTrue()
、hasText()
等。这些方法主要用于验证方法参数或对象状态是否满足预期条件,如果不满足,则会抛出IllegalArgumentException
或IllegalStateException
等运行时异常。
常用的Assert
方法源码如下:
//判断传入的表达式是否为true,如果为false,则抛出`IllegalArgumentException`异常,并使用指定的错误信息
public static void isTrue(boolean expression, String message) {if (!expression) {throw new IllegalArgumentException(message);}
}//判断传入的对象是否为null,如果为null,则抛出`IllegalArgumentException`异常,并使用指定的错误信息
public static void isNull(@Nullable Object object, String message) {if (object != null) {throw new IllegalArgumentException(message);}
}
org.springframework.util.Assert
类中提供的方法可以帮助我们在编码过程中进行快速的参数校验,避免使用繁琐的if语句或手动抛出异常。同时,这些方法也提供了可自定义的错误信息,有助于更好地理解校验失败的原因。
什么是异常?
异常(Exception)是程序运行时出现的错误或异常情况,它会打断程序正常的执行流程,并且可能导致程序崩溃或产生不可预期的结果。在Java中,异常通常被表示为一个继承自Throwable类的对象,例如RuntimeException、IllegalArgumentException等。
而自定义异常是指开发人员基于Java中的Exception或其子类,定义自己的异常类。通常情况下,自定义异常类用于表示特定的异常情况,以便更好地对程序的异常情况进行分类处理和管理。自定义异常类可以包含自己的属性和方法,以提供更详细的异常信息和处理方式。
需要自定义异常的原因有以下几点:
-
更细粒度的异常控制:Java标准库中的异常类型比较全面,但是在实际应用中,我们可能需要更具体的异常类型来描述某种特定场景下的异常情况。例如,我们可以自定义一个PayErrorException来表示支付异常,这样可以更好地区分不同类型的异常情况,并进行不同的处理。
-
信息更丰富:Java标准库中的异常类型通常只包含错误信息,如果需要传递更多的相关信息,就需要自定义异常类。例如,我们可以在自定义异常类中添加一些额外的属性,如异常码、请求参数等,以便更好地记录和跟踪异常信息。
-
更友好的异常提示:Java标准库中的异常信息通常比较晦涩难懂,如果需要更加友好和易于理解的提示信息,就需要自定义异常类。通过自定义异常类,开发人员可以提供更加直观和易懂的异常提示信息,以便用户或其他开发人员更好地理解异常情况。
在实际业务中,我们往往需要设置一个全局的异常处理器对异常进行统一的处理和管理,并返回相应的错误信息,确保应用程序的稳定性和可靠性。
基于断言实现的异常处理机制
创建自定义异常类
首先,需要创建一个自定义的异常类,继承自RuntimeException
或其子类:
/*** 自定义通用异常类*/
public class CommonException extends RuntimeException {/*** 无参构造方法*/public CommonException() {}/*** 构造方法,传入异常信息* @param message 异常信息*/public CommonException(String message) {super(message);}/*** 构造方法,传入异常信息和原始异常对象* @param message 异常信息* @param cause 原始异常对象*/public CommonException(String message, Throwable cause) {super(message, cause);}/*** 构造方法,传入原始异常对象* @param cause 原始异常对象*/public CommonException(Throwable cause) {super(cause);}
}
在自定义异常类CommonException
中我们提供了几个不同的构造方法,方便在不同场景下创建异常对象。每个构造方法都调用了父类的构造方法super
,以便初始化异常对象。
创建全局异常处理器
我们还需要创建一个全局异常处理器GlobalExceptionHandler
,用于统一处理我们抛出的自定义异常类:
/*** 全局异常处理器*/
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {/*** 处理CommonException异常* @param e 异常对象* @return 异常信息*/@ExceptionHandler(CommonException.class)public String handleCommonException(CommonException e) {log.error("错误信息:{}", e.getMessage());return e.getMessage();}
}
在全局异常处理器GlobalExceptionHandler
类上我们使用了@RestControllerAdvice
注解标识该类为全局异常处理器。在该类中,定义了一个方法handleCommonException
,用于处理异常捕获后的逻辑,在方法上添加了@ExceptionHandler()
注解表示该方法处理指定自定义异常CommonException
。
创建自定义断言类
对于断言类,我们可以模仿org.springframework.util.Assert
类,借鉴其中的方法,自定义一个抽象类MyAssert
:
/*** 断言类*/
public abstract class MyAssert {/*** 判断对象是否为空,如果不为空则抛出CommonException异常** @param object 要进行判断的对象*/public void assertIsNull(@Nullable Object object) {// 如果对象不为空,则抛出CommonException异常,并将当前对象序列化为JSON字符串作为异常信息if (object != null) {throw new CommonException(JSON.toJSONString(this));}}}
如上,我们创建了一个assertIsNull
方法,参数object
用于接收要进行判断的对象,如果object
为空,则抛出CommonException
异常,并将当前对象序列化为JSON字符串作为异常信息。
创建响应码类
创建自定义的响应码类,同时继承断言类MyAssert,这样我们可以通过响应码直接调用断言类中的方法进行判断:
/*** 响应码类,继承自断言类MyAssert*/
@Getter
@NoArgsConstructor
@AllArgsConstructor
public class ResCode extends MyAssert {/*** 响应码*/private int code;/*** 响应消息*/private String message;}
上述代码中,使用了Lombok库的注解来简化代码编写。具体注解的含义如下:
@Getter
: 自动生成属性的getter方法。@NoArgsConstructor
: 自动生成无参构造方法。@AllArgsConstructor
: 自动生成包含所有参数的构造方法。
创建工具类
ResCodeUtils
工具类用于调用响应码进行校验,抛出自定义异常并返回指定错误信息:
/*** 响应码工具类,继承自响应码类ResCode*/
public class ResCodeUtils extends ResCode {/*** 响应码naa,表示错误*/public static ResCode naa = new ResCode(300, "错误");/*** 响应码naa1,表示naa1错误*/public static ResCode naa1 = new ResCode(4044, "naa1错误");}
在ResCodeUtils
类中提供了两个静态属性naa
和naa1
,分别表示响应码为300和4044的错误类型,方便通过类名.
的方式直接调用。
测试效果
-
编写
TestController
类,添加@RestController
注解表明该类是一个控制器类,用于处理HTTP请求并返回响应:@RestController public class TestController {@RequestMapping("/send1")public String send1() {ResCodeUtils.naa.assertIsNull(null);return "success";}@RequestMapping("/send2")public String send2() {ResCodeUtils.naa1.assertIsNull(new ResCode());return "success";}}
在
TestController
类中,定义了两个请求处理方法send1()
和send2()
。这两个方法使用了@RequestMapping
注解来指定它们对应的URL路径。-
send1()
方法中调用了ResCodeUtils.naa.assertIsNull(null)
,这表示对naa
响应码进行断言,判断传入的参数是否为null。如果参数为null,断言通过,否则会抛出异常。 -
send2()
方法中调用了ResCodeUtils.naa1.assertIsNull(new ResCode())
,这表示对naa1
响应码进行断言,判断传入的参数是否为null。由于参数new ResCode()
不为null,所以这里会抛出异常。
无论是
send1()
还是send2()
方法,最终都会返回字符串"success"作为处理结果。 -
-
启动项目,使用 ApiFox 访问对应接口。
-
访问
send1()
,由于参数为null,断言通过,返回字符串"success": -
访问
send2()
,由于参数为new ResCode()
,不为null,断言未通过,抛出自定义异常之后被全局异常处理器GlobalExceptionHandler
捕获,返回对应错误信息:同时,可以在控制台看到打印的日志信息
-
本文到此结束,感谢您的阅读,希望对您有所帮助!!!
相关文章:

Spring Boot 使用断言抛出自定义异常,优化异常处理机制
文章目录 什么是断言?什么是异常?基于断言实现的异常处理机制创建自定义异常类创建全局异常处理器创建自定义断言类创建响应码类创建工具类测试效果 什么是断言? 实际上,断言(Assertion)是在Java 1.4 版本…...

vue基于ElementUI/Plus自定义的一些组件
vue3-my-ElementPlus 源码请到GitHub下载使用MyTable、MySelect、MyPagination 置顶|Top | 使用案例: 1.0 定义表格数据(测试使用) data() {return {tableData: [],value:[],valueList: [],}; },// 构造表格测试数据// 1 第一行…...

leetcode刷题日记:69.sqrt(x)
给出一个非负的整数x,返回x的平方根向下取整的结果,这个被返回的数也应该是一个非负的值。 对我们的要求是不能使用任何内置的指数函数与操作,官方还给了我们例子: 在C种不能使用pow(x, 0.5) 在python不能使用 x**0.5 既然官方已经…...

[尚硅谷React笔记]——第9章 ReactRouter6
目录: 课程说明一级路由重定向NavLink高亮useRoutes路由表嵌套路由路由的params参数路由的search参数路由的state参数编程式路由导航useRouterContextuseNavigationTypeuseOutletuseResolvedPath()总结项目地址 1.课程说明 概述 React Router以三个不同的包发布…...

强大的pdf编辑软件:Acrobat Pro DC 2023中文
Acrobat Pro DC 2023是一款强大的PDF编辑和管理软件,它提供了广泛的功能,使用户能够轻松创建、编辑、转换和共享PDF文档。通过直观的界面和先进的工具,用户可以快速进行文本编辑、图像调整、页面管理等操作,同时支持OCR技术&#…...

玩一下Spring Boot
文章目录 1 开发环境1.1 JDK1.2 IntelliJ IDEA2 Spring Boot2.1 创建项目2.2 创建模板页面2.3 创建控制器2.4 启动项目2.5 访问页面1 开发环境 1.1 JDK 安装JDK21 配置环境变量 在命令行查看JDK版本 玩一玩jshell...

一个高性能类型安全的.NET枚举实用开源库
从零构建.Net前后端分离项目 枚举应该是我们编程中,必不可少的了,今天推荐一个.NET枚举实用开源库,它提供许多方便的扩展方法,方便开发者使用开发。 01 项目简介 Enums.NET是一个.NET枚举实用程序库,专注于为枚举提…...

c#字符串格式化
字符串格式化是一种将变量的值插入到字符串中的方法。它允许我们创建动态的字符串,其中包含变量的值。 string.Format 通过在字符串中使用占位符{0},{1}等,我们可以指定要插入的变量的位置。然后,通过在string.Format方法的参数…...

AMD老电脑超频及性能提升方案及实施
收拾电子元件的时候找到了若干古董的CPU 其中有一个X3 440 是原来同学主板烧了之后给我的,我从网上配了AM2 昂达主板,然后又买了AMD兼容内存,组成了win7 64位电脑,用起来非常不错,我把硬件配置和升级过程说明下&#x…...

Github 自动化部署到GitHub Pages
1.准备工作 新建仓库 新建项目 配置 vite.config.ts base: ./,部署应用包时的基本URL,例:vue-cli 5.x 配置 publicPath 推送到远程仓库 2.配置 GitHub Token 点击 Settings -> Actions -> General 找到 Workflow permissions,选中第…...

Golang 串口通信
简介 串口通信是一种常见的硬件通信方式,用于在计算机和外部设备之间传输数据。Golang(Go语言)作为一种高效、可靠的编程语言,提供了丰富的库和工具用于串口通信。本文将介绍如何使用Golang进行串口通信,包括串口配置…...

项目管理之如何识别并应对项目风险
项目风险管理是项目管理中不可忽视的环节,如何识别并应对项目的风险对于项目的成功实施至关重要。本文将介绍风险管理的流程、风险分解结构、定性及定量风险评估方法,以及消极和积极的风险应对策略,旨在帮助读者更好地理解和应对项目风险。 …...

vue封装独立组件:实现手写签名功能
目录 第一章 效果展示 第二章 准备工作 2.1 使用的工具vue-sign 2.1.1 安装 2.1.2 了解 2.1.3 参数说明 第三章 源代码 第一章 效果展示 第二章 准备工作 2.1 使用的工具vue-esign 2.1.1 安装 npm install vue-esign --save 2.1.2 了解 兼容pc端和移动端有对应的参…...

图及谱聚类商圈聚类中的应用
背景 在O2O业务场景中,有商圈的概念,商圈是业务运营的单元,有对应的商户BD负责人以及配送运力负责任。这些商圈通常是一定地理围栏构成的区域,区域内包括商户和用户,商圈和商圈之间就通常以道路、河流等围栏进行分隔。…...

npx 和 npm 区别
文章目录 背景作用执行流程 背景 解决 npm 之前的执行包中的命令行需要先下载的问题,如果有多个不同版本的包就需要下载多次比如已经装了全局的 webpack 1.x 版本并且还要继续使用,还需要装个 webpack 4.x 使用的其相应功能,这个时候可以不装在全局&…...

HTML_案例1_注册页面
用纯html页面,不用css画一个注册页面。 最终效果如下: html页面代码如下: <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>注册页面</title> </head>…...

Adobe After Effects 2024(Ae2024)在新版本中的升级有哪些?
After Effects 2024是Adobe公司推出的一款视频处理软件,它适用于从事设计和视频特技的机构,包括电视台、动画制作公司、个人后期制作工作室以及多媒体工作室。通过After Effects,用户可以高效且精确地创建无数种引人注目的动态图形和震撼人心…...

超越 GLIP! | RegionSpot: 识别一切区域,多模态融合的开放世界物体识别新方法
本文的主题是多模态融合和图文理解,文中提出了一种名为RegionSpot的新颖区域识别架构,旨在解决计算机视觉中的一个关键问题:理解无约束图像中的各个区域或patch的语义。这在开放世界目标检测等领域是一个具有挑战性的任务。 关于这一块&…...

webgoat-(A1)injection
SQL Injection (intro) SQL 命令主要分为三类: 数据操作语言 (DML)DML 语句可用于请求记录 (SELECT)、添加记录 (INSERT)、删除记录 (DELETE) 和修改现有记录 ÿ…...

51单片机-中断
文章目录 前言 前言 #include <reg52.h> #include <intrins.h>sbit key_s2P3^0; sbit flagP3^7;void delay(unsigned int z){unsigned int x,y;for(xz;x>0;x--)for(y114;y>0;y--); }void int_init(){EA1;EX11;IT11;}void main(){int_init();while(1){if (key…...

Canvas 梦幻树生长动画
canvas可以制作出非常炫酷的动画,以下是一个梦幻树的示例。 效果图 源代码 <!DOCTYPE> <html> <head> <meta http-equiv"Content-Type" content"text/html; charsetutf-8" /> <title>梦幻数生长动画</title&…...

Unity之UI、模型跟随鼠标移动(自适应屏幕分辨率、锚点、pivot中心点)
一、效果 UI跟随鼠标移动, 动态修改屏幕分辨率、锚点、pivot等参数也不会受到影响。同时脚本中包含3d物体跟随ui位置、鼠标位置移动 二、屏幕坐标、Canvas自适应、锚点、中心点 在说原理之前我们需要先了解屏幕坐标、Canvas自适应、锚点、中心的特性和之间的关系。 1.屏幕坐标…...

竞赛 深度学习猫狗分类 - python opencv cnn
文章目录 0 前言1 课题背景2 使用CNN进行猫狗分类3 数据集处理4 神经网络的编写5 Tensorflow计算图的构建6 模型的训练和测试7 预测效果8 最后 0 前言 🔥 优质竞赛项目系列,今天要分享的是 🚩 **基于深度学习猫狗分类 ** 该项目较为新颖&a…...

S4.2.4.7 Start of Data Stream Ordered Set (SDS)
一 本章节主讲知识点 1.1 xxx 1.2 sss 1.3 ddd 二 本章节原文翻译 2.1 SDS 数据流开始有序集 SDS 代表传输的数据类型从有序集转为数据流。它会在 Configuration.Idle,Recovery.Idle 和 Tx 的 L0s.FTS 状态发送。Loopback 模式下,主机允许发送 SDS。…...

CentOS操作系统的特点
CentOS操作系统的特点如下: 免费开源:CentOS是一个免费开源的操作系统,完全免费,无需花费任何成本。 稳定性高:CentOS以其出色的稳定性和安全性而闻名。它是一个基于Red Hat Enterprise Linux(RHEL&#x…...

Go基础(待更新)
Go基础(待更新) 参考Go 语言教程 文章目录 Go基础(待更新)一、基本语法1、格式化输出2、声明并赋值1)单变量赋值2)多变量赋值 二、math工具包的使用三、函数1、参数传递1)普通传递2)…...

二、Hadoop分布式系统基础架构
1、分布式 分布式体系中,会存在众多服务器,会造成混乱等情况。那如何让众多服务器一起工作,高效且不出现问题呢? 2、调度 (1)架构 在大数据体系中,分布式的调度主要有2类架构模式:…...

数据结构(超详细讲解!!)第二十一节 特殊矩阵的压缩存储
1.压缩存储的目标 值相同的元素只存储一次 压缩掉对零元的存储,只存储非零元 特殊形状矩阵: 是指非零元(如值相同的元素)或零元素分布具有一定规律性的矩阵。 如: 对称矩阵 上三角矩阵 下三角矩阵 对角矩阵 准…...

Python最强自动化神器Playwright!再也不用为爬虫逆向担忧了!
版权说明:本文禁止抄袭、转载,侵权必究! 目录 一、简介+使用场景二、环境部署(准备)三、代码生成器(优势)四、元素定位器(核心)五、追踪查看器(辅助)六、权限控制与认证(高级)七、其他重要功能(进阶)八、作者Info一、简介+使用场景 Playwright是什么?来自Chat…...

为什么 conda 不能升级 python 到 3.12
为什么 conda 不能升级 python 到 3.12 2023-11-05 23:33:29 ChrisZZ 1. 目的 弄清楚为什么执行了如下升级命令后, python 版本还是 3.11? conda update conda conda update python2. 原因 因为 conda forge 没有完成 migration Migration is the …...