# apiAssert **Repository Path**: min1854/api-assert ## Basic Information - **Project Name**: apiAssert - **Description**: 校验、断言框架 - **Primary Language**: Java - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 5 - **Forks**: 2 - **Created**: 2022-04-01 - **Last Updated**: 2026-06-02 ## Categories & Tags **Categories**: Uncategorized **Tags**: Java ## README # Api-Assert [![Maven Central](https://img.shields.io/maven-central/v/io.github.min1854/apiAssert)](https://central.sonatype.com/artifact/io.github.min1854/apiAssert) [![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](./LICENSE) > 轻量级 Java 断言框架 —— 让条件校验更优雅,告别重复的 `if-throw` 代码 - [GitHub 地址](https://github.com/min1854/apiAssert) - [Gitee 地址](https://gitee.com/min1854/api-assert) --- ## 📖 目录 - [简介](#简介) - [快速开始](#快速开始) - [检查器对比](#检查器对比) - [详细用法](#详细用法) - [版本说明](#版本说明) - [常见问题](#常见问题) - [相关链接](#相关链接) --- ## 简介 在日常开发中,我们经常需要编写这样的代码: ```java if (req == null) { throw new RuntimeException("参数不可为空"); } if (req.getId() == null) { throw new RuntimeException("id 不可为空"); } ``` **Api-Assert** 将这些重复的条件判断封装为链式调用,让代码更加简洁、可读、易维护。 ```java FunctionApiAssert apiAssert = FunctionApiAssert.create(RuntimeException::new); apiAssert.isNull(req, "参数不可为空") .isNull(req.getId(), "id 不可为空"); ``` ### 核心设计理念 > 将业务代码的执行流程抽象为一个 `assert` 对象,通过流程划分保证代码质量的下限,提高可维护性。 --- ## 快速开始 ### 1. 添加依赖 **Maven** ```xml io.github.min1854 apiAssert 2.0.5 ``` **Gradle** ```gradle implementation 'io.github.min1854:apiAssert:2.0.5' ``` ### 2. 第一个示例 ```java import io.github.min1854.apiAssert.check.FunctionApiAssert; public class OrderService { // 将断言声明为常量,避免重复创建 private static final FunctionApiAssert ASSERT = FunctionApiAssert.create(IllegalArgumentException::new); public void createOrder(CreateOrderRequest req) { ASSERT.isNull(req, "请求参数不能为空") .isNull(req.getUserId(), "用户 ID 不能为空") .isTrue(req.getAmount() <= 0, "金额必须大于 0"); // 业务逻辑... } } ``` 如果任一条件成立,会立即抛出 `IllegalArgumentException`,并携带对应的错误信息。 --- ## 检查器对比 | 检查器 | 异常创建方式 | 是否链式 | 是否立即抛出 | 适用场景 | | --- | --- | --- | --- | --- | | `FunctionApiAssert` | 函数式(由调用者提供) | ✅(多个条件校验) | ✅ | 常量定义、工具类、简单参数校验 | | `OperateApiAssert` | 函数式 | ✅(支持对象属性校验) | ✅ | 复杂对象校验、链式属性判断 | | `EnumFunctionApiAssert` | 枚举消息(函数式) | ✅ | ✅ | 国际化场景、统一错误码管理 | | `EnumOperateApiAssert` | 枚举消息 | ✅ | ✅ | 对象属性校验 + 国际化错误码 | | `FirstApiAssert` | 无(仅记录) | ✅ | ❌(需手动调用) | 收集多个校验结果,最后统一处理 | | `ReflectionApiAssert` | 反射 | ✅ | ✅ | 异常类型在运行时才能确定 | ### 如何选择? - **简单参数校验** → `FunctionApiAssert` - **对象属性校验**(如 `req.getXxx()`) → `OperateApiAssert` - **需要国际化或错误码** → `EnumFunctionApiAssert` / `EnumOperateApiAssert` - **需要收集所有错误后统一处理** → `FirstApiAssert` --- ## 详细用法 ### 1. FunctionApiAssert —— 基础条件校验 ```java FunctionApiAssert assert = FunctionApiAssert.create(RuntimeException::new); assert.isNull(obj, "对象不能为空") .nonNull(obj, "对象必须为空") .isTrue(flag, "条件必须为 true") .isFalse(flag, "条件必须为 false") .isEmpty(collection, "集合不能为空"); ``` ### 2. OperateApiAssert —— 对象属性校验 ```java // 创建一个带有被测对象的校验器 OperateApiAssert assert = OperateApiAssert.create(user, RuntimeException::new); // Lambda 方式获取属性,类似 MyBatis-Plus 的 LambdaWrapper assert.nonNull(User::getName, "用户名不能为空") .isTrue(User::getActive, "用户未激活") .isEmpty(User::getOrders, "订单列表不为空"); ``` ### 3. then() —— 对象转换与继续校验 ```java OperateApiAssert userAssert = OperateApiAssert.create(user, RuntimeException::new); // 获取用户的 ID 并继续校验 OperateApiAssert idAssert = userAssert.then(User::getId); idAssert.isTrue(id -> id > 0, "用户 ID 必须大于 0"); ``` ### 4. process() —— 校验前/后插入业务逻辑 ```java OperateApiAssert assert = OperateApiAssert.create(user, RuntimeException::new); assert.process(() -> { System.out.println("校验前置处理"); }) .process(userObj -> { System.out.println("当前用户: " + userObj); }) .process((userObj, self) -> { self.isNull(userObj.getParent(), "父级用户不存在"); }); ``` ### 5. 完整示例 ```java public class DemoService { private static final FunctionApiAssert ASSERT = FunctionApiAssert.create(IllegalArgumentException::new); public void processOrder(OrderReq req) { OperateApiAssert assert = OperateApiAssert.create(req, IllegalArgumentException::new); assert.isNull(OrderReq::getOrderId, "订单 ID 不能为空") .isTrue(OrderReq::getAmount > 0, "金额必须大于 0") .process(() -> validateInventory(req)) .then(OrderReq::getOrderId) .isTrue(id -> id.startsWith("ORD"), "订单 ID 格式错误"); // 业务逻辑... } private void validateInventory(OrderReq req) { // 库存校验逻辑 } } ``` --- ## 版本说明 ### ⚠️ 2.0 破坏性变更 2.0 版本进行了完全重构,与 1.x **不兼容**: - 包名变更(1.x 与 2.x 不同) - 继承体系重构 - 部分 API 方法签名调整 > 如果你正在使用 1.x 版本,建议阅读 [迁移指南](./MIGRATION.md)(待补充) ### 最新版本:2.0.5 - **优化**:所有 `message` 仅在条件成立后执行,避免无意义的字符串拼接开销 ### 历史版本 | 版本 | 主要变更 | | --- | --- | | 2.0.4 | 包名变更为 `io.github.min1854` | | 2.0.3 | 元组类重构,新增新的元组类 | | 2.0.2 | `handler` 默认方法提升至 `StandardApiAssert` | | 2.0.1 | `OperationApiAssert` 增加 `handler` 默认方法 | | 2.0.0 | 完全重构,新增枚举校验器 | > 完整版本日志请查看 [CHANGELOG.md](./CHANGELOG.md) --- ## 常见问题 ### Q1: 这些校验器是线程安全的吗? - `FunctionApiAssert` 是**无状态的**,可以作为常量在多个线程中共享 - `OperateApiAssert` 持有具体对象实例,**不应跨线程共享** ### Q2: 可以自定义异常类型吗? 可以。`FunctionApiAssert.create(Supplier)` 支持传入任何 `RuntimeException` 的子类。 ### Q3: 条件成立后才获取 message,如果 message 是动态生成的会有性能问题吗? 不会。框架保证 message 只在条件成立时执行,不会产生不必要的开销。 ### Q4: 与 Spring 的 Assert 工具类有什么区别? | 特性 | Spring Assert | Api-Assert | | --- | --- | --- | | 链式调用 | ❌ | ✅ | | Lambda 属性获取 | ❌ | ✅ | | 自定义异常 | 有限 | 完全支持 | | 对象转换继续校验 | ❌ | ✅(`then` 方法) | --- ## 相关链接 - [GitHub 仓库](https://github.com/min1854/apiAssert) - [Gitee 镜像](https://gitee.com/min1854/api-assert) - [问题反馈](https://github.com/min1854/apiAssert/issues) - [更新日志](./CHANGELOG.md) --- ## License Apache 2.0