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")
|
||||
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);
|
||||
}
|
||||
|
||||
protected final <VV extends V> PropertyValidator<K, VV> checkProperty(K key) {
|
||||
PropertyValidator<K, VV> validator = new PropertyValidator<>(key);
|
||||
protected final <VV extends V> EntryValidator<K, VV> checkProperty(K key) {
|
||||
EntryValidator<K, VV> validator = new EntryValidator<>(key);
|
||||
this.consumers.add(validator::validate);
|
||||
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.*;
|
||||
|
||||
|
@ -7,11 +7,16 @@ import java.util.Collection;
|
|||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
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.function.PredicateTools;
|
||||
import xyz.zhouxy.plusone.commons.util.RegexUtil;
|
||||
import xyz.zhouxy.plusone.validator.MapValidator;
|
||||
|
||||
class MapValidatorTests {
|
||||
|
||||
|
@ -26,34 +31,38 @@ class MapValidatorTests {
|
|||
private static final MapValidator<String, Object> validator = new MapValidator<String, Object>(
|
||||
new String[] { USERNAME, ACCOUNT, PASSWORD, AGE, BOOLEAN, ROLE_LIST }) {
|
||||
{
|
||||
checkProperty(USERNAME, String.class)
|
||||
.withRules(StringUtils::isNotEmpty)
|
||||
.withRules(PredicateTools.matches(PatternConsts.USERNAME),
|
||||
username -> new IllegalArgumentException(String.format("用户名【%s】不符合规范", username)));
|
||||
checkProperty(USERNAME, String.class).withRules(
|
||||
PredicateTools.from(StringUtils::isNotBlank)
|
||||
.and(username -> RegexUtil.matches(username, PatternConsts.USERNAME)),
|
||||
username -> new IllegalArgumentException(String.format("用户名【%s】不符合规范", username)));
|
||||
|
||||
checkProperty(ACCOUNT, String.class)
|
||||
.withRules(StringUtils::isNotEmpty)
|
||||
.withRules(PredicateTools.matchesOne(PatternConsts.EMAIL, PatternConsts.MOBILE_PHONE),
|
||||
"请输入正确的邮箱地址或手机号");
|
||||
checkProperty(ACCOUNT, String.class).withRules(
|
||||
PredicateTools.from(StringUtils::isNotBlank)
|
||||
.and(account -> RegexUtil.matchesOne(account,
|
||||
new Pattern[] { PatternConsts.EMAIL, PatternConsts.MOBILE_PHONE })),
|
||||
"请输入正确的邮箱地址或手机号");
|
||||
|
||||
checkProperty(PASSWORD, String.class)
|
||||
.withRules(StringUtils::isNotEmpty)
|
||||
.withRules(PredicateTools.matches(PatternConsts.PASSWORD), "密码不符合规范");
|
||||
.withRules(StringUtils::isNotEmpty, "密码不能为空")
|
||||
.withRules(pwd -> RegexUtil.matches(pwd, PatternConsts.PASSWORD), "密码不符合规范");
|
||||
|
||||
// 校验到多个属性,只能针对 map 本身进行校验
|
||||
withRule(m -> Objects.equals(m.get(PASSWORD), m.get(PASSWORD2)),
|
||||
"两次输入的密码不一样!");
|
||||
|
||||
checkProperty(AGE, Integer.class)
|
||||
// 通过泛型方式调用方法,指定数据类型
|
||||
this.<Integer>checkProperty(AGE)
|
||||
.withRules(Objects::nonNull)
|
||||
.withRules(age -> (18 <= age && 60 >= age));
|
||||
|
||||
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.");
|
||||
|
||||
this.<Collection<String>>checkProperty(ROLE_LIST)
|
||||
.withRules(c -> c != null && !c.isEmpty(), "角色列表不能为空!")
|
||||
.withRules(PredicateTools.forAllItems(Objects::nonNull), () -> new NullPointerException(ROLE_LIST));
|
||||
.withRules(CollectionTools::isNotEmpty, "角色列表不能为空!")
|
||||
.withRules(l -> l.stream().allMatch(StringUtils::isNotBlank),
|
||||
() -> new IllegalArgumentException(ROLE_LIST));
|
||||
}
|
||||
};
|
||||
|
Loading…
Reference in New Issue