1. 重构代码;2. 支持对 POJO 的校验
parent
e4f18d5d89
commit
a703fcadc1
|
@ -0,0 +1,51 @@
|
||||||
|
package xyz.zhouxy.plusone.validator;
|
||||||
|
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
public abstract class BasePropertyValidator<TObj, TProperty, TValidator extends BasePropertyValidator<TObj, TProperty, TValidator>> {
|
||||||
|
|
||||||
|
private final Function<TObj, ? extends TProperty> getter;
|
||||||
|
|
||||||
|
protected BasePropertyValidator(Function<TObj, ? extends TProperty> getter) {
|
||||||
|
this.getter = getter;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final List<Consumer<TProperty>> consumers = new LinkedList<>();
|
||||||
|
|
||||||
|
public final TValidator withRules(Predicate<? super TProperty> rule) {
|
||||||
|
return withRules(rule, v -> new IllegalArgumentException());
|
||||||
|
}
|
||||||
|
|
||||||
|
public final TValidator withRules(
|
||||||
|
Predicate<? super TProperty> rule, String errorMsg) {
|
||||||
|
return withRules(rule, v -> new IllegalArgumentException(errorMsg));
|
||||||
|
}
|
||||||
|
|
||||||
|
public final <E extends RuntimeException> TValidator withRules(
|
||||||
|
Predicate<? super TProperty> rule, Supplier<E> e) {
|
||||||
|
return withRules(rule, v -> e.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
public final <E extends RuntimeException> TValidator withRules(
|
||||||
|
Predicate<? super TProperty> rule, Function<TProperty, E> e) {
|
||||||
|
this.consumers.add(v -> {
|
||||||
|
if (!rule.test(v)) {
|
||||||
|
throw e.apply(v);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return thisObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
public final <T extends TObj> void validate(T dto) {
|
||||||
|
for (Consumer<TProperty> consumer : consumers) {
|
||||||
|
consumer.accept(getter.apply(dto));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract TValidator thisObject();
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
package xyz.zhouxy.plusone.validator;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class EntryValidator<K, V>
|
||||||
|
extends BasePropertyValidator<Map<K, ? super V>, V, EntryValidator<K, V>> {
|
||||||
|
|
||||||
|
public EntryValidator(K key) {
|
||||||
|
super(m -> {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
V v = (V) m.get(key);
|
||||||
|
return v;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected EntryValidator<K, V> thisObject() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
|
@ -51,12 +51,12 @@ public abstract class MapValidator<K, V> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
protected final <VV extends V> PropertyValidator<K, VV> checkProperty(K key, Class<VV> clazz) {
|
protected final <VV extends V> EntryValidator<K, VV> checkProperty(K key, Class<VV> clazz) {
|
||||||
return checkProperty(key);
|
return checkProperty(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected final <VV extends V> PropertyValidator<K, VV> checkProperty(K key) {
|
protected final <VV extends V> EntryValidator<K, VV> checkProperty(K key) {
|
||||||
PropertyValidator<K, VV> validator = new PropertyValidator<>(key);
|
EntryValidator<K, VV> validator = new EntryValidator<>(key);
|
||||||
this.consumers.add(validator::validate);
|
this.consumers.add(validator::validate);
|
||||||
return validator;
|
return validator;
|
||||||
}
|
}
|
||||||
|
@ -81,45 +81,3 @@ public abstract class MapValidator<K, V> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class PropertyValidator<K, V> {
|
|
||||||
|
|
||||||
private final K key;
|
|
||||||
|
|
||||||
public PropertyValidator(K key) {
|
|
||||||
this.key = key;
|
|
||||||
}
|
|
||||||
|
|
||||||
private final List<Consumer<V>> consumers = new LinkedList<>();
|
|
||||||
|
|
||||||
public final PropertyValidator<K, V> withRules(Predicate<? super V> rule) {
|
|
||||||
return withRules(rule, v -> new IllegalArgumentException(key.toString()));
|
|
||||||
}
|
|
||||||
|
|
||||||
public final PropertyValidator<K, V> withRules(Predicate<? super V> rule, String errorMsg) {
|
|
||||||
return withRules(rule, v -> new IllegalArgumentException(errorMsg));
|
|
||||||
}
|
|
||||||
|
|
||||||
public final <E extends RuntimeException> PropertyValidator<K, V> withRules(Predicate<? super V> rule,
|
|
||||||
Supplier<E> e) {
|
|
||||||
return withRules(rule, v -> e.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
public final <E extends RuntimeException> PropertyValidator<K, V> withRules(Predicate<? super V> rule,
|
|
||||||
Function<V, E> e) {
|
|
||||||
this.consumers.add(v -> {
|
|
||||||
if (!rule.test(v)) {
|
|
||||||
throw e.apply(v);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public final void validate(Map<K, ? super V> map) {
|
|
||||||
for (Consumer<V> consumer : consumers) {
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
V v = (V) map.get(this.key);
|
|
||||||
consumer.accept(v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,90 +0,0 @@
|
||||||
package xyz.zhouxy.plusone.validator;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.function.Predicate;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
public class PredicateTools {
|
|
||||||
|
|
||||||
private PredicateTools() {
|
|
||||||
throw new IllegalStateException("Utility class");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> Predicate<T> asPredicate(Predicate<T> predicate) {
|
|
||||||
return predicate;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> boolean notNull(T obj) {
|
|
||||||
return obj != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> Predicate<T> notNull() {
|
|
||||||
return PredicateTools::notNull;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int length(CharSequence cs) {
|
|
||||||
return cs == null ? 0 : cs.length();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isNotBlank(CharSequence cs) {
|
|
||||||
return !isBlank(cs);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Predicate<CharSequence> isNotBlank() {
|
|
||||||
return PredicateTools::isNotBlank;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isBlank(CharSequence cs) {
|
|
||||||
final int strLen = length(cs);
|
|
||||||
if (strLen == 0) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
for (int i = 0; i < strLen; i++) {
|
|
||||||
if (!Character.isWhitespace(cs.charAt(i))) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Predicate<CharSequence> isBlank() {
|
|
||||||
return PredicateTools::isBlank;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Predicate<CharSequence> matches(Pattern pattern) {
|
|
||||||
return str -> pattern.matcher(str).matches();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Predicate<CharSequence> matchesAll(Pattern... patterns) {
|
|
||||||
return str -> {
|
|
||||||
for (Pattern pattern : patterns) {
|
|
||||||
if (!pattern.matcher(str).matches()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Predicate<CharSequence> matchesOne(Pattern... patterns) {
|
|
||||||
return str -> {
|
|
||||||
for (Pattern pattern : patterns) {
|
|
||||||
if (pattern.matcher(str).matches()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> Predicate<Collection<T>> forAllItems(Predicate<T> predicate) {
|
|
||||||
return c -> {
|
|
||||||
for (T t : c) {
|
|
||||||
if (!predicate.test(t)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
package xyz.zhouxy.plusone.validator;
|
||||||
|
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
public class PropertyValidator<TObj, TProperty>
|
||||||
|
extends BasePropertyValidator<TObj, TProperty, PropertyValidator<TObj, TProperty>> {
|
||||||
|
|
||||||
|
protected PropertyValidator(Function<TObj, ? extends TProperty> getter) {
|
||||||
|
super(getter);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected PropertyValidator<TObj, TProperty> thisObject() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package xyz.zhouxy.plusone.validator;
|
package xyz.zhouxy.plusone.validator.map;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
@ -7,11 +7,16 @@ import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import xyz.zhouxy.plusone.commons.collection.CollectionTools;
|
||||||
import xyz.zhouxy.plusone.commons.constant.PatternConsts;
|
import xyz.zhouxy.plusone.commons.constant.PatternConsts;
|
||||||
|
import xyz.zhouxy.plusone.commons.function.PredicateTools;
|
||||||
|
import xyz.zhouxy.plusone.commons.util.RegexUtil;
|
||||||
|
import xyz.zhouxy.plusone.validator.MapValidator;
|
||||||
|
|
||||||
class MapValidatorTests {
|
class MapValidatorTests {
|
||||||
|
|
||||||
|
@ -26,34 +31,38 @@ class MapValidatorTests {
|
||||||
private static final MapValidator<String, Object> validator = new MapValidator<String, Object>(
|
private static final MapValidator<String, Object> validator = new MapValidator<String, Object>(
|
||||||
new String[] { USERNAME, ACCOUNT, PASSWORD, AGE, BOOLEAN, ROLE_LIST }) {
|
new String[] { USERNAME, ACCOUNT, PASSWORD, AGE, BOOLEAN, ROLE_LIST }) {
|
||||||
{
|
{
|
||||||
checkProperty(USERNAME, String.class)
|
checkProperty(USERNAME, String.class).withRules(
|
||||||
.withRules(StringUtils::isNotEmpty)
|
PredicateTools.from(StringUtils::isNotBlank)
|
||||||
.withRules(PredicateTools.matches(PatternConsts.USERNAME),
|
.and(username -> RegexUtil.matches(username, PatternConsts.USERNAME)),
|
||||||
username -> new IllegalArgumentException(String.format("用户名【%s】不符合规范", username)));
|
username -> new IllegalArgumentException(String.format("用户名【%s】不符合规范", username)));
|
||||||
|
|
||||||
checkProperty(ACCOUNT, String.class)
|
checkProperty(ACCOUNT, String.class).withRules(
|
||||||
.withRules(StringUtils::isNotEmpty)
|
PredicateTools.from(StringUtils::isNotBlank)
|
||||||
.withRules(PredicateTools.matchesOne(PatternConsts.EMAIL, PatternConsts.MOBILE_PHONE),
|
.and(account -> RegexUtil.matchesOne(account,
|
||||||
"请输入正确的邮箱地址或手机号");
|
new Pattern[] { PatternConsts.EMAIL, PatternConsts.MOBILE_PHONE })),
|
||||||
|
"请输入正确的邮箱地址或手机号");
|
||||||
|
|
||||||
checkProperty(PASSWORD, String.class)
|
checkProperty(PASSWORD, String.class)
|
||||||
.withRules(StringUtils::isNotEmpty)
|
.withRules(StringUtils::isNotEmpty, "密码不能为空")
|
||||||
.withRules(PredicateTools.matches(PatternConsts.PASSWORD), "密码不符合规范");
|
.withRules(pwd -> RegexUtil.matches(pwd, PatternConsts.PASSWORD), "密码不符合规范");
|
||||||
|
|
||||||
|
// 校验到多个属性,只能针对 map 本身进行校验
|
||||||
withRule(m -> Objects.equals(m.get(PASSWORD), m.get(PASSWORD2)),
|
withRule(m -> Objects.equals(m.get(PASSWORD), m.get(PASSWORD2)),
|
||||||
"两次输入的密码不一样!");
|
"两次输入的密码不一样!");
|
||||||
|
|
||||||
checkProperty(AGE, Integer.class)
|
// 通过泛型方式调用方法,指定数据类型
|
||||||
|
this.<Integer>checkProperty(AGE)
|
||||||
.withRules(Objects::nonNull)
|
.withRules(Objects::nonNull)
|
||||||
.withRules(age -> (18 <= age && 60 >= age));
|
.withRules(age -> (18 <= age && 60 >= age));
|
||||||
|
|
||||||
checkProperty(BOOLEAN, Boolean.class)
|
checkProperty(BOOLEAN, Boolean.class)
|
||||||
.withRules(PredicateTools.notNull(), "Boolean property could not be null.")
|
.withRules(Objects::nonNull, "Boolean property could not be null.")
|
||||||
.withRules(b -> b, "Boolean property must be true.");
|
.withRules(b -> b, "Boolean property must be true.");
|
||||||
|
|
||||||
this.<Collection<String>>checkProperty(ROLE_LIST)
|
this.<Collection<String>>checkProperty(ROLE_LIST)
|
||||||
.withRules(c -> c != null && !c.isEmpty(), "角色列表不能为空!")
|
.withRules(CollectionTools::isNotEmpty, "角色列表不能为空!")
|
||||||
.withRules(PredicateTools.forAllItems(Objects::nonNull), () -> new NullPointerException(ROLE_LIST));
|
.withRules(l -> l.stream().allMatch(StringUtils::isNotBlank),
|
||||||
|
() -> new IllegalArgumentException(ROLE_LIST));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue