feat: 新增 package-info.java 并初步集成 JSpecify

- 添加 JSpecify 依赖到 pom.xml
- 创建 validator/package-info.java
- 创建 function/package-info.java
- 添加 @Nullable 注解到核心接口和类
This commit is contained in:
2026-05-27 18:29:17 +08:00
parent ba9ccebb56
commit 08e228c5f7
9 changed files with 119 additions and 15 deletions

View File

@@ -44,6 +44,11 @@
<groupId>xyz.zhouxy.plusone</groupId> <groupId>xyz.zhouxy.plusone</groupId>
<artifactId>plusone-commons</artifactId> <artifactId>plusone-commons</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.jspecify</groupId>
<artifactId>jspecify</artifactId>
<version>1.0.0</version>
</dependency>
<dependency> <dependency>
<groupId>org.junit.jupiter</groupId> <groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId> <artifactId>junit-jupiter</artifactId>

View File

@@ -24,6 +24,8 @@ import java.util.function.Function;
import java.util.function.Predicate; import java.util.function.Predicate;
import java.util.function.Supplier; import java.util.function.Supplier;
import org.jspecify.annotations.Nullable;
/** /**
* 属性校验器。包含针对属性的校验规则。 * 属性校验器。包含针对属性的校验规则。
* *
@@ -135,9 +137,9 @@ public abstract class BasePropertyValidator<
/** /**
* 校验属性 * 校验属性
* *
* @param obj 属性所在的对象 * @param obj 属性所在的对象,允许为 {@code null}
*/ */
public final void validate(T obj) { public final void validate(@Nullable T obj) {
for (Consumer<? super TProperty> consumer : consumers) { for (Consumer<? super TProperty> consumer : consumers) {
consumer.accept(getter.apply(obj)); consumer.accept(getter.apply(obj));
} }

View File

@@ -28,6 +28,8 @@ import java.util.function.Supplier;
import xyz.zhouxy.plusone.validator.function.*; import xyz.zhouxy.plusone.validator.function.*;
import org.jspecify.annotations.Nullable;
/** /**
* 校验器基类 * 校验器基类
* <p> * <p>
@@ -311,7 +313,7 @@ public abstract class BaseValidator<T> implements IValidator<T> {
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
public void validate(T obj) { public void validate(@Nullable T obj) {
this.rules.forEach(rule -> rule.accept(obj)); this.rules.forEach(rule -> rule.accept(obj));
} }
} }

View File

@@ -15,6 +15,8 @@
*/ */
package xyz.zhouxy.plusone.validator; package xyz.zhouxy.plusone.validator;
import org.jspecify.annotations.Nullable;
/** /**
* 校验器 * 校验器
* *
@@ -30,7 +32,7 @@ public interface IValidator<T> {
/** /**
* 校验指定对象是否符合预定义规则 * 校验指定对象是否符合预定义规则
* *
* @param obj 待校验的对象实例 * @param obj 待校验的对象实例,允许为 {@code null}
*/ */
void validate(T obj); void validate(@Nullable T obj);
} }

View File

@@ -23,6 +23,8 @@ import java.util.Set;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.jspecify.annotations.Nullable;
/** /**
* 对 Map 进行校验的校验器 * 对 Map 进行校验的校验器
* *
@@ -59,10 +61,10 @@ public abstract class MapValidator<K, V> extends BaseValidator<Map<K, V>> {
/** /**
* 校验并拷贝,仅保留指定 key 的属性。 * 校验并拷贝,仅保留指定 key 的属性。
* *
* @param obj 待校验的 map * @param obj 待校验的 map,允许为 {@code null}
* @return 拷贝后的 map * @return 拷贝后的 map
*/ */
public final Map<K, V> validateAndCopy(Map<K, V> obj) { public final Map<K, V> validateAndCopy(@Nullable Map<K, V> obj) {
return validateAndCopyInternal(obj, this.keys); return validateAndCopyInternal(obj, this.keys);
} }
@@ -89,7 +91,7 @@ public abstract class MapValidator<K, V> extends BaseValidator<Map<K, V>> {
return validateAndCopyInternal(obj, Arrays.asList(keys)); return validateAndCopyInternal(obj, Arrays.asList(keys));
} }
private final Map<K, V> validateAndCopyInternal(Map<K, V> obj, Collection<K> keys) { private final Map<K, V> validateAndCopyInternal(@Nullable Map<K, V> obj, Collection<K> keys) {
validate(obj); validate(obj);
return obj.entrySet().stream() return obj.entrySet().stream()
.filter(kv -> keys.contains(kv.getKey())) .filter(kv -> keys.contains(kv.getKey()))

View File

@@ -547,7 +547,7 @@ public class StringPropertyValidator<T>
private static Predicate<String> length(int length) { private static Predicate<String> length(int length) {
AssertTools.checkArgument(length >= 0, AssertTools.checkArgument(length >= 0,
"The expected length must be non-negative."); "The expected length must be non-negative.");
return input -> input == null || input.length() == length; return input -> input == null || input.length() == length;
} }

View File

@@ -15,6 +15,8 @@
*/ */
package xyz.zhouxy.plusone.validator; package xyz.zhouxy.plusone.validator;
import org.jspecify.annotations.Nullable;
/** /**
* 校验失败异常 * 校验失败异常
* *
@@ -30,11 +32,11 @@ public class ValidationException extends RuntimeException {
super(message); super(message);
} }
private ValidationException(Throwable cause) { private ValidationException(@Nullable Throwable cause) {
super(cause); super(cause);
} }
private ValidationException(String message, Throwable cause) { private ValidationException(String message, @Nullable Throwable cause) {
super(message, cause); super(message, cause);
} }
@@ -71,10 +73,10 @@ public class ValidationException extends RuntimeException {
/** /**
* 创建 {@code ValidationException} 实例 * 创建 {@code ValidationException} 实例
* *
* @param cause 导致校验失败的根本异常 * @param cause 导致校验失败的根本异常,允许为 {@code null}
* @return {@code ValidationException} 实例 * @return {@code ValidationException} 实例
*/ */
public static ValidationException withCause(Throwable cause) { public static ValidationException withCause(@Nullable Throwable cause) {
return new ValidationException(cause); return new ValidationException(cause);
} }
@@ -82,10 +84,10 @@ public class ValidationException extends RuntimeException {
* 创建 {@code ValidationException} 实例 * 创建 {@code ValidationException} 实例
* *
* @param message 异常信息 * @param message 异常信息
* @param cause 导致校验失败的根本异常 * @param cause 导致校验失败的根本异常,允许为 {@code null}
* @return {@code ValidationException} 实例 * @return {@code ValidationException} 实例
*/ */
public static ValidationException withMessageAndCause(String message, Throwable cause) { public static ValidationException withMessageAndCause(String message, @Nullable Throwable cause) {
return new ValidationException(message, cause); return new ValidationException(message, cause);
} }
} }

View File

@@ -0,0 +1,37 @@
/*
* 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.
*/
/**
* 函数式接口包,提供带序列化能力的特殊 {@code Function} 子类型。
*
* <p>
* 本包中的接口均继承自 {@link java.util.function.Function},同时实现
* {@link java.io.Serializable},使 lambda 表达式或方法引用可以被序列化。
* 主要用作 {@link xyz.zhouxy.plusone.validator.BaseValidator} 中
* {@code ruleFor} 方法族的参数类型,以支持特定类型的属性取值。
*
* <ul>
* <li>{@link xyz.zhouxy.plusone.validator.function.ToStringFunction ToStringFunction} — Function&lt;T, String&gt;</li>
* <li>{@link xyz.zhouxy.plusone.validator.function.ToIntegerFunction ToIntegerFunction} — Function&lt;T, Integer&gt;</li>
* <li>{@link xyz.zhouxy.plusone.validator.function.ToLongObjectFunction ToLongObjectFunction} — Function&lt;T, Long&gt;</li>
* <li>{@link xyz.zhouxy.plusone.validator.function.ToDoubleObjectFunction ToDoubleObjectFunction} — Function&lt;T, Double&gt;</li>
* <li>{@link xyz.zhouxy.plusone.validator.function.ToBoolObjectFunction ToBoolObjectFunction} — Function&lt;T, Boolean&gt;</li>
* </ul>
*/
@NullMarked
package xyz.zhouxy.plusone.validator.function;
import org.jspecify.annotations.NullMarked;

View File

@@ -0,0 +1,52 @@
/*
* 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.
*/
/**
* Plusone Validator 核心包,提供流式校验 API。
*
* <p>
* 使用 lambda 表达式(包括方法引用)和流式 API 构建校验规则,对对象进行校验。
* 支持校验普通对象POJO和 {@code Map} 对象。
*
* <h3>快速开始</h3>
* <pre>{@code
* public class PersonValidator extends BaseValidator<Person> {
* public PersonValidator() {
* ruleFor(Person::getName)
* .notNull()
* .notBlank();
* ruleForInt(Person::getAge)
* .gt(0);
* }
* }
* }</pre>
*
* <h3>核心概念</h3>
* <ul>
* <li>{@link xyz.zhouxy.plusone.validator.IValidator IValidator} — 校验器接口</li>
* <li>{@link xyz.zhouxy.plusone.validator.BaseValidator BaseValidator} — 校验器基类,通过继承并添加规则构建校验器</li>
* <li>{@link xyz.zhouxy.plusone.validator.BasePropertyValidator BasePropertyValidator} — 属性校验器基类</li>
* <li>{@link xyz.zhouxy.plusone.validator.MapValidator MapValidator} — Map 校验器</li>
* <li>{@link xyz.zhouxy.plusone.validator.ValidationException ValidationException} — 校验失败异常</li>
* </ul>
*
* @see xyz.zhouxy.plusone.validator.BaseValidator
* @see xyz.zhouxy.plusone.validator.MapValidator
*/
@NullMarked
package xyz.zhouxy.plusone.validator;
import org.jspecify.annotations.NullMarked;