Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7330e28579 | |||
| d73b8f445d | |||
| ba9ccebb56 | |||
| 821f43d154 | |||
| 4a604a64c4 | |||
| 9aa510820d | |||
| 98a7ed573b | |||
| f3c173818c | |||
| fdabd29347 | |||
| e22a95861d | |||
| edeaec85da | |||
| 5705686375 | |||
| 5b5d7b50d6 | |||
| aad5b6b4fe | |||
| 75a3c7798a | |||
| 7d0a25144b | |||
| 2977c9a7fb | |||
| 09d596b599 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -4,6 +4,8 @@ target/
|
||||
!**/src/main/**/target/
|
||||
!**/src/test/**/target/
|
||||
|
||||
.flattened-pom.xml
|
||||
|
||||
### STS ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
|
||||
9
NOTICE
Normal file
9
NOTICE
Normal file
@@ -0,0 +1,9 @@
|
||||
Plusone Validator
|
||||
Copyright 2022-present Zhou Xingyi
|
||||
|
||||
This product includes software developed by
|
||||
Zhou Xingyi (周兴毅) (https://gitea.zhouxy.xyz/plusone).
|
||||
|
||||
This product is licensed to you under the Apache License, Version 2.0
|
||||
(the "License"). You may not use this product except in compliance with
|
||||
the License.
|
||||
180
README.md
180
README.md
@@ -1,16 +1,41 @@
|
||||
# Plusone Validator
|
||||
|
||||
## 简介
|
||||
Plusone Validator 是一个校验库,使用 lambda 表达式(包括方法引用)和流式 API 构建校验规则,对对象进行校验。
|
||||
|
||||
Plusone Validator 是一个受 [FluentValidation](https://github.com/FluentValidation/FluentValidation) 启发的 Java 校验库,使用 Lambda 表达式(方法引用)和流式 API 构建声明式校验规则。
|
||||
|
||||
**特性:**
|
||||
- 链式调用
|
||||
- 支持 **POJO** 和 **Map** 两种校验模式
|
||||
- 每种校验规则支持四种错误信息提供方式(默认/自定义字符串/自定义异常/含属性值的自定义异常)
|
||||
- 基于 JDK 1.8
|
||||
|
||||
## 环境要求
|
||||
|
||||
- **JDK**:1.8 及以上
|
||||
- **编码**:UTF-8
|
||||
|
||||
## 安装
|
||||
Plusone Validator 暂未提交 maven 中央仓库,可 clone 代码仓库,通过 maven 安装到本地库,然后在项目中引入。
|
||||
|
||||
Plusone Validator 暂未发布至 Maven 中央仓库,需 clone 代码仓库后通过 `mvn install` 安装到本地仓库,然后在项目中引入:
|
||||
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>xyz.zhouxy.plusone</groupId>
|
||||
<artifactId>plusone-validator</artifactId>
|
||||
<version>${plusone-validator.version}</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
> 该项目依赖 [plusone-commons](https://gitea.zhouxy.xyz/plusone/plusone-commons),它本身依赖 Guava。
|
||||
|
||||
## 示例
|
||||
|
||||
### 校验对象
|
||||
以下示例基于一个包含姓名、邮箱、会员等级、客户编号、生日、地址等字段的 `Customer` 对象。
|
||||
|
||||
定义校验器:
|
||||
### 校验 POJO 对象
|
||||
|
||||
继承 `BaseValidator<T>`,在构造器中通过 `ruleFor` 添加规则链:
|
||||
```java
|
||||
class CustomerValidator extends BaseValidator<Customer> {
|
||||
|
||||
@@ -25,14 +50,9 @@ class CustomerValidator extends BaseValidator<Customer> {
|
||||
.notNull("生日不能为空")
|
||||
.must(LocalDate.now().minusYears(16)::isAfter, "用户必须大于16周岁");
|
||||
ruleFor(Customer::getAddress).length(20, 250, "地址长度必须在20-250之间");
|
||||
ruleFor((Customer customer) -> Pair.of(customer.getVipLevel(), customer.getBirthday()))
|
||||
.must(CustomerValidator::validateAge, "5级以上会员必须满18周岁");
|
||||
}
|
||||
|
||||
private static boolean validateAge(Pair<Integer, LocalDate> vipLevelAndBirthday) {
|
||||
Integer vipLevel = vipLevelAndBirthday.getLeft();
|
||||
LocalDate birthday = vipLevelAndBirthday.getRight();
|
||||
return vipLevel <= 5 || LocalDate.now().minusYears(18).isAfter(birthday);
|
||||
ruleFor(Customer::getVipLevel, Customer::getBirthday)
|
||||
.must((vipLevel, birthday) -> vipLevel <= 5 || LocalDate.now().minusYears(18).isAfter(birthday),
|
||||
"5级以上会员必须满18周岁");
|
||||
}
|
||||
|
||||
public static CustomerValidator getInstance() {
|
||||
@@ -51,7 +71,11 @@ public void foo(Customer customer) {
|
||||
|
||||
### 校验 Map
|
||||
|
||||
定义校验器:
|
||||
继承 `MapValidator<K,V>`,在构造器中通过 `ruleForString`、`ruleForInt` 等方法按 key 添加规则链。
|
||||
|
||||
`validateAndCopy()` 会**先校验,然后仅保留白名单 key**(构造时传入的 `FIELD_NAMES`),多余字段会被自动剥离,可防止 Map 注入攻击。
|
||||
|
||||
> 注意泛型类型见证语法 `this.<LocalDate>ruleFor(...)` — 当 Map 的 value 类型是 `Object` 时,需显式指定实际类型。
|
||||
```java
|
||||
class CustomerMapValidator extends MapValidator<String, Object> {
|
||||
|
||||
@@ -73,15 +97,9 @@ class CustomerMapValidator extends MapValidator<String, Object> {
|
||||
.notNull("生日不能为空")
|
||||
.must(LocalDate.now().minusYears(16)::isAfter, "用户必须大于16周岁");
|
||||
ruleForString("address").length(20, 250, "地址长度必须在20-250之间");
|
||||
this.<Pair<Integer, LocalDate>>ruleFor((Map<String, Object> customer) ->
|
||||
Pair.of(MapUtils.getInteger(customer, "vipLevel"), (LocalDate) customer.get("birthday")))
|
||||
.must(CustomerMapValidator::validateAge, "5级以上会员必须满18周岁");
|
||||
}
|
||||
|
||||
private static boolean validateAge(Pair<Integer, LocalDate> vipLevelAndBirthday) {
|
||||
Integer vipLevel = vipLevelAndBirthday.getLeft();
|
||||
LocalDate birthday = vipLevelAndBirthday.getRight();
|
||||
return vipLevel <= 5 || LocalDate.now().minusYears(18).isAfter(birthday);
|
||||
this.<Integer, LocalDate>ruleForPair("vipLevel", "birthday")
|
||||
.must((vipLevel, birthday) -> vipLevel <= 5 || LocalDate.now().minusYears(18).isAfter(birthday),
|
||||
"5级以上会员必须满18周岁");
|
||||
}
|
||||
|
||||
public static CustomerMapValidator getInstance() {
|
||||
@@ -97,10 +115,120 @@ public void foo(Map<String, Object> customer) {
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
## 快速参考
|
||||
|
||||
### ruleFor 方法一览
|
||||
|
||||
| 方法 | 属性类型 | 适用场景 |
|
||||
|------|---------|---------|
|
||||
| `ruleFor(getter)` | 任意类型 | 通用对象属性校验 |
|
||||
| `ruleForString(getter)` | `String` | 字符串属性校验 |
|
||||
| `ruleForInt(getter)` | `Integer` | 整数属性校验 |
|
||||
| `ruleForLong(getter)` | `Long` | 长整数属性校验 |
|
||||
| `ruleForDouble(getter)` | `Double` | 浮点数属性校验 |
|
||||
| `ruleForBool(getter)` | `Boolean` | 布尔属性校验 |
|
||||
| `ruleForComparable(getter)` | `Comparable` | 可比较类型属性校验 |
|
||||
| `ruleForCollection(getter)` | `Collection<E>` | 集合属性校验 |
|
||||
| `ruleForArray(getter)` | `E[]` | 数组属性校验 |
|
||||
| `ruleFor(g1, g2)` | 二元组 | 两个属性的联合校验 |
|
||||
|
||||
### 校验规则一览
|
||||
|
||||
| 规则 | Object | Comparable | 数值 | String | Bool | 集合/数组 | 说明 |
|
||||
|------|:---:|:---:|:---:|:---:|:---:|:---:|------|
|
||||
| `notNull()` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | 不为 null |
|
||||
| `isNull()` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | 必须为 null |
|
||||
| `equal(obj)` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | 等于给定值 |
|
||||
| `notEqual(obj)` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | 不等于给定值 |
|
||||
| `must(pred)` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | 自定义条件 |
|
||||
| `gt/ge/lt/le` | — | — | ✅ | — | — | — | 大于/大于等于/小于/小于等于 |
|
||||
| `inRange(range)` | — | ✅ | ✅ | ✅ | — | — | 值在指定区间内 |
|
||||
| `notBlank()` | — | — | — | ✅ | — | — | 不为空白字符串 |
|
||||
| `notEmpty()` | — | — | — | ✅ | — | ✅ | 不为空(长度 > 0) |
|
||||
| `isEmpty()` | — | — | — | — | — | ✅ | 必须为空 |
|
||||
| `length(min, max)` | — | — | — | ✅ | — | ✅ | 长度/大小在范围内 |
|
||||
| `emailAddress()` | — | — | — | ✅ | — | — | 满足邮箱格式 |
|
||||
| `matches(pattern)` | — | — | — | ✅ | — | — | 匹配正则表达式 |
|
||||
| `matchesAny(patterns)` | — | — | — | ✅ | — | — | 匹配任一正则 |
|
||||
| `matchesAll(patterns)` | — | — | — | ✅ | — | — | 匹配所有正则 |
|
||||
| `allMatch(pred)` | — | — | — | — | — | ✅ | 所有元素满足条件 |
|
||||
| `isTrueValue()` | — | — | — | — | ✅ | — | 必须为 true |
|
||||
| `isFalseValue()` | — | — | — | — | ✅ | — | 必须为 false |
|
||||
|
||||
### 自定义错误信息
|
||||
|
||||
每个校验规则都支持四种错误信息提供方式:
|
||||
|
||||
```java
|
||||
// 1. 默认消息
|
||||
ruleFor(Person::getName).notNull();
|
||||
|
||||
// 2. 自定义字符串
|
||||
ruleFor(Person::getName).notNull("姓名不能为空");
|
||||
|
||||
// 3. 自定义异常(Supplier)
|
||||
ruleFor(Person::getName).notNull(() -> new BizException("姓名不能为空"));
|
||||
|
||||
// 4. 自定义异常 + 属性值注入(Function)
|
||||
ruleFor(Person::getAge).gt(0, age -> new BizException("年龄必须 > 0,当前值:%d", age));
|
||||
```
|
||||
|
||||
### Null 值处理
|
||||
|
||||
多数校验规则对 `null` **宽松处理**(视为通过),让用户通过 `notNull()` 显式控制 null 行为:
|
||||
|
||||
```java
|
||||
// ✅ null 视为通过 — 不会因 NPE 失败
|
||||
ruleFor(Person::getEmail).emailAddress();
|
||||
|
||||
// ✅ 显式拒绝 null
|
||||
ruleFor(Person::getEmail).notNull("邮箱不能为空").emailAddress();
|
||||
```
|
||||
|
||||
例外:`notBlank()` 和 `notEmpty()` 将 `null` 视为不通过(null 本身就是 blank/empty)。
|
||||
|
||||
### 嵌套对象校验
|
||||
|
||||
使用 `withRule(Consumer)` 在子类构造器中调用嵌套校验器:
|
||||
|
||||
```java
|
||||
class OrderValidator extends BaseValidator<Order> {
|
||||
private static final OrderValidator INSTANCE = new OrderValidator();
|
||||
|
||||
private OrderValidator() {
|
||||
ruleFor(Order::getOrderId).notBlank("订单号不能为空");
|
||||
|
||||
// 嵌套校验 Customer
|
||||
withRule(order -> {
|
||||
Customer customer = order.getCustomer();
|
||||
CustomerValidator.getInstance().validate(customer);
|
||||
});
|
||||
|
||||
// 需要自定义错误信息时,try-catch 重新包装
|
||||
withRule(order -> {
|
||||
try {
|
||||
AddressValidator.getInstance().validate(order.getAddress());
|
||||
} catch (ValidationException e) {
|
||||
throw ValidationException.withMessage("地址校验失败:%s", e.getMessage());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 对象整体校验
|
||||
|
||||
使用 `withRule(Predicate)` 对多个属性进行联合校验:
|
||||
|
||||
```java
|
||||
// 三个及以上字段的联合校验
|
||||
withRule(order -> order.getTotalAmount().compareTo(order.getPaidAmount()) >= 0,
|
||||
"订单金额不能小于已付金额");
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 其他
|
||||
## 关于本项目
|
||||
|
||||
Plusone Validator 是个人在学习 Microsoft 的 [eShop](https://github.com/dotnet/eShop) 时,被其中 [FluentValidation](https://github.com/FluentValidation/FluentValidation) 的 API 所吸引,出于学习和个人使用的目的进行开发和维护。使用 [Apache License 2.0](./LICENSE) 开源。
|
||||
|
||||
欢迎通过 issue 反馈使用过程中发现的问题和建议。
|
||||
Plusone Validator 受 .NET 的 [FluentValidation](https://github.com/FluentValidation/FluentValidation) API 启发,使用 [Apache License 2.0](./LICENSE) 开源。
|
||||
|
||||
@@ -8,28 +8,21 @@
|
||||
<parent>
|
||||
<groupId>xyz.zhouxy.plusone</groupId>
|
||||
<artifactId>plusone-validator-parent</artifactId>
|
||||
<version>1.0.0-RC1</version>
|
||||
<version>1.0.0-RC4</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<artifactId>plusone-validator</artifactId>
|
||||
<name>plusone-validator</name>
|
||||
<url>http://zhouxy.xyz</url>
|
||||
|
||||
<description>
|
||||
Plusone Validator 是一个校验库,使用 lambda 表达式(包括方法引用)和流式 API 构建校验规则,对对象进行校验。
|
||||
</description>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>xyz.zhouxy.plusone</groupId>
|
||||
<artifactId>plusone-commons</artifactId>
|
||||
<version>1.1.0-RC1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023-2025 the original author or authors.
|
||||
* Copyright 2023-present ZhouXY
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -151,11 +151,17 @@ public class ArrayPropertyValidator<T, E>
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验是否所有元素都满足指定条件
|
||||
*
|
||||
* <p>
|
||||
* 当数组为 {@code null} 时,视为通过。如果需要校验值不为 {@code null},请使用 {@link #notNull()} 方法。
|
||||
*
|
||||
* @param condition 校验条件
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final ArrayPropertyValidator<T, E> allMatch(final Predicate<E> condition) {
|
||||
return withRule(c -> {
|
||||
if (ArrayTools.isEmpty(c)) {
|
||||
return;
|
||||
}
|
||||
for (E element : c) {
|
||||
if (!condition.test(element)) {
|
||||
throw ValidationException.withMessage("All elements must match the condition.");
|
||||
@@ -167,6 +173,9 @@ public class ArrayPropertyValidator<T, E>
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验是否所有元素都满足指定条件
|
||||
*
|
||||
* <p>
|
||||
* 当数组为 {@code null} 时,视为通过。如果需要校验值不为 {@code null},请使用 {@link #notNull()} 方法。
|
||||
*
|
||||
* @param condition 校验条件
|
||||
* @param errorMessage 异常信息
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
@@ -174,6 +183,9 @@ public class ArrayPropertyValidator<T, E>
|
||||
public final ArrayPropertyValidator<T, E> allMatch(
|
||||
final Predicate<E> condition, final String errorMessage) {
|
||||
return withRule(c -> {
|
||||
if (ArrayTools.isEmpty(c)) {
|
||||
return;
|
||||
}
|
||||
for (E element : c) {
|
||||
if (!condition.test(element)) {
|
||||
throw ValidationException.withMessage(errorMessage);
|
||||
@@ -185,6 +197,9 @@ public class ArrayPropertyValidator<T, E>
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验是否所有元素都满足指定条件
|
||||
*
|
||||
* <p>
|
||||
* 当数组为 {@code null} 时,视为通过。如果需要校验值不为 {@code null},请使用 {@link #notNull()} 方法。
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param condition 校验条件
|
||||
* @param exceptionSupplier 自定义异常
|
||||
@@ -193,6 +208,9 @@ public class ArrayPropertyValidator<T, E>
|
||||
public final <X extends RuntimeException> ArrayPropertyValidator<T, E> allMatch(
|
||||
final Predicate<E> condition, final Supplier<X> exceptionSupplier) {
|
||||
return withRule(c -> {
|
||||
if (ArrayTools.isEmpty(c)) {
|
||||
return;
|
||||
}
|
||||
for (E element : c) {
|
||||
if (!condition.test(element)) {
|
||||
throw exceptionSupplier.get();
|
||||
@@ -204,6 +222,9 @@ public class ArrayPropertyValidator<T, E>
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验是否所有元素都满足指定条件
|
||||
*
|
||||
* <p>
|
||||
* 当数组为 {@code null} 时,视为通过。如果需要校验值不为 {@code null},请使用 {@link #notNull()} 方法。
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param condition 校验条件
|
||||
* @param exceptionFunction 自定义异常
|
||||
@@ -212,6 +233,9 @@ public class ArrayPropertyValidator<T, E>
|
||||
public final <X extends RuntimeException> ArrayPropertyValidator<T, E> allMatch(
|
||||
final Predicate<E> condition, final Function<E, X> exceptionFunction) {
|
||||
return withRule(c -> {
|
||||
if (ArrayTools.isEmpty(c)) {
|
||||
return;
|
||||
}
|
||||
for (E element : c) {
|
||||
if (!condition.test(element)) {
|
||||
throw exceptionFunction.apply(element);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2025 the original author or authors.
|
||||
* Copyright 2025-present ZhouXY
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -33,7 +33,7 @@ import com.google.common.collect.Range;
|
||||
*/
|
||||
public abstract class BaseComparablePropertyValidator<
|
||||
T,
|
||||
TProperty extends Comparable<TProperty>,
|
||||
TProperty extends Comparable<? super TProperty>,
|
||||
TPropertyValidator extends BaseComparablePropertyValidator<T, TProperty, TPropertyValidator>>
|
||||
extends BasePropertyValidator<T, TProperty, TPropertyValidator> {
|
||||
|
||||
@@ -47,9 +47,9 @@ public abstract class BaseComparablePropertyValidator<
|
||||
* @param range 区间
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final TPropertyValidator inRange(final Range<TProperty> range) {
|
||||
public final TPropertyValidator inRange(final Range<? super TProperty> range) {
|
||||
return withRule(Conditions.inRange(range), value -> ValidationException.withMessage(
|
||||
"The input must in the interval %s. You entered %s.", range, value));
|
||||
"The input must in the interval %s. You entered %s.", range, value));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -60,7 +60,7 @@ public abstract class BaseComparablePropertyValidator<
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final TPropertyValidator inRange(
|
||||
final Range<TProperty> range, final String errorMessage) {
|
||||
final Range<? super TProperty> range, final String errorMessage) {
|
||||
return withRule(Conditions.inRange(range), errorMessage);
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ public abstract class BaseComparablePropertyValidator<
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final <X extends RuntimeException> TPropertyValidator inRange(
|
||||
final Range<TProperty> range, final Supplier<X> exceptionSupplier) {
|
||||
final Range<? super TProperty> range, final Supplier<X> exceptionSupplier) {
|
||||
return withRule(Conditions.inRange(range), exceptionSupplier);
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ public abstract class BaseComparablePropertyValidator<
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final <X extends RuntimeException> TPropertyValidator inRange(
|
||||
final Range<TProperty> range, final Function<TProperty, X> exceptionFunction) {
|
||||
final Range<? super TProperty> range, final Function<TProperty, X> exceptionFunction) {
|
||||
return withRule(Conditions.inRange(range), exceptionFunction);
|
||||
}
|
||||
|
||||
@@ -95,8 +95,8 @@ public abstract class BaseComparablePropertyValidator<
|
||||
*/
|
||||
private static class Conditions {
|
||||
|
||||
private static <TProperty extends Comparable<TProperty>> Predicate<TProperty> inRange(
|
||||
final Range<TProperty> range) {
|
||||
private static <TProperty extends Comparable<? super TProperty>> Predicate<TProperty> inRange(
|
||||
final Range<? super TProperty> range) {
|
||||
return value -> value == null || range.contains(value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2024-2025 the original author or authors.
|
||||
* Copyright 2024-present ZhouXY
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -258,6 +258,9 @@ public abstract class BasePropertyValidator<
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否等于给定值
|
||||
*
|
||||
* <p>
|
||||
* 当值为 {@code null} 时,视为通过。如果需要校验值不为 {@code null},请使用 {@link #notNull()} 方法。
|
||||
*
|
||||
* @param obj 用于比较的对象
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
@@ -269,6 +272,9 @@ public abstract class BasePropertyValidator<
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否等于给定值
|
||||
*
|
||||
* <p>
|
||||
* 当值为 {@code null} 时,视为通过。如果需要校验值不为 {@code null},请使用 {@link #notNull()} 方法。
|
||||
*
|
||||
* @param obj 用于比较的对象
|
||||
* @param errorMessage 异常信息
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
@@ -281,6 +287,9 @@ public abstract class BasePropertyValidator<
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否等于给定值
|
||||
*
|
||||
* <p>
|
||||
* 当值为 {@code null} 时,视为通过。如果需要校验值不为 {@code null},请使用 {@link #notNull()} 方法。
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param obj 用于比较的对象
|
||||
* @param exceptionSupplier 自定义异常
|
||||
@@ -294,6 +303,9 @@ public abstract class BasePropertyValidator<
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否等于给定值
|
||||
*
|
||||
* <p>
|
||||
* 当值为 {@code null} 时,视为通过。如果需要校验值不为 {@code null},请使用 {@link #notNull()} 方法。
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param obj 用于比较的对象
|
||||
* @param exceptionFunction 自定义异常
|
||||
@@ -313,7 +325,10 @@ public abstract class BasePropertyValidator<
|
||||
// ================================
|
||||
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否等于给定值
|
||||
* 添加一条校验属性的规则,校验属性是否不等于给定值
|
||||
*
|
||||
* <p>
|
||||
* 当值为 {@code null} 时,视为通过。如果需要校验值不为 {@code null},请使用 {@link #notNull()} 方法。
|
||||
*
|
||||
* @param obj 用于比较的对象
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
@@ -324,7 +339,10 @@ public abstract class BasePropertyValidator<
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否等于给定值
|
||||
* 添加一条校验属性的规则,校验属性是否不等于给定值
|
||||
*
|
||||
* <p>
|
||||
* 当值为 {@code null} 时,视为通过。如果需要校验值不为 {@code null},请使用 {@link #notNull()} 方法。
|
||||
*
|
||||
* @param obj 用于比较的对象
|
||||
* @param errorMessage 异常信息
|
||||
@@ -335,7 +353,10 @@ public abstract class BasePropertyValidator<
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否等于给定值
|
||||
* 添加一条校验属性的规则,校验属性是否不等于给定值
|
||||
*
|
||||
* <p>
|
||||
* 当值为 {@code null} 时,视为通过。如果需要校验值不为 {@code null},请使用 {@link #notNull()} 方法。
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param obj 用于比较的对象
|
||||
@@ -348,7 +369,10 @@ public abstract class BasePropertyValidator<
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验属性是否等于给定值
|
||||
* 添加一条校验属性的规则,校验属性是否不等于给定值
|
||||
*
|
||||
* <p>
|
||||
* 当值为 {@code null} 时,视为通过。如果需要校验值不为 {@code null},请使用 {@link #notNull()} 方法。
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param obj 用于比较的对象
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2022-2025 the original author or authors.
|
||||
* Copyright 2022-present ZhouXY
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,6 +19,7 @@ package xyz.zhouxy.plusone.validator;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.AbstractMap.SimpleImmutableEntry;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
@@ -108,7 +109,7 @@ public abstract class BaseValidator<T> implements IValidator<T> {
|
||||
* 示例:{@code Person::getName}。
|
||||
* @return {@code ComparablePropertyValidator}。用于添加针对该属性的校验规则。
|
||||
*/
|
||||
protected final <R extends Comparable<R>> ComparablePropertyValidator<T, R> ruleForComparable(
|
||||
protected final <R extends Comparable<? super R>> ComparablePropertyValidator<T, R> ruleForComparable(
|
||||
Function<T, R> getter) {
|
||||
ComparablePropertyValidator<T, R> validator = new ComparablePropertyValidator<>(getter);
|
||||
this.rules.add(validator::validate);
|
||||
@@ -280,13 +281,34 @@ public abstract class BaseValidator<T> implements IValidator<T> {
|
||||
* @param <V2> 第二个元素的类型
|
||||
* @param getter 根据对象构造一个二元组,通常是两个属性的值。
|
||||
* @return {@code PairPropertyValidator}。用于添加针对该二元组的校验规则。
|
||||
*
|
||||
* @deprecated 请使用 {@link #ruleFor(Function, Function)} 代替。
|
||||
*/
|
||||
protected final <V1, V2> PairPropertyValidator<T, V1, V2> ruleForPair(Function<T, Entry<V1, V2>> getter) {
|
||||
@Deprecated
|
||||
protected final <V1, V2> PairPropertyValidator<T, V1, V2> ruleForPair( // NOSONAR
|
||||
Function<T, Entry<V1, V2>> getter) {
|
||||
PairPropertyValidator<T, V1, V2> validator = new PairPropertyValidator<>(getter);
|
||||
this.rules.add(validator::validate);
|
||||
return validator;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一个针对二元组的校验器
|
||||
*
|
||||
* @param <V1> 第1个元素的类型
|
||||
* @param <V2> 第2个元素的类型
|
||||
* @param v1Getter 用于从目标对象获取第1个元素的函数式接口。示例:{@code Person::getName1}。
|
||||
* @param v2Getter 用于从目标对象获取第2个元素的函数式接口。示例:{@code Person::getName2}。
|
||||
* @return {@code PairPropertyValidator}。用于添加针对该二元组的校验规则。
|
||||
*/
|
||||
protected final <V1, V2> PairPropertyValidator<T, V1, V2> ruleFor(
|
||||
Function<T, V1> v1Getter, Function<T, V2> v2Getter) {
|
||||
PairPropertyValidator<T, V1, V2> validator = new PairPropertyValidator<>(
|
||||
t -> new SimpleImmutableEntry<>(v1Getter.apply(t), v2Getter.apply(t)));
|
||||
this.rules.add(validator::validate);
|
||||
return validator;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void validate(T obj) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023-2025 the original author or authors.
|
||||
* Copyright 2023-present ZhouXY
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023-2025 the original author or authors.
|
||||
* Copyright 2023-present ZhouXY
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -151,36 +151,56 @@ public class CollectionPropertyValidator<T, E>
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验是否所有元素都满足指定条件
|
||||
*
|
||||
* <p>
|
||||
* 当集合为 {@code null} 时,视为通过。如果需要校验值不为 {@code null},请使用 {@link #notNull()} 方法。
|
||||
*
|
||||
* @param condition 校验条件
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final CollectionPropertyValidator<T, E> allMatch(
|
||||
final Predicate<E> condition) {
|
||||
return withRule(c -> c.forEach(element -> {
|
||||
if (!condition.test(element)) {
|
||||
throw ValidationException.withMessage("All elements must match the condition.");
|
||||
return withRule(c -> {
|
||||
if (CollectionTools.isEmpty(c)) {
|
||||
return;
|
||||
}
|
||||
}));
|
||||
c.forEach(element -> {
|
||||
if (!condition.test(element)) {
|
||||
throw ValidationException.withMessage("All elements must match the condition.");
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验是否所有元素都满足指定条件
|
||||
*
|
||||
* <p>
|
||||
* 当集合为 {@code null} 时,视为通过。如果需要校验值不为 {@code null},请使用 {@link #notNull()} 方法。
|
||||
*
|
||||
* @param condition 校验条件
|
||||
* @param errorMessage 异常信息
|
||||
* @return 当前校验器实例,用于链式调用
|
||||
*/
|
||||
public final CollectionPropertyValidator<T, E> allMatch(
|
||||
final Predicate<E> condition, final String errorMessage) {
|
||||
return withRule(c -> c.forEach(element -> {
|
||||
if (!condition.test(element)) {
|
||||
throw ValidationException.withMessage(errorMessage);
|
||||
return withRule(c -> {
|
||||
if (CollectionTools.isEmpty(c)) {
|
||||
return;
|
||||
}
|
||||
}));
|
||||
c.forEach(element -> {
|
||||
if (!condition.test(element)) {
|
||||
throw ValidationException.withMessage(errorMessage);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验是否所有元素都满足指定条件
|
||||
*
|
||||
* <p>
|
||||
* 当集合为 {@code null} 时,视为通过。如果需要校验值不为 {@code null},请使用 {@link #notNull()} 方法。
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param condition 校验条件
|
||||
* @param exceptionSupplier 自定义异常
|
||||
@@ -188,16 +208,24 @@ public class CollectionPropertyValidator<T, E>
|
||||
*/
|
||||
public final <X extends RuntimeException> CollectionPropertyValidator<T, E> allMatch(
|
||||
final Predicate<E> condition, final Supplier<X> exceptionSupplier) {
|
||||
return withRule(c -> c.forEach(element -> {
|
||||
if (!condition.test(element)) {
|
||||
throw exceptionSupplier.get();
|
||||
return withRule(c -> {
|
||||
if (CollectionTools.isEmpty(c)) {
|
||||
return;
|
||||
}
|
||||
}));
|
||||
c.forEach(element -> {
|
||||
if (!condition.test(element)) {
|
||||
throw exceptionSupplier.get();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一条校验属性的规则,校验是否所有元素都满足指定条件
|
||||
*
|
||||
* <p>
|
||||
* 当集合为 {@code null} 时,视为通过。如果需要校验值不为 {@code null},请使用 {@link #notNull()} 方法。
|
||||
*
|
||||
* @param <X> 自定义异常类型
|
||||
* @param condition 校验条件
|
||||
* @param exceptionFunction 自定义异常
|
||||
@@ -205,11 +233,16 @@ public class CollectionPropertyValidator<T, E>
|
||||
*/
|
||||
public final <X extends RuntimeException> CollectionPropertyValidator<T, E> allMatch(
|
||||
final Predicate<E> condition, final Function<E, X> exceptionFunction) {
|
||||
return withRule(c -> c.forEach(element -> {
|
||||
if (!condition.test(element)) {
|
||||
throw exceptionFunction.apply(element);
|
||||
return withRule(c -> {
|
||||
if (CollectionTools.isEmpty(c)) {
|
||||
return;
|
||||
}
|
||||
}));
|
||||
c.forEach(element -> {
|
||||
if (!condition.test(element)) {
|
||||
throw exceptionFunction.apply(element);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// ================================
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2025 the original author or authors.
|
||||
* Copyright 2025-present ZhouXY
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -26,7 +26,7 @@ import java.util.function.Function;
|
||||
* @see com.google.common.collect.Range
|
||||
* @author ZhouXY
|
||||
*/
|
||||
public class ComparablePropertyValidator<T, TProperty extends Comparable<TProperty>>
|
||||
public class ComparablePropertyValidator<T, TProperty extends Comparable<? super TProperty>>
|
||||
extends BaseComparablePropertyValidator<T, TProperty, ComparablePropertyValidator<T, TProperty>> {
|
||||
|
||||
ComparablePropertyValidator(Function<T, ? extends TProperty> getter) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023-2025 the original author or authors.
|
||||
* Copyright 2023-present ZhouXY
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -48,7 +48,7 @@ public class DoublePropertyValidator<T>
|
||||
*/
|
||||
public final DoublePropertyValidator<T> gt(final double min) {
|
||||
return withRule(Conditions.greaterThan(min),
|
||||
"The input must be greater than '%s'.", min);
|
||||
"The input must be greater than '%f'.", min);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -105,7 +105,7 @@ public class DoublePropertyValidator<T>
|
||||
*/
|
||||
public final DoublePropertyValidator<T> ge(final double min) {
|
||||
return withRule(Conditions.greaterThanOrEqualTo(min),
|
||||
"The input must be greater than or equal to '%s'.", min);
|
||||
"The input must be greater than or equal to '%f'.", min);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -162,7 +162,7 @@ public class DoublePropertyValidator<T>
|
||||
*/
|
||||
public final DoublePropertyValidator<T> lt(final double max) {
|
||||
return withRule(Conditions.lessThan(max),
|
||||
"The input must be less than '%s'.", max);
|
||||
"The input must be less than '%f'.", max);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -219,7 +219,7 @@ public class DoublePropertyValidator<T>
|
||||
*/
|
||||
public final DoublePropertyValidator<T> le(final double max) {
|
||||
return withRule(Conditions.lessThanOrEqualTo(max),
|
||||
"The input must be less than or equal to '%s'.", max);
|
||||
"The input must be less than or equal to '%f'.", max);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023-2025 the original author or authors.
|
||||
* Copyright 2023-present ZhouXY
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2025 the original author or authors.
|
||||
* Copyright 2025-present ZhouXY
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023-2025 the original author or authors.
|
||||
* Copyright 2023-present ZhouXY
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023-2025 the original author or authors.
|
||||
* Copyright 2023-present ZhouXY
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2024-2025 the original author or authors.
|
||||
* Copyright 2024-present ZhouXY
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,11 +16,9 @@
|
||||
|
||||
package xyz.zhouxy.plusone.validator;
|
||||
|
||||
import java.util.AbstractMap.SimpleImmutableEntry;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -95,7 +93,7 @@ public abstract class MapValidator<K, V> extends BaseValidator<Map<K, V>> {
|
||||
validate(obj);
|
||||
return obj.entrySet().stream()
|
||||
.filter(kv -> keys.contains(kv.getKey()))
|
||||
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
|
||||
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (v1, v2) -> v2));
|
||||
}
|
||||
|
||||
// ================================
|
||||
@@ -175,7 +173,8 @@ public abstract class MapValidator<K, V> extends BaseValidator<Map<K, V>> {
|
||||
* @param key key
|
||||
* @return 属性校验器
|
||||
*/
|
||||
protected final <E extends Comparable<E>> ComparablePropertyValidator<Map<K, V>, E> ruleForComparable(K key) {
|
||||
protected final <E extends Comparable<? super E>> //
|
||||
ComparablePropertyValidator<Map<K, V>, E> ruleForComparable(K key) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Function<Map<K, V>, E> getter = m -> (E) m.get(key);
|
||||
return ruleForComparable(getter);
|
||||
@@ -196,18 +195,19 @@ public abstract class MapValidator<K, V> extends BaseValidator<Map<K, V>> {
|
||||
|
||||
/**
|
||||
* 添加一个属性校验器,对指定的两个 key 对应的 value 进行校验
|
||||
* @param <V1> 第一个属性的类型
|
||||
* @param <V2> 第二个属性的类型
|
||||
* @param k1 第一个 key
|
||||
* @param k2 第二个 key
|
||||
* @param <V1> 第1个属性的类型
|
||||
* @param <V2> 第2个属性的类型
|
||||
* @param k1 第1个 key
|
||||
* @param k2 第2个 key
|
||||
* @return 属性校验器
|
||||
*/
|
||||
protected final <V1 extends V, V2 extends V>
|
||||
PairPropertyValidator<Map<K, V>, V1, V2> ruleForPair(K k1, K k2) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Function<Map<K, V>, Entry<V1, V2>> getter = m ->
|
||||
new SimpleImmutableEntry<>((V1) m.get(k1), (V2) m.get(k2));
|
||||
return ruleForPair(getter);
|
||||
final Function<Map<K, V>, V1> v1Getter = m -> (V1) m.get(k1);
|
||||
@SuppressWarnings("unchecked")
|
||||
final Function<Map<K, V>, V2> v2Getter = m -> (V2) m.get(k2);
|
||||
return ruleFor(v1Getter, v2Getter);
|
||||
}
|
||||
|
||||
// ================================
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023-2025 the original author or authors.
|
||||
* Copyright 2023-present ZhouXY
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -28,7 +28,7 @@ import java.util.function.Function;
|
||||
public class ObjectPropertyValidator<T, TProperty>
|
||||
extends BasePropertyValidator<T, TProperty, ObjectPropertyValidator<T, TProperty>> {
|
||||
|
||||
ObjectPropertyValidator(Function<T, TProperty> getter) {
|
||||
ObjectPropertyValidator(Function<T, ? extends TProperty> getter) {
|
||||
super(getter);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2025 the original author or authors.
|
||||
* Copyright 2025-present ZhouXY
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023-2025 the original author or authors.
|
||||
* Copyright 2023-present ZhouXY
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2025 the original author or authors.
|
||||
* Copyright 2025-present ZhouXY
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2025 the original author or authors.
|
||||
* Copyright 2025-present ZhouXY
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2025 the original author or authors.
|
||||
* Copyright 2025-present ZhouXY
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2025 the original author or authors.
|
||||
* Copyright 2025-present ZhouXY
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2025 the original author or authors.
|
||||
* Copyright 2025-present ZhouXY
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2025 the original author or authors.
|
||||
* Copyright 2025-present ZhouXY
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2025 the original author or authors.
|
||||
* Copyright 2025-present ZhouXY
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2025 the original author or authors.
|
||||
* Copyright 2025-present ZhouXY
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2025 the original author or authors.
|
||||
* Copyright 2025-present ZhouXY
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2025 the original author or authors.
|
||||
* Copyright 2025-present ZhouXY
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -293,8 +293,18 @@ public class ArrayPropertyValidatorTests {
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithStringArrayProperty(new String[] { "1234", "12345", "123456" });
|
||||
assertDoesNotThrow(() -> validator.validate(command));
|
||||
{
|
||||
ExampleCommand command = exampleCommandWithStringArrayProperty(new String[] { "1234", "12345", "123456" });
|
||||
assertDoesNotThrow(() -> validator.validate(command));
|
||||
}
|
||||
{
|
||||
ExampleCommand command = exampleCommandWithStringArrayProperty(new String[0]);
|
||||
assertDoesNotThrow(() -> validator.validate(command));
|
||||
}
|
||||
{
|
||||
ExampleCommand command = exampleCommandWithStringArrayProperty(null);
|
||||
assertDoesNotThrow(() -> validator.validate(command));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023-2025 the original author or authors.
|
||||
* Copyright 2023-present ZhouXY
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2025 the original author or authors.
|
||||
* Copyright 2025-present ZhouXY
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2025 the original author or authors.
|
||||
* Copyright 2025-present ZhouXY
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -298,8 +298,14 @@ public class CollectionPropertyValidatorTests {
|
||||
}
|
||||
};
|
||||
|
||||
ExampleCommand command = exampleCommandWithStringListProperty(Lists.newArrayList("1234", "12345", "123456"));
|
||||
assertDoesNotThrow(() -> validator.validate(command));
|
||||
{
|
||||
ExampleCommand command = exampleCommandWithStringListProperty(Lists.newArrayList("1234", "12345", "123456"));
|
||||
assertDoesNotThrow(() -> validator.validate(command));
|
||||
}
|
||||
{
|
||||
ExampleCommand command = exampleCommandWithStringListProperty(null);
|
||||
assertDoesNotThrow(() -> validator.validate(command));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2025 the original author or authors.
|
||||
* Copyright 2025-present ZhouXY
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2025 the original author or authors.
|
||||
* Copyright 2025-present ZhouXY
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -87,7 +87,7 @@ public class DoublePropertyValidatorTests {
|
||||
|
||||
ValidationException e = assertThrows(
|
||||
ValidationException.class, () -> validator.validate(command));
|
||||
assertEquals(String.format("The input must be greater than '%s'.", MIN), e.getMessage());
|
||||
assertEquals(String.format("The input must be greater than '%f'.", MIN), e.getMessage());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@@ -196,7 +196,7 @@ public class DoublePropertyValidatorTests {
|
||||
|
||||
ValidationException e = assertThrows(
|
||||
ValidationException.class, () -> validator.validate(command));
|
||||
assertEquals(String.format("The input must be greater than or equal to '%s'.", MIN), e.getMessage());
|
||||
assertEquals(String.format("The input must be greater than or equal to '%f'.", MIN), e.getMessage());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@@ -305,7 +305,7 @@ public class DoublePropertyValidatorTests {
|
||||
|
||||
ValidationException e = assertThrows(
|
||||
ValidationException.class, () -> validator.validate(command));
|
||||
assertEquals(String.format("The input must be less than '%s'.", MAX), e.getMessage());
|
||||
assertEquals(String.format("The input must be less than '%f'.", MAX), e.getMessage());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@@ -414,7 +414,7 @@ public class DoublePropertyValidatorTests {
|
||||
|
||||
ValidationException e = assertThrows(
|
||||
ValidationException.class, () -> validator.validate(command));
|
||||
assertEquals(String.format("The input must be less than or equal to '%s'.", MAX), e.getMessage());
|
||||
assertEquals(String.format("The input must be less than or equal to '%f'.", MAX), e.getMessage());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2025 the original author or authors.
|
||||
* Copyright 2025-present ZhouXY
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2025 the original author or authors.
|
||||
* Copyright 2025-present ZhouXY
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2025 the original author or authors.
|
||||
* Copyright 2025-present ZhouXY
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2025 the original author or authors.
|
||||
* Copyright 2025-present ZhouXY
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -31,6 +31,7 @@ import xyz.zhouxy.plusone.validator.BaseValidator;
|
||||
import xyz.zhouxy.plusone.validator.IValidator;
|
||||
import xyz.zhouxy.plusone.validator.ValidationException;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public class PairPropertyValidatorTests {
|
||||
|
||||
static final String MESSAGE = "Validation failed.";
|
||||
@@ -41,7 +42,9 @@ public class PairPropertyValidatorTests {
|
||||
|
||||
@Test
|
||||
void must_validInput() {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
ExampleCommand command = exampleCommandWithIntAndStringListProperty(100, "100");
|
||||
|
||||
IValidator<ExampleCommand> validator1 = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForPair((ExampleCommand command) -> new SimpleImmutableEntry<String,Integer>(command.getStringProperty(), command.getIntProperty()))
|
||||
.must((str, intValue) -> Objects.equals(str, intValue.toString()))
|
||||
@@ -51,69 +54,113 @@ public class PairPropertyValidatorTests {
|
||||
(str, intValue) -> ExampleException.withMessage("Validation failed: ('%s', %d).", str, intValue));
|
||||
}
|
||||
};
|
||||
assertDoesNotThrow(() -> validator1.validate(command));
|
||||
|
||||
ExampleCommand command = exampleCommandWithIntAndStringListProperty(100, "100");
|
||||
assertDoesNotThrow(() -> validator.validate(command));
|
||||
IValidator<ExampleCommand> validator2 = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleFor(ExampleCommand::getStringProperty, ExampleCommand::getIntProperty)
|
||||
.must((str, intValue) -> Objects.equals(str, intValue.toString()))
|
||||
.must((str, intValue) -> Objects.equals(str, intValue.toString()), MESSAGE)
|
||||
.must((str, intValue) -> Objects.equals(str, intValue.toString()), () -> ExampleException.withMessage(MESSAGE))
|
||||
.must((str, intValue) -> Objects.equals(str, intValue.toString()),
|
||||
(str, intValue) -> ExampleException.withMessage("Validation failed: ('%s', %d).", str, intValue));
|
||||
}
|
||||
};
|
||||
assertDoesNotThrow(() -> validator2.validate(command));
|
||||
}
|
||||
|
||||
@Test
|
||||
void must_default_invalidInput() {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
ExampleCommand command = exampleCommandWithIntAndStringListProperty(100, "");
|
||||
|
||||
IValidator<ExampleCommand> validator1 = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForPair((ExampleCommand command) -> new SimpleImmutableEntry<String,Integer>(command.getStringProperty(), command.getIntProperty()))
|
||||
.must((str, intValue) -> Objects.equals(str, intValue.toString()));
|
||||
}
|
||||
};
|
||||
ValidationException e1 = assertThrows(ValidationException.class, () -> validator1.validate(command));
|
||||
assertEquals("The specified condition was not met for the input.", e1.getMessage());
|
||||
|
||||
ExampleCommand command = exampleCommandWithIntAndStringListProperty(100, "");
|
||||
|
||||
ValidationException e = assertThrows(ValidationException.class, () -> validator.validate(command));
|
||||
assertEquals("The specified condition was not met for the input.", e.getMessage());
|
||||
IValidator<ExampleCommand> validator2 = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleFor(ExampleCommand::getStringProperty, ExampleCommand::getIntProperty)
|
||||
.must((str, intValue) -> Objects.equals(str, intValue.toString()));
|
||||
}
|
||||
};
|
||||
ValidationException e2 = assertThrows(ValidationException.class, () -> validator2.validate(command));
|
||||
assertEquals("The specified condition was not met for the input.", e2.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void must_message_invalidInput() {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
ExampleCommand command = exampleCommandWithIntAndStringListProperty(100, "");
|
||||
|
||||
IValidator<ExampleCommand> validator1 = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForPair((ExampleCommand command) -> new SimpleImmutableEntry<String,Integer>(command.getStringProperty(), command.getIntProperty()))
|
||||
.must((str, intValue) -> Objects.equals(str, intValue.toString()), MESSAGE);
|
||||
}
|
||||
};
|
||||
ValidationException e1 = assertThrows(ValidationException.class, () -> validator1.validate(command));
|
||||
assertEquals(MESSAGE, e1.getMessage());
|
||||
|
||||
ExampleCommand command = exampleCommandWithIntAndStringListProperty(100, "");
|
||||
ValidationException e = assertThrows(ValidationException.class, () -> validator.validate(command));
|
||||
assertEquals(MESSAGE, e.getMessage());
|
||||
IValidator<ExampleCommand> validator2 = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleFor(ExampleCommand::getStringProperty, ExampleCommand::getIntProperty)
|
||||
.must((str, intValue) -> Objects.equals(str, intValue.toString()), MESSAGE);
|
||||
}
|
||||
};
|
||||
ValidationException e2 = assertThrows(ValidationException.class, () -> validator2.validate(command));
|
||||
assertEquals(MESSAGE, e2.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void must_exceptionSupplier_invalidInput() {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
ExampleCommand command = exampleCommandWithIntAndStringListProperty(100, "");
|
||||
|
||||
IValidator<ExampleCommand> validator1 = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForPair((ExampleCommand command) -> new SimpleImmutableEntry<String,Integer>(command.getStringProperty(), command.getIntProperty()))
|
||||
.must((str, intValue) -> Objects.equals(str, intValue.toString()), () -> ExampleException.withMessage(MESSAGE));
|
||||
}
|
||||
};
|
||||
ExampleException e1 = assertThrows(ExampleException.class, () -> validator1.validate(command));
|
||||
assertEquals(MESSAGE, e1.getMessage());
|
||||
|
||||
ExampleCommand command = exampleCommandWithIntAndStringListProperty(100, "");
|
||||
|
||||
ExampleException e = assertThrows(ExampleException.class, () -> validator.validate(command));
|
||||
assertEquals(MESSAGE, e.getMessage());
|
||||
IValidator<ExampleCommand> validator2 = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleFor(ExampleCommand::getStringProperty, ExampleCommand::getIntProperty)
|
||||
.must((str, intValue) -> Objects.equals(str, intValue.toString()), () -> ExampleException.withMessage(MESSAGE));
|
||||
}
|
||||
};
|
||||
ExampleException e2 = assertThrows(ExampleException.class, () -> validator2.validate(command));
|
||||
assertEquals(MESSAGE, e2.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void must_exceptionFunction_invalidInput() {
|
||||
IValidator<ExampleCommand> validator = new BaseValidator<ExampleCommand>() {
|
||||
ExampleCommand command = exampleCommandWithIntAndStringListProperty(100, "");
|
||||
|
||||
IValidator<ExampleCommand> validator1 = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleForPair((ExampleCommand command) -> new SimpleImmutableEntry<String,Integer>(command.getStringProperty(), command.getIntProperty()))
|
||||
.must((str, intValue) -> Objects.equals(str, intValue.toString()),
|
||||
(str, intValue) -> ExampleException.withMessage("Validation failed: ('%s', %d).", str, intValue));
|
||||
}
|
||||
};
|
||||
ExampleException e1 = assertThrows(ExampleException.class, () -> validator1.validate(command));
|
||||
assertEquals("Validation failed: ('', 100).", e1.getMessage());
|
||||
|
||||
ExampleCommand command = exampleCommandWithIntAndStringListProperty(100, "");
|
||||
|
||||
ExampleException e = assertThrows(ExampleException.class, () -> validator.validate(command));
|
||||
assertEquals("Validation failed: ('', 100).", e.getMessage());
|
||||
IValidator<ExampleCommand> validator2 = new BaseValidator<ExampleCommand>() {
|
||||
{
|
||||
ruleFor(ExampleCommand::getStringProperty, ExampleCommand::getIntProperty)
|
||||
.must((str, intValue) -> Objects.equals(str, intValue.toString()),
|
||||
(str, intValue) -> ExampleException.withMessage("Validation failed: ('%s', %d).", str, intValue));
|
||||
}
|
||||
};
|
||||
ExampleException e2 = assertThrows(ExampleException.class, () -> validator2.validate(command));
|
||||
assertEquals("Validation failed: ('', 100).", e2.getMessage());
|
||||
}
|
||||
|
||||
// ================================
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2025 the original author or authors.
|
||||
* Copyright 2025-present ZhouXY
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2024-2025 the original author or authors.
|
||||
* Copyright 2024-present ZhouXY
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -122,14 +122,14 @@ class ParamsValidator extends MapValidator<String, Object> {
|
||||
.notNull(d -> ExampleException.withMessage("The doubleProperty cannot be null, but it was %s", d));
|
||||
ruleForString(STRING_PROPERTY)
|
||||
.notNull();
|
||||
ruleForComparable(DATE_TIME_PROPERTY)
|
||||
this.<LocalDateTime>ruleForComparable(DATE_TIME_PROPERTY)
|
||||
.notNull("The dateTimeProperty cannot be null");
|
||||
ruleFor(OBJECT_PROPERTY)
|
||||
.notNull(() -> ExampleException.withMessage("The objectProperty cannot be null"));
|
||||
ruleForCollection(STRING_LIST_PROPERTY)
|
||||
this.<String>ruleForCollection(STRING_LIST_PROPERTY)
|
||||
.notNull(d -> ExampleException.withMessage("The stringListProperty cannot be null, but it was %s", d));
|
||||
|
||||
ruleForPair(STRING_PROPERTY, STRING_PROPERTY2)
|
||||
this.<String, String>ruleForPair(STRING_PROPERTY, STRING_PROPERTY2)
|
||||
.must((str1, str2) -> str1 != null && str1.equals(str2),
|
||||
"'stringProperty' must be equal to 'stringProperty2'.");
|
||||
}
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2025-present ZhouXY
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package xyz.zhouxy.plusone.validator;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
143
pom.xml
143
pom.xml
@@ -6,10 +6,10 @@
|
||||
|
||||
<groupId>xyz.zhouxy.plusone</groupId>
|
||||
<artifactId>plusone-validator-parent</artifactId>
|
||||
<version>1.0.0-RC1</version>
|
||||
<version>1.0.0-RC4</version>
|
||||
|
||||
<name>plusone-validator-parent</name>
|
||||
<url>http://zhouxy.xyz</url>
|
||||
<url>https://gitea.zhouxy.xyz/plusone/plusone-validator</url>
|
||||
|
||||
<packaging>pom</packaging>
|
||||
|
||||
@@ -21,8 +21,33 @@
|
||||
Plusone Validator 是一个校验库,使用 lambda 表达式(包括方法引用)和流式 API 构建校验规则,对对象进行校验。
|
||||
</description>
|
||||
|
||||
<licenses>
|
||||
<license>
|
||||
<name>Apache License, Version 2.0</name>
|
||||
<url>https://www.apache.org/licenses/LICENSE-2.0</url>
|
||||
<distribution>repo</distribution>
|
||||
</license>
|
||||
</licenses>
|
||||
|
||||
<developers>
|
||||
<developer>
|
||||
<name>Zhou Xingyi (周兴毅)</name>
|
||||
<url>https://gitea.zhouxy.xyz/plusone</url>
|
||||
</developer>
|
||||
</developers>
|
||||
|
||||
<scm>
|
||||
<connection>scm:git:https://gitea.zhouxy.xyz/plusone/plusone-validator.git</connection>
|
||||
<developerConnection>scm:git:ssh://gitea.zhouxy.xyz/plusone/plusone-validator.git</developerConnection>
|
||||
<url>https://gitea.zhouxy.xyz/plusone/plusone-validator</url>
|
||||
</scm>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
|
||||
<plusone-commons.version>1.1.0-RC2</plusone-commons.version>
|
||||
</properties>
|
||||
|
||||
<dependencyManagement>
|
||||
@@ -30,57 +55,81 @@
|
||||
<dependency>
|
||||
<groupId>xyz.zhouxy.plusone</groupId>
|
||||
<artifactId>plusone-dependencies</artifactId>
|
||||
<version>1.1.0-RC1</version>
|
||||
<version>${plusone-commons.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>xyz.zhouxy.plusone</groupId>
|
||||
<artifactId>plusone-commons</artifactId>
|
||||
<version>${plusone-commons.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<build>
|
||||
<!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
|
||||
<plugin>
|
||||
<artifactId>maven-clean-plugin</artifactId>
|
||||
<version>3.1.0</version>
|
||||
</plugin>
|
||||
<!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
|
||||
<plugin>
|
||||
<artifactId>maven-resources-plugin</artifactId>
|
||||
<version>3.0.2</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.0</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>2.22.1</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>3.0.2</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-install-plugin</artifactId>
|
||||
<version>2.5.2</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-deploy-plugin</artifactId>
|
||||
<version>2.8.2</version>
|
||||
</plugin>
|
||||
<!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
|
||||
<plugin>
|
||||
<artifactId>maven-site-plugin</artifactId>
|
||||
<version>3.7.1</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-project-info-reports-plugin</artifactId>
|
||||
<version>3.0.0</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
<plugins>
|
||||
<!-- Flatten 插件:生成包含继承信息的完整 POM 用于发布 -->
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>flatten-maven-plugin</artifactId>
|
||||
<version>1.6.0</version>
|
||||
<configuration>
|
||||
<!-- 核心配置:oss 模式专为 Sonatype/Maven Central 设计 -->
|
||||
<!-- 它会保留 url, licenses, developers, scm, properties 等必要元素 -->
|
||||
<flattenMode>oss</flattenMode>
|
||||
</configuration>
|
||||
<executions>
|
||||
<!-- 在 process-resources 阶段生成展平的 POM -->
|
||||
<execution>
|
||||
<id>flatten</id>
|
||||
<phase>process-resources</phase>
|
||||
<goals>
|
||||
<goal>flatten</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
<!-- 在 clean 阶段删除展平的 POM -->
|
||||
<execution>
|
||||
<id>flatten.clean</id>
|
||||
<phase>clean</phase>
|
||||
<goals>
|
||||
<goal>clean</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>release</id>
|
||||
<build>
|
||||
<plugins>
|
||||
<!-- GPG -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-gpg-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>sign-artifacts</id>
|
||||
<phase>verify</phase>
|
||||
<goals>
|
||||
<goal>sign</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.sonatype.central</groupId>
|
||||
<artifactId>central-publishing-maven-plugin</artifactId>
|
||||
<extensions>true</extensions>
|
||||
<configuration>
|
||||
<publishingServerId>central</publishingServerId>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
</project>
|
||||
|
||||
Reference in New Issue
Block a user