Spring Assert 使用全面指南
作者:mobaiQAQ
在Spring框架中,Assert
类主要用于在开发过程中对代码进行验证,确保程序的正确性和稳定性。Assert
类属于org.springframework.util
包。它提供了一系列静态方法,用于在运行时检测条件是否满足,如果不满足则抛出IllegalArgumentException
异常。这对于参数校验、状态检查等场景非常有用。
Assert
写在前面
这篇文档原本并不在我的计划之内。我原本打算先完成 Spring AI 框架篇的内容,但那一部分的文档进展不太顺利,暂时难以成文。最近在研究 Spring AI 框架源码的过程中,我发现 Spring 团队大量使用了 Assert
类来校验方法参数的规范性。深入研究之后,我发现这个类非常实用,并且它与 org.junit
包下的 Assert
类有很大区别。本文旨在说明 org.springframework.util
包下的 Assert
类的作用、它与 org.junit
包下的 Assert
有何不同,以及它如何帮助我们简化日常开发,使代码更加优雅。
一、Assert是什么
在 Spring 框架中,Assert
是 org.springframework.util
包下的一个工具类,它通过一系列静态方法实现对方法参数、对象状态或业务逻辑前提的校验。其核心设计思想是:在程序运行时主动检查关键条件是否满足,若不满足则立即抛出异常,快速暴露问题,避免错误在后续流程中被掩盖或放大。
简单来说,Assert
的作用可以概括为 “条件校验 + 异常抛出的自动化封装”,仅专注于 “校验” 这一单一职责。它替代了传统开发中 “if (!条件) { throw new 异常(...); }
” 这种重复的校验逻辑,用更简洁的代码表达校验意图,让开发者能更专注于核心业务逻辑。
二、Assert怎么用
接下来让我们来举个例子说明这一点,在不使用 Assert
之前,我们大多数业务代码中的数据校验是这样做的
List<ChatMemory> list = chatMemoryMapper.selectBySessionId("111"); if (list == null || list.isEmpty()){ throw new RuntimeException("会话不存在"); } //下面处理会话相关逻辑
判断一个数据是否存在,如果存在继续下面的业务代码,如果不存在则抛出异常让外层捕获处理
使用Assert
来进行处理是这样子的
List<ChatMemory> list = chatMemoryMapper.selectBySessionId("111"); Assert.notEmpty(list, "会话不存在"); //下面处理会话相关逻辑
Assert.notEmpty()
方法的实现如下
@Contract("null, _ -> fail") public static void notEmpty(@Nullable Collection<?> collection, String message) { if (CollectionUtils.isEmpty(collection)) { throw new IllegalArgumentException(message); } }
Assert
类本身不包含任何业务逻辑,仅专注于 “校验” 这一单一职责。它的所有方法均为静态方法,无需实例化即可直接调用(如 Assert.notNull(obj, "对象不能为空")
),且校验失败时会抛出 IllegalArgumentException
(参数不合法)或 IllegalStateException
(状态不合法)等运行时异常。
虽然抛出异常需要处理,但也不应在所有业务接口中都重复编写 try-catch
代码,否则会降低代码的可读性并导致冗余。可将Assert
与 Spring MVC 的全局异常处理器结合使用
@ControllerAdvice public class GlobalExceptionHandler { /** * 处理Assert抛出的IllegalArgumentException异常 */ @ExceptionHandler(IllegalArgumentException.class) @ResponseBody @ResponseStatus(HttpStatus.BAD_REQUEST) public Map<String, Object> handleIllegalArgumentException(IllegalArgumentException e) { Map<String, Object> result = new HashMap<>(); result.put("code", 400); result.put("message", e.getMessage()); // 可以根据需要添加更多信息,如时间戳、请求路径等 return result; } /** * 处理Assert抛出的IllegalStateException异常 */ @ExceptionHandler(IllegalStateException.class) @ResponseBody @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) public Map<String, Object> handleIllegalStateException(IllegalStateException e) { Map<String, Object> result = new HashMap<>(); result.put("code", 500); result.put("message", e.getMessage()); return result; } }
当 Assert
校验失败抛出异常(如 IllegalArgumentException
)时,全局异常处理器会捕获并处理这些异常。这种做法的优势在于:
- 职责分离:业务代码只关注参数校验逻辑,异常处理逻辑集中在全局异常处理器中
- 代码简洁:避免了大量重复的
if-else
和try-catch
代码 - 统一格式:所有异常响应都遵循统一格式,便于前端处理
- 易于维护:异常处理逻辑集中管理,修改时只需调整一处
通过这种方式,我们既利用了 Assert 的简洁校验能力,又通过全局异常处理器实现了异常的统一管理,让代码更加优雅、易读和易维护。
三、Assert有哪些方法
分类 | 方法签名 | 作用描述 | 参数说明 | 抛出异常 | 示例代码 |
---|---|---|---|---|---|
对象校验 | notNull(Object object, String message) | 检查对象不为 null ,若为 null 则失败 | object :待校验对象;message :失败提示信息 | IllegalArgumentException | Assert.notNull(user, "用户对象不能为空"); |
isNull(Object object, String message) | 检查对象必须为 null ,若不为 null 则失败(特殊场景用) | 同 notNull | IllegalArgumentException | Assert.isNull(deletedUser, "已删除用户应不存在"); | |
集合 / 数组校验 | notEmpty(Collection<?> collection, String message) | 检查集合不为 null 且非空(size > 0 ) | collection :待校验集合;message :失败提示信息 | IllegalArgumentException | Assert.notEmpty(userList, "用户列表不能为空"); |
notEmpty(Object[] array, String message) | 检查数组不为 null 且非空(length > 0 ) | array :待校验数组;message :失败提示信息 | IllegalArgumentException | Assert.notEmpty(ids, "ID数组不能为空"); | |
noNullElements(Object[] array, String message) | 检查数组中无 null 元素(数组本身可空,但非空元素不能为 null ) | 同数组 notEmpty | IllegalArgumentException | Assert.noNullElements(names, "名称数组不可含null"); | |
字符串校验 | hasLength(String text, String message) | 检查字符串不为 null 且长度 > 0 (允许全空白,如 " " ) | text :待校验字符串;message :失败提示信息 | IllegalArgumentException | Assert.hasLength(username, "用户名长度不能为0"); |
hasText(String text, String message) | 检查字符串不为 null 且含非空白字符(trim().length > 0 ,排除全空白) | 同 hasLength | IllegalArgumentException | Assert.hasText(username, "用户名不能为空白"); | |
doesNotContain(String textToSearch, String substring, String message) | 检查字符串 textToSearch 中不包含子串 substring | textToSearch :被检查字符串;substring :禁止出现的子串;message :提示信息 | IllegalArgumentException | Assert.doesNotContain(username, "admin", "用户名不可含'admin'"); | |
条件校验 | isTrue(boolean condition, String message) | 检查布尔条件为 true ,若为 false 则失败(通用条件校验) | condition :待校验条件;message :失败提示信息 | IllegalArgumentException | Assert.isTrue(age >= 18, "年龄必须≥18岁"); |
state(boolean condition, String message) | 检查对象状态为 true (语义上用于状态检查,非参数校验) | 同 isTrue | IllegalStateException | Assert.state(order.isPaid(), "订单未支付,不能发货"); | |
类型校验 | isInstanceOf(Class<?> type, Object obj, String message) | 检查 obj 是 type 或其子类的实例 | type :预期类型;obj :待校验对象;message :提示信息 | IllegalArgumentException | Assert.isInstanceOf(User.class, obj, "对象必须是User类型"); |
isAssignable(Class<?> superType, Class<?> subType, String message) | 检查 subType 可赋值给 superType (即 superType 是 subType 的父类) | superType :父类型;subType :子类型;message :提示信息 | IllegalArgumentException | Assert.isAssignable(Number.class, Integer.class, "Integer必须是Number子类"); |
四、Assert与Assert的区别
org.springframework.util.Assert
与 org.junit.Assert
的最大区别一个抛出RuntimeException
另一个抛出 Error
。
从设计角度看 org.springframework.util.Assert
适合用于生产代码中的参数校验、状态检查(业务逻辑层的前提校验)
而 org.junit.Assert
适合用于测试代码中的结果断言(验证测试用例的预期结果)
到此这篇关于Spring Assert 使用全面指南的文章就介绍到这了,更多相关Spring Assert 使用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!