diff --git a/plusone-basic/plusone-basic-infrastructure/src/main/java/xyz/zhouxy/plusone/validator/BaseValidator.java b/plusone-basic/plusone-basic-infrastructure/src/main/java/xyz/zhouxy/plusone/validator/BaseValidator.java index 36b13f6..fd5305f 100644 --- a/plusone-basic/plusone-basic-infrastructure/src/main/java/xyz/zhouxy/plusone/validator/BaseValidator.java +++ b/plusone-basic/plusone-basic-infrastructure/src/main/java/xyz/zhouxy/plusone/validator/BaseValidator.java @@ -2,14 +2,18 @@ package xyz.zhouxy.plusone.validator; import java.util.ArrayList; import java.util.List; +import java.util.function.Function; import java.util.function.Predicate; +import java.util.function.Supplier; import xyz.zhouxy.plusone.exception.InvalidInputException; /** * 校验器 * - *

可以使用以下方式初始化一个校验器:

+ *

+ * 可以使用以下方式初始化一个校验器: + *

* *
  * BaseValidator<Integer> validator = new BaseValidator<>() {
@@ -20,7 +24,9 @@ import xyz.zhouxy.plusone.exception.InvalidInputException;
  * };
  * 
* - *

也可以通过继承本类,定义一个校验器(可使用单例模式)。

+ *

+ * 也可以通过继承本类,定义一个校验器(可使用单例模式)。 + *

* *

* 然后通过校验器的 {@link #validate} 方法,或 @@ -43,30 +49,40 @@ import xyz.zhouxy.plusone.exception.InvalidInputException; */ public abstract class BaseValidator { - private final List> rules = new ArrayList<>(); + private final List> rules = new ArrayList<>(); protected BaseValidator() { } - protected final void ruleFor(Predicate rule, String errorMessage) { - this.rules.add(new RuleInfo<>(rule, errorMessage)); + protected final void withRule(Predicate rule, String errorMessage) { + withRule(rule, () -> new InvalidInputException(errorMessage)); + } + + protected final void withRule(Predicate rule, Supplier exceptionCreator) { + withRule(rule, value -> exceptionCreator.get()); + } + + protected final void withRule(Predicate rule, Function exceptionCreator) { + this.rules.add(new RuleInfo<>(rule, exceptionCreator)); } public void validate(T obj) { - this.rules.forEach((RuleInfo ruleInfo) -> { - if (!ruleInfo.rule.test(obj)) { - throw new InvalidInputException(ruleInfo.message); - } - }); + this.rules.forEach(ruleInfo -> ruleInfo.validate(obj)); } - protected static class RuleInfo { - Predicate rule; - String message; + protected static class RuleInfo { + private final Predicate rule; + private final Function exceptionCreator; - public RuleInfo(Predicate rule, String message) { + private RuleInfo(Predicate rule, Function exceptionCreator) { this.rule = rule; - this.message = message; + this.exceptionCreator = exceptionCreator; + } + + private void validate(T obj) { + if (!rule.test(obj)) { + throw exceptionCreator.apply(obj); + } } } } diff --git a/plusone-basic/plusone-basic-infrastructure/src/main/java/xyz/zhouxy/plusone/validator/BaseValidator2.java b/plusone-basic/plusone-basic-infrastructure/src/main/java/xyz/zhouxy/plusone/validator/BaseValidator2.java deleted file mode 100644 index b7ba736..0000000 --- a/plusone-basic/plusone-basic-infrastructure/src/main/java/xyz/zhouxy/plusone/validator/BaseValidator2.java +++ /dev/null @@ -1,129 +0,0 @@ -package xyz.zhouxy.plusone.validator; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Objects; -import java.util.function.Function; -import java.util.function.Predicate; - -import cn.hutool.core.exceptions.ValidateException; -import lombok.AllArgsConstructor; -import xyz.zhouxy.plusone.constant.RegexConsts; -import xyz.zhouxy.plusone.util.RegexUtil; - -public abstract class BaseValidator2 { - - private List> hs = new ArrayList<>(); - - protected final ValidValueHolder ruleFor(Function getter) { - ValidValueHolder validValueHolder = new ValidValueHolder<>(getter); - hs.add(validValueHolder); - return validValueHolder; - } - - public void validate(T obj) { - for (var holder : hs) { - var value = holder.getter.apply(obj); - for (var rule : holder.rules) { - if (!rule.condition.test(value)) { - throw new ValidateException(rule.errMsg); - } - } - } - } -} - -class ValidValueHolder { - Function getter; - - List> rules = new ArrayList<>(); - - public ValidValueHolder(Function getter) { - this.getter = getter; - } - - private void addRule(Predicate condition, String errMsg) { - this.rules.add(new RuleInfo<>(condition, errMsg)); - } - - public ValidValueHolder nonNull(String errMsg) { - addRule(Objects::nonNull, errMsg); - return this; - } - - public ValidValueHolder nonEmpty(String errMsg) { - addRule(value -> { - if (value == null) { - return false; - } - if (value instanceof Collection) { - return ((Collection) value).isEmpty(); - } - if (value instanceof String) { - return ((String) value).isEmpty(); - } - return false; - }, errMsg); - return this; - } - - public ValidValueHolder size(int min, int max, String errMsg) { - addRule(value -> { - if (value == null) { - return false; - } - if (value instanceof Collection) { - int size = ((Collection) value).size(); - return size >= min && size <= max; - } - return true; - }, errMsg); - return this; - } - - public ValidValueHolder length(int min, int max, String errMsg) { - addRule(value -> { - if (value == null) { - return false; - } - if (value instanceof String) { - int length = ((String) value).length(); - return length >= min && length <= max; - } - return true; - }, errMsg); - return this; - } - - public ValidValueHolder matches(String regex, String errMsg) { - addRule(input -> RegexUtil.matches(regex, (String) input), errMsg); - return this; - } - - public ValidValueHolder matchesOr(String[] regexs, String errMsg) { - addRule(input -> RegexUtil.matchesOr((String) input, regexs), errMsg); - return this; - } - - public ValidValueHolder matchesAnd(String[] regexs, String errMsg) { - addRule(input -> RegexUtil.matchesAnd((String) input, regexs), errMsg); - return this; - } - - public ValidValueHolder email(String errMsg) { - return matches(RegexConsts.EMAIL, errMsg); - } - - @SuppressWarnings("unchecked") - public ValidValueHolder and(Predicate condition, String errMsg) { - addRule((Predicate) condition, errMsg); - return this; - } - - @AllArgsConstructor - static final class RuleInfo { - Predicate condition; - String errMsg; - } -} diff --git a/plusone-basic/plusone-basic-infrastructure/src/main/java/xyz/zhouxy/plusone/validator/Validator.java b/plusone-basic/plusone-basic-infrastructure/src/main/java/xyz/zhouxy/plusone/validator/Validator.java index cc6890e..b56ff50 100644 --- a/plusone-basic/plusone-basic-infrastructure/src/main/java/xyz/zhouxy/plusone/validator/Validator.java +++ b/plusone-basic/plusone-basic-infrastructure/src/main/java/xyz/zhouxy/plusone/validator/Validator.java @@ -36,7 +36,7 @@ import java.util.function.Predicate; */ public final class Validator extends BaseValidator { public final Validator addRule(final Predicate rule, final String errorMessage) { - ruleFor(rule, errorMessage); + withRule(rule, errorMessage); return this; } } diff --git a/plusone-basic/plusone-basic-infrastructure/src/main/java/xyz/zhouxy/plusone/validator/validator2/BaseValidator2.java b/plusone-basic/plusone-basic-infrastructure/src/main/java/xyz/zhouxy/plusone/validator/validator2/BaseValidator2.java new file mode 100644 index 0000000..843672a --- /dev/null +++ b/plusone-basic/plusone-basic-infrastructure/src/main/java/xyz/zhouxy/plusone/validator/validator2/BaseValidator2.java @@ -0,0 +1,21 @@ +package xyz.zhouxy.plusone.validator.validator2; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Function; + +public abstract class BaseValidator2 { + + private List> hs = new ArrayList<>(); + + protected final ValueValidator ruleFor(Function getter) { + ValueValidator validValueHolder = new ValueValidator<>(getter); + hs.add(validValueHolder); + return validValueHolder; + } + + public void validate(T obj) { + this.hs.forEach(valueValidator -> valueValidator.validateProperty(obj)); + } +} + diff --git a/plusone-basic/plusone-basic-infrastructure/src/main/java/xyz/zhouxy/plusone/validator/validator2/ValueValidator.java b/plusone-basic/plusone-basic-infrastructure/src/main/java/xyz/zhouxy/plusone/validator/validator2/ValueValidator.java new file mode 100644 index 0000000..69b1467 --- /dev/null +++ b/plusone-basic/plusone-basic-infrastructure/src/main/java/xyz/zhouxy/plusone/validator/validator2/ValueValidator.java @@ -0,0 +1,310 @@ +package xyz.zhouxy.plusone.validator.validator2; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Objects; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.function.Supplier; + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import xyz.zhouxy.plusone.constant.RegexConsts; +import xyz.zhouxy.plusone.exception.InvalidInputException; +import xyz.zhouxy.plusone.util.RegexUtil; + +public class ValueValidator { + Function getter; + List> rules = new ArrayList<>(); + + public ValueValidator(Function getter) { + this.getter = getter; + } + + private void withRule(Predicate condition, String errMsg) { + withRule(condition, value -> new InvalidInputException(errMsg)); + } + + private void withRule(Predicate condition, + Function exceptionCreator) { + this.rules.add(new RuleInfo<>(condition, exceptionCreator)); + } + + // ==================== + // ====== Object ====== + // ==================== + + // ====== notNull ===== + + public ValueValidator notNull(String errMsg) { + return notNull(value -> new InvalidInputException(errMsg)); + } + + public ValueValidator notNull(Supplier exceptionCreator) { + return notNull(value -> exceptionCreator.get()); + } + + public ValueValidator notNull(Function exceptionCreator) { + withRule(Objects::nonNull, exceptionCreator); + return this; + } + + // ====== isNull ===== + + public ValueValidator isNull(String errMsg) { + return isNull(value -> new InvalidInputException(errMsg)); + } + + public ValueValidator isNull(Supplier exceptionCreator) { + return isNull(value -> exceptionCreator.get()); + } + + public ValueValidator isNull(Function exceptionCreator) { + withRule(Objects::isNull, exceptionCreator); + return this; + } + + // ===== equals ===== + + public ValueValidator equalsThat(Object that) { + return equalsThat(that, value -> new InvalidInputException(String.format("(%s) 必须与 (%s) 相等", value, that))); + } + + public ValueValidator equalsThat(Object that, String errMsg) { + return equalsThat(that, value -> new InvalidInputException(errMsg)); + } + + public ValueValidator equalsThat( + Object that, Supplier exceptionCreator) { + return equalsThat(that, value -> exceptionCreator.get()); + } + + public ValueValidator equalsThat( + Object that, Function exceptionCreator) { + withRule(value -> Objects.equals(value, that), exceptionCreator); + return this; + } + + // ===== state ===== + + public ValueValidator state(Predicate condition) { + return state(condition, value -> new InvalidInputException("无效的用户输入")); + } + + public ValueValidator state(Predicate condition, String errMsg) { + return state(condition, value -> new InvalidInputException(errMsg)); + } + + public ValueValidator state( + Predicate condition, + Supplier exceptionCreator) { + return state(condition, value -> exceptionCreator.get()); + } + + public ValueValidator state( + Predicate condition, + Function exceptionCreator) { + withRule(condition, exceptionCreator); + return this; + } + + // ================= + // ====== int ====== + // ================= + + public ValueValidator between(int min, int max) { + return between(min, max, String.format("数值不在 %d 和 %d 之间", min, max)); + } + + public ValueValidator between(int min, int max, String errMsg) { + return between(min, max, value -> new InvalidInputException(errMsg)); + } + + public ValueValidator between(int min, int max, + Supplier exceptionCreator) { + return between(min, max, value -> exceptionCreator.get()); + } + + public ValueValidator between(int min, int max, + Function exceptionCreator) { + withRule(value -> ((int) value >= min && (int) value < max), exceptionCreator); + return this; + } + + // ================================ + // ====== Collection, String ====== + // ================================ + + // ====== notEmpty ===== + + public ValueValidator notEmpty(String errMsg) { + return notEmpty(value -> new InvalidInputException(errMsg)); + } + + public ValueValidator notEmpty(Supplier exceptionCreator) { + return notEmpty(value -> exceptionCreator.get()); + } + + public ValueValidator notEmpty(Function exceptionCreator) { + withRule(value -> { + if (value == null) { + return false; + } + if (value instanceof Collection) { + return !((Collection) value).isEmpty(); + } + if (value instanceof String) { + return !((String) value).isEmpty(); + } + return false; + }, exceptionCreator); + return this; + } + + // ====== isEmpty ===== + + public ValueValidator isEmpty(String errMsg) { + return isEmpty(value -> new InvalidInputException(errMsg)); + } + + public ValueValidator isEmpty(Supplier exceptionCreator) { + return isEmpty(value -> exceptionCreator.get()); + } + + public ValueValidator isEmpty(Function exceptionCreator) { + withRule(value -> { + if (value == null) { + return false; + } + if (value instanceof Collection) { + return ((Collection) value).isEmpty(); + } + if (value instanceof String) { + return ((String) value).isEmpty(); + } + return false; + }, exceptionCreator); + return this; + } + + // ===================== + // ====== boolean ====== + // ===================== + + // ====== isTrue ====== + + public ValueValidator isTrue() { + return isTrue(value -> new InvalidInputException("Value must be true.")); + } + + public ValueValidator isTrue(String errMsg) { + return isTrue(value -> new InvalidInputException(errMsg)); + } + + public ValueValidator isTrue(Supplier exceptionCreator) { + return isTrue(value -> exceptionCreator.get()); + } + + public ValueValidator isTrue(Function exceptionCreator) { + withRule(Boolean.TRUE::equals, exceptionCreator); + return this; + } + + // ====== isFalse ====== + + public ValueValidator isFalse() { + return isFalse(value -> new InvalidInputException("Value must be true.")); + } + + public ValueValidator isFalse(String errMsg) { + return isFalse(value -> new InvalidInputException(errMsg)); + } + + public ValueValidator isFalse(Supplier exceptionCreator) { + return isFalse(value -> exceptionCreator.get()); + } + + public ValueValidator isFalse(Function exceptionCreator) { + withRule(Boolean.FALSE::equals, exceptionCreator); + return this; + } + + // ==================== + // ====== String ====== + // ==================== + + // ===== matches ===== + + public ValueValidator matches(String regex, String errMsg) { + return matches(regex, value -> new InvalidInputException(errMsg)); + } + + public ValueValidator matches(String regex, + Supplier exceptionCreator) { + return matches(regex, value -> exceptionCreator.get()); + } + + public ValueValidator matches(String regex, + Function exceptionCreator) { + withRule(input -> RegexUtil.matches((String) input, regex), exceptionCreator); + return this; + } + + // ===== matchesOr ===== + + public ValueValidator matchesOr(String[] regexs, String errMsg) { + return matchesOr(regexs, value -> new InvalidInputException(errMsg)); + } + + public ValueValidator matchesOr(String[] regexs, + Supplier exceptionCreator) { + return matchesOr(regexs, value -> exceptionCreator.get()); + } + + public ValueValidator matchesOr(String[] regexs, + Function exceptionCreator) { + withRule(input -> RegexUtil.matchesOr((String) input, regexs), exceptionCreator); + return this; + } + + // ===== matchesOr ===== + + public ValueValidator matchesAnd(String[] regexs, String errMsg) { + withRule(input -> RegexUtil.matchesAnd((String) input, regexs), errMsg); + return this; + } + + // ===== email ===== + + public ValueValidator email(String errMsg) { + return email(value -> new InvalidInputException(errMsg)); + } + + public ValueValidator email(Supplier exceptionCreator) { + return email(value -> exceptionCreator.get()); + } + + public ValueValidator email(Function exceptionCreator) { + return matches(RegexConsts.EMAIL, exceptionCreator); + } + + // ======================================================================== + + void validateProperty(DTO obj) { + PROPERTY value = this.getter.apply(obj); + this.rules.forEach(rule -> rule.validate(value)); + } + + @AllArgsConstructor(access = AccessLevel.PRIVATE) + private static final class RuleInfo { + private final Predicate condition; + private final Function exceptionCreator; + + private void validate(V obj) { + if (!this.condition.test(obj)) { + throw exceptionCreator.apply(obj); + } + } + } +} diff --git a/plusone-basic/plusone-basic-infrastructure/src/test/java/xyz/zhouxy/plusone/validator/BaseValidator2Test.java b/plusone-basic/plusone-basic-infrastructure/src/test/java/xyz/zhouxy/plusone/validatortest/BaseValidator2Test.java similarity index 71% rename from plusone-basic/plusone-basic-infrastructure/src/test/java/xyz/zhouxy/plusone/validator/BaseValidator2Test.java rename to plusone-basic/plusone-basic-infrastructure/src/test/java/xyz/zhouxy/plusone/validatortest/BaseValidator2Test.java index 6acdee4..7a963d8 100644 --- a/plusone-basic/plusone-basic-infrastructure/src/test/java/xyz/zhouxy/plusone/validator/BaseValidator2Test.java +++ b/plusone-basic/plusone-basic-infrastructure/src/test/java/xyz/zhouxy/plusone/validatortest/BaseValidator2Test.java @@ -1,4 +1,4 @@ -package xyz.zhouxy.plusone.validator; +package xyz.zhouxy.plusone.validatortest; import org.junit.jupiter.api.Test; @@ -6,12 +6,13 @@ import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import xyz.zhouxy.plusone.constant.RegexConsts; +import xyz.zhouxy.plusone.validator.validator2.BaseValidator2; class BaseValidator2Test { @Test void testValid() { - LoginCommand loginCommand = new LoginCommand("13169053215@qq.com", "8GouTDE53a", false); + LoginCommand loginCommand = new LoginCommand("13169053215@qq.com", "A1qZ6c-cQ78=^(", false); LoginCommandValidator.INSTANCE.validate(loginCommand); System.err.println(loginCommand); } @@ -32,10 +33,11 @@ class LoginCommandValidator extends BaseValidator2 { private LoginCommandValidator() { ruleFor(loginCommand -> loginCommand.getAccount()) - .nonNull("邮箱地址不能为空") - .matchesOr(new String[] { RegexConsts.EMAIL, RegexConsts.MOBILE_PHONE }, "请输入邮箱地址或手机号"); + .notNull("邮箱地址不能为空") + .matchesOr(new String[] { RegexConsts.EMAIL, RegexConsts.MOBILE_PHONE }, value -> new RuntimeException('"' + value + "\" 不是邮箱地址或手机号")); ruleFor(loginCommand -> loginCommand.getPwd()) - .nonNull("密码不能为空") + .notNull("密码不能为空") + .notEmpty("密码不能为空") .matches(RegexConsts.PASSWORD, "密码格式错误"); } } diff --git a/plusone-system/plusone-system-application/src/main/java/xyz/zhouxy/plusone/system/application/service/command/validator/LoginByOtpCommandValidator.java b/plusone-system/plusone-system-application/src/main/java/xyz/zhouxy/plusone/system/application/service/command/validator/LoginByOtpCommandValidator.java index b21b170..01d3eaa 100644 --- a/plusone-system/plusone-system-application/src/main/java/xyz/zhouxy/plusone/system/application/service/command/validator/LoginByOtpCommandValidator.java +++ b/plusone-system/plusone-system-application/src/main/java/xyz/zhouxy/plusone/system/application/service/command/validator/LoginByOtpCommandValidator.java @@ -15,13 +15,13 @@ import xyz.zhouxy.plusone.validator.DtoValidator; @DtoValidator(LoginByOtpCommand.class) public class LoginByOtpCommandValidator extends BaseValidator { public LoginByOtpCommandValidator() { - ruleFor(loginCommand -> { + withRule(loginCommand -> { String principal = loginCommand.getPrincipal(); return StringUtils.hasText(principal) && RegexUtil.matchesOr(principal, RegexConsts.EMAIL, RegexConsts.MOBILE_PHONE); }, "输入邮箱地址或手机号"); - ruleFor(loginCommand -> { + withRule(loginCommand -> { String otp = loginCommand.getOtp(); return StringUtils.hasText(otp) && Pattern.matches(RegexConsts.CAPTCHA, otp); }, "验证码不符合要求"); diff --git a/plusone-system/plusone-system-application/src/main/java/xyz/zhouxy/plusone/system/application/service/command/validator/LoginByPasswordCommandValidator.java b/plusone-system/plusone-system-application/src/main/java/xyz/zhouxy/plusone/system/application/service/command/validator/LoginByPasswordCommandValidator.java index 3fa2e2a..9aad770 100644 --- a/plusone-system/plusone-system-application/src/main/java/xyz/zhouxy/plusone/system/application/service/command/validator/LoginByPasswordCommandValidator.java +++ b/plusone-system/plusone-system-application/src/main/java/xyz/zhouxy/plusone/system/application/service/command/validator/LoginByPasswordCommandValidator.java @@ -15,13 +15,13 @@ import xyz.zhouxy.plusone.validator.DtoValidator; @DtoValidator(LoginByPasswordCommand.class) public class LoginByPasswordCommandValidator extends BaseValidator { public LoginByPasswordCommandValidator() { - ruleFor(loginCommand -> { + withRule(loginCommand -> { String principal = loginCommand.getPrincipal(); return StringUtils.hasText(principal) && RegexUtil.matchesOr(principal, RegexConsts.USERNAME, RegexConsts.EMAIL, RegexConsts.MOBILE_PHONE, principal); }, "输入用户名、邮箱地址或手机号"); - ruleFor(loginCommand -> { + withRule(loginCommand -> { String password = loginCommand.getPassword(); return StringUtils.hasText(password) &&