java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Spring Assert 使用

Spring Assert 使用全面指南

作者:mobaiQAQ

本文旨在说明org.springframework.util包下的Assert类的作用、它与org.junit包下的Assert有何不同,以及它如何帮助我们简化日常开发,使代码更加优雅,感兴趣的朋友跟随小编一起看看吧

在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 框架中,Assertorg.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)时,全局异常处理器会捕获并处理这些异常。这种做法的优势在于:

  1. 职责分离:业务代码只关注参数校验逻辑,异常处理逻辑集中在全局异常处理器中
  2. 代码简洁:避免了大量重复的if-elsetry-catch代码
  3. 统一格式:所有异常响应都遵循统一格式,便于前端处理
  4. 易于维护:异常处理逻辑集中管理,修改时只需调整一处

通过这种方式,我们既利用了 Assert 的简洁校验能力,又通过全局异常处理器实现了异常的统一管理,让代码更加优雅、易读和易维护。

三、Assert有哪些方法

分类方法签名作用描述参数说明抛出异常示例代码
对象校验notNull(Object object, String message)检查对象不为 null,若为 null 则失败object:待校验对象;message:失败提示信息IllegalArgumentExceptionAssert.notNull(user, "用户对象不能为空");
isNull(Object object, String message)检查对象必须为 null,若不为 null 则失败(特殊场景用)notNullIllegalArgumentExceptionAssert.isNull(deletedUser, "已删除用户应不存在");
集合 / 数组校验notEmpty(Collection<?> collection, String message)检查集合不为 null 且非空(size > 0collection:待校验集合;message:失败提示信息IllegalArgumentExceptionAssert.notEmpty(userList, "用户列表不能为空");
notEmpty(Object[] array, String message)检查数组不为 null 且非空(length > 0array:待校验数组;message:失败提示信息IllegalArgumentExceptionAssert.notEmpty(ids, "ID数组不能为空");
noNullElements(Object[] array, String message)检查数组中无 null 元素(数组本身可空,但非空元素不能为 null同数组 notEmptyIllegalArgumentExceptionAssert.noNullElements(names, "名称数组不可含null");
字符串校验hasLength(String text, String message)检查字符串不为 null 且长度 > 0(允许全空白,如 " "text:待校验字符串;message:失败提示信息IllegalArgumentExceptionAssert.hasLength(username, "用户名长度不能为0");
hasText(String text, String message)检查字符串不为 null 且含非空白字符(trim().length > 0,排除全空白)hasLengthIllegalArgumentExceptionAssert.hasText(username, "用户名不能为空白");
doesNotContain(String textToSearch, String substring, String message)检查字符串 textToSearch 中不包含子串 substringtextToSearch:被检查字符串;substring:禁止出现的子串;message:提示信息IllegalArgumentExceptionAssert.doesNotContain(username, "admin", "用户名不可含'admin'");
条件校验isTrue(boolean condition, String message)检查布尔条件为 true,若为 false 则失败(通用条件校验)condition:待校验条件;message:失败提示信息IllegalArgumentExceptionAssert.isTrue(age >= 18, "年龄必须≥18岁");
state(boolean condition, String message)检查对象状态为 true(语义上用于状态检查,非参数校验)isTrueIllegalStateExceptionAssert.state(order.isPaid(), "订单未支付,不能发货");
类型校验isInstanceOf(Class<?> type, Object obj, String message)检查 objtype 或其子类的实例type:预期类型;obj:待校验对象;message:提示信息IllegalArgumentExceptionAssert.isInstanceOf(User.class, obj, "对象必须是User类型");
isAssignable(Class<?> superType, Class<?> subType, String message)检查 subType 可赋值给 superType(即 superTypesubType 的父类)superType:父类型;subType:子类型;message:提示信息IllegalArgumentExceptionAssert.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 使用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文