Skip to content

Commit 31860d4

Browse files
authored
Merge pull request dianpoint#21 from dianpoint/feature-validator
✨ 添加一个基础校验框架,支持多种数据格式校验,包括基本类型、集合、自定义对象的校验
2 parents 2a2b667 + 2c2f3f7 commit 31860d4

File tree

8 files changed

+347
-0
lines changed

8 files changed

+347
-0
lines changed
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package com.dianpoint.summer.validation;
2+
3+
/**
4+
* @author: congccoder
5+
* @email: congccoder@gmail.com | <a href="https://github.com/ccoderJava">github-homepage</a>
6+
* @date: 2025/5/19 21:48
7+
*/
8+
9+
public class ValidationResult {
10+
private boolean success;
11+
private String errorMessage;
12+
private String fieldName;
13+
14+
public ValidationResult(boolean success, String errorMessage, String fieldName) {
15+
this.success = success;
16+
this.errorMessage = errorMessage;
17+
this.fieldName = fieldName;
18+
}
19+
20+
public static ValidationResult success() {
21+
return new ValidationResult(true, null, null);
22+
}
23+
24+
public static ValidationResult failure(String errorMessage) {
25+
return new ValidationResult(false, errorMessage, null);
26+
}
27+
28+
public static ValidationResult failure(String errorMessage, String fieldName) {
29+
return new ValidationResult(false, errorMessage, fieldName);
30+
}
31+
32+
public boolean isSuccess() {
33+
return success;
34+
}
35+
36+
public boolean isFailure() {
37+
return !success;
38+
}
39+
40+
public String getErrorMessage() {
41+
return errorMessage;
42+
}
43+
44+
public String getFieldName() {
45+
return fieldName;
46+
}
47+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package com.dianpoint.summer.validation;
2+
3+
/**
4+
* @author: congccoder
5+
* @email: congccoder@gmail.com | <a href="https://github.com/ccoderJava">github-homepage</a>
6+
* @date: 2025/5/19 21:48
7+
*/
8+
9+
@FunctionalInterface
10+
public interface ValidationRule<T> {
11+
12+
ValidationResult validate(T target);
13+
14+
// 默认方法:组合多个规则(AND关系)
15+
default ValidationRule<T> and(ValidationRule<T> other) {
16+
return target -> {
17+
ValidationResult result = this.validate(target);
18+
return result.isSuccess() ? other.validate(target) : result;
19+
};
20+
}
21+
22+
// 默认方法:组合多个规则(OR关系)
23+
default ValidationRule<T> or(ValidationRule<T> other) {
24+
return target -> {
25+
ValidationResult result = this.validate(target);
26+
return result.isSuccess() ? result : other.validate(target);
27+
};
28+
}
29+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package com.dianpoint.summer.validation;
2+
3+
/**
4+
* @author: congccoder
5+
* @email: congccoder@gmail.com | <a href="https://github.com/ccoderJava">github-homepage</a>
6+
* @date: 2025/5/19 22:26
7+
*/
8+
9+
public final class ValidationRules {
10+
11+
private ValidationRules() {
12+
13+
}
14+
15+
public static ValidationRule<String> minLength(int length) {
16+
return str -> str.length() >= length ?
17+
ValidationResult.success() :
18+
ValidationResult.failure("长度不能小于" + length, "string");
19+
}
20+
21+
public static ValidationRule<String> maxLength(int length) {
22+
return str -> str.length() <= length ?
23+
ValidationResult.success() :
24+
ValidationResult.failure("长度不能大于" + length, "string");
25+
}
26+
27+
public static ValidationRule<String> matches(String regex) {
28+
return str -> str.matches(regex) ?
29+
ValidationResult.success() :
30+
ValidationResult.failure("格式不符合要求" + regex, "string");
31+
}
32+
33+
public static ValidationRule<Integer> min(int value) {
34+
return num -> num >= value ?
35+
ValidationResult.success() :
36+
ValidationResult.failure("不能小于" + value, "integer");
37+
}
38+
39+
public static ValidationRule<Integer> max(int value) {
40+
return num -> num <= value ?
41+
ValidationResult.success() :
42+
ValidationResult.failure("不能大于" + value, "integer");
43+
}
44+
45+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package com.dianpoint.summer.validation;
2+
3+
import com.dianpoint.summer.validation.validator.GenericValidator;
4+
5+
import java.util.Objects;
6+
import java.util.function.Predicate;
7+
8+
/**
9+
* @author: congccoder
10+
* @email: congccoder@gmail.com | <a href="https://github.com/ccoderJava">github-homepage</a>
11+
* @date: 2025/5/19 22:16
12+
*/
13+
14+
public final class Validators {
15+
16+
private Validators() {
17+
}
18+
19+
public static <T> GenericValidator<T> generic() {
20+
return GenericValidator.create();
21+
}
22+
23+
public static GenericValidator<String> string() {
24+
return (GenericValidator<String>) GenericValidator.<String>create()
25+
.addRule(str -> str != null && !str.trim().isEmpty(),
26+
"字符串不能为空",
27+
"string");
28+
}
29+
30+
public static GenericValidator<Integer> integer() {
31+
return (GenericValidator<Integer>) GenericValidator.<Integer>create()
32+
.addRule(Objects::nonNull, "整数不能为空", "integer");
33+
}
34+
35+
public <T> ValidationRule<T> rule(Predicate<T> condition, String errorMessage, String fieldName) {
36+
return target -> condition.test(target) ?
37+
ValidationResult.success() :
38+
ValidationResult.failure(errorMessage, fieldName);
39+
}
40+
41+
42+
}
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
package com.dianpoint.summer.validation.validator;
2+
3+
import com.dianpoint.summer.validation.ValidationResult;
4+
import com.dianpoint.summer.validation.ValidationRule;
5+
6+
import java.util.ArrayList;
7+
import java.util.Collections;
8+
import java.util.List;
9+
import java.util.function.Predicate;
10+
11+
/**
12+
* @author: congccoder
13+
* @email: congccoder@gmail.com | <a href="https://github.com/ccoderJava">github-homepage</a>
14+
* @date: 2025/5/19 21:48
15+
*/
16+
17+
public abstract class AbstractValidator<T> implements Validator<T> {
18+
19+
private final List<ValidationRule<T>> rules = new ArrayList<>();
20+
private boolean skipOnFirstFailure = false;
21+
private boolean allowNull = false;
22+
private String nullErrorMessage = "对象不能为null";
23+
private String fieldName;
24+
25+
@Override
26+
public Validator<T> addRule(ValidationRule<T> rule) {
27+
rules.add(rule);
28+
return this;
29+
}
30+
31+
@Override
32+
public Validator<T> addRule(Predicate<T> condition, String errorMessage) {
33+
return addRule(target ->
34+
condition.test(target) ?
35+
ValidationResult.success() :
36+
ValidationResult.failure(errorMessage, fieldName));
37+
}
38+
39+
@Override
40+
public Validator<T> addRule(Predicate<T> condition, String errorMessage, String fieldName) {
41+
return addRule(target ->
42+
condition.test(target) ?
43+
ValidationResult.success() :
44+
ValidationResult.failure(errorMessage, fieldName));
45+
}
46+
47+
@Override
48+
public List<ValidationResult> validate(T target) {
49+
if (target == null) {
50+
return allowNull ?
51+
new ArrayList<>() :
52+
Collections.singletonList(ValidationResult.failure(nullErrorMessage, fieldName));
53+
}
54+
List<ValidationResult> results = new ArrayList<>();
55+
for (ValidationRule<T> rule : rules) {
56+
ValidationResult result = rule.validate(target);
57+
if (result.isFailure()) {
58+
results.add(result);
59+
if (skipOnFirstFailure) {
60+
break;
61+
}
62+
}
63+
}
64+
return results;
65+
}
66+
67+
@Override
68+
public boolean isValid(T target) {
69+
return validate(target).isEmpty();
70+
}
71+
72+
public Validator<T> skipOnFirstFailure(boolean skipOnFirstFailure) {
73+
this.skipOnFirstFailure = skipOnFirstFailure;
74+
return this;
75+
}
76+
77+
public Validator<T> fieldName(String fieldName) {
78+
this.fieldName = fieldName;
79+
return this;
80+
}
81+
82+
public Validator<T> allowNull(boolean allowNull) {
83+
this.allowNull = allowNull;
84+
return this;
85+
}
86+
87+
public Validator<T> nullErrorMessage(String nullErrorMessage) {
88+
this.nullErrorMessage = nullErrorMessage;
89+
return this;
90+
}
91+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.dianpoint.summer.validation.validator;
2+
3+
/**
4+
* @author: congccoder
5+
* @email: congccoder@gmail.com | <a href="https://github.com/ccoderJava">github-homepage</a>
6+
* @date: 2025/5/19 22:15
7+
*/
8+
9+
public class GenericValidator<T> extends AbstractValidator<T> {
10+
11+
private GenericValidator() {
12+
}
13+
14+
public static <T> GenericValidator<T> create() {
15+
return new GenericValidator<T>();
16+
}
17+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package com.dianpoint.summer.validation.validator;
2+
3+
import com.dianpoint.summer.validation.ValidationResult;
4+
import com.dianpoint.summer.validation.ValidationRule;
5+
6+
import java.util.List;
7+
import java.util.function.Predicate;
8+
9+
/**
10+
* @author: congccoder
11+
* @email: congccoder@gmail.com | <a href="https://github.com/ccoderJava">github-homepage</a>
12+
* @date: 2025/5/19 21:48
13+
*/
14+
15+
public interface Validator<T> {
16+
17+
Validator<T> addRule(ValidationRule<T> rule);
18+
19+
Validator<T> addRule(Predicate<T> condition, String errorMessage);
20+
21+
Validator<T> addRule(Predicate<T> condition, String errorMessage, String fieldName);
22+
23+
List<ValidationResult> validate(T target);
24+
25+
boolean isValid(T target);
26+
27+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package com.dianpoint.summer.test.validator;
2+
3+
import com.dianpoint.summer.validation.ValidationResult;
4+
import com.dianpoint.summer.validation.ValidationRules;
5+
import com.dianpoint.summer.validation.Validators;
6+
7+
import java.util.List;
8+
9+
/**
10+
* @author: congccoder
11+
* @email: congccoder@gmail.com | <a href="https://github.com/ccoderJava">github-homepage</a>
12+
* @date: 2025/5/19 22:33
13+
*/
14+
15+
public class ValidatorDemo {
16+
public static void main(String[] args) {
17+
validateEmail("congccoder@gmail.com");
18+
validateEmail("congccoder@dianpoint.com");
19+
20+
validateAge(16);
21+
validateAge(21);
22+
}
23+
24+
static void validateEmail(String email) {
25+
List<ValidationResult> validateResult = Validators.string()
26+
.addRule(ValidationRules.minLength(1))
27+
.addRule(ValidationRules.maxLength(20))
28+
.addRule(str -> !str.endsWith("gmail.com"), "自定义错误提示信息", "email")
29+
.addRule(ValidationRules.matches("^[\\w-\\.]+@([\\w-]+\\.)+[\\w-]{2,4}$"))
30+
.validate(email);
31+
printResults(validateResult);
32+
}
33+
34+
static void validateAge(Integer age) {
35+
List<ValidationResult> validationResults = Validators.integer()
36+
.addRule(ValidationRules.max(18))
37+
.addRule(ValidationRules.min(14))
38+
.addRule(num -> num <= 15, "自定义错误信息:青少年年龄", "age")
39+
.validate(age);
40+
printResults(validationResults);
41+
}
42+
43+
44+
static void printResults(List<ValidationResult> validateResult) {
45+
for (ValidationResult result : validateResult) {
46+
System.out.println(result.getFieldName() + "校验结果:" + result.getErrorMessage());
47+
}
48+
}
49+
}

0 commit comments

Comments
 (0)