当前位置: 首页 > news >正文

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()等。这些方法主要用于验证方法参数或对象状态是否满足预期条件,如果不满足,则会抛出IllegalArgumentExceptionIllegalStateException等运行时异常。

常用的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或其子类,定义自己的异常类。通常情况下,自定义异常类用于表示特定的异常情况,以便更好地对程序的异常情况进行分类处理和管理。自定义异常类可以包含自己的属性和方法,以提供更详细的异常信息和处理方式。

需要自定义异常的原因有以下几点:

  1. 更细粒度的异常控制:Java标准库中的异常类型比较全面,但是在实际应用中,我们可能需要更具体的异常类型来描述某种特定场景下的异常情况。例如,我们可以自定义一个PayErrorException来表示支付异常,这样可以更好地区分不同类型的异常情况,并进行不同的处理。

  2. 信息更丰富:Java标准库中的异常类型通常只包含错误信息,如果需要传递更多的相关信息,就需要自定义异常类。例如,我们可以在自定义异常类中添加一些额外的属性,如异常码、请求参数等,以便更好地记录和跟踪异常信息。

  3. 更友好的异常提示: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类中提供了两个静态属性naanaa1,分别表示响应码为300和4044的错误类型,方便通过类名.的方式直接调用。

测试效果

  1. 编写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"作为处理结果。

  2. 启动项目,使用 ApiFox 访问对应接口。

    • 访问send1(),由于参数为null,断言通过,返回字符串"success":

      image-20231101211357371

    • 访问send2(),由于参数为new ResCode(),不为null,断言未通过,抛出自定义异常之后被全局异常处理器GlobalExceptionHandler捕获,返回对应错误信息:

      image-20231101211431765

      同时,可以在控制台看到打印的日志信息

      image-20231101211511456


本文到此结束,感谢您的阅读,希望对您有所帮助!!!

相关文章:

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 第一行&#xf…...

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页面&#xff0c;不用css画一个注册页面。 最终效果如下&#xff1a; html页面代码如下&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>注册页面</title> </head>…...

Adobe After Effects 2024(Ae2024)在新版本中的升级有哪些?

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

超越 GLIP! | RegionSpot: 识别一切区域,多模态融合的开放世界物体识别新方法

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

webgoat-(A1)injection

SQL Injection (intro) SQL 命令主要分为三类&#xff1a; 数据操作语言 &#xff08;DML&#xff09;DML 语句可用于请求记录 &#xff08;SELECT&#xff09;、添加记录 &#xff08;INSERT&#xff09;、删除记录 &#xff08;DELETE&#xff09; 和修改现有记录 &#xff…...

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…...

AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; &#x1f680; AI篇持续更新中&#xff01;&#xff08;长期更新&#xff09; 目前2025年06月05日更新到&#xff1a; AI炼丹日志-28 - Aud…...

进程地址空间(比特课总结)

一、进程地址空间 1. 环境变量 1 &#xff09;⽤户级环境变量与系统级环境变量 全局属性&#xff1a;环境变量具有全局属性&#xff0c;会被⼦进程继承。例如当bash启动⼦进程时&#xff0c;环 境变量会⾃动传递给⼦进程。 本地变量限制&#xff1a;本地变量只在当前进程(ba…...

跨链模式:多链互操作架构与性能扩展方案

跨链模式&#xff1a;多链互操作架构与性能扩展方案 ——构建下一代区块链互联网的技术基石 一、跨链架构的核心范式演进 1. 分层协议栈&#xff1a;模块化解耦设计 现代跨链系统采用分层协议栈实现灵活扩展&#xff08;H2Cross架构&#xff09;&#xff1a; 适配层&#xf…...

在Ubuntu中设置开机自动运行(sudo)指令的指南

在Ubuntu系统中&#xff0c;有时需要在系统启动时自动执行某些命令&#xff0c;特别是需要 sudo权限的指令。为了实现这一功能&#xff0c;可以使用多种方法&#xff0c;包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法&#xff0c;并提供…...

高危文件识别的常用算法:原理、应用与企业场景

高危文件识别的常用算法&#xff1a;原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件&#xff0c;如包含恶意代码、敏感数据或欺诈内容的文档&#xff0c;在企业协同办公环境中&#xff08;如Teams、Google Workspace&#xff09;尤为重要。结合大模型技术&…...

Axios请求超时重发机制

Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式&#xff1a; 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...

工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配

AI3D视觉的工业赋能者 迁移科技成立于2017年&#xff0c;作为行业领先的3D工业相机及视觉系统供应商&#xff0c;累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成&#xff0c;通过稳定、易用、高回报的AI3D视觉系统&#xff0c;为汽车、新能源、金属制造等行…...

多种风格导航菜单 HTML 实现(附源码)

下面我将为您展示 6 种不同风格的导航菜单实现&#xff0c;每种都包含完整 HTML、CSS 和 JavaScript 代码。 1. 简约水平导航栏 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&qu…...

【JavaWeb】Docker项目部署

引言 之前学习了Linux操作系统的常见命令&#xff0c;在Linux上安装软件&#xff0c;以及如何在Linux上部署一个单体项目&#xff0c;大多数同学都会有相同的感受&#xff0c;那就是麻烦。 核心体现在三点&#xff1a; 命令太多了&#xff0c;记不住 软件安装包名字复杂&…...

怎么让Comfyui导出的图像不包含工作流信息,

为了数据安全&#xff0c;让Comfyui导出的图像不包含工作流信息&#xff0c;导出的图像就不会拖到comfyui中加载出来工作流。 ComfyUI的目录下node.py 直接移除 pnginfo&#xff08;推荐&#xff09;​​ 在 save_images 方法中&#xff0c;​​删除或注释掉所有与 metadata …...