Skip to content

Commit 9d47918

Browse files
committed
✨ 添加注解类校验
1 parent 6732fa2 commit 9d47918

File tree

10 files changed

+266
-1
lines changed

10 files changed

+266
-1
lines changed

src/main/java/com/dianpoint/summer/validation/Validators.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package com.dianpoint.summer.validation;
22

3+
import com.dianpoint.summer.validation.validator.AnnotationValidatorAdapter;
34
import com.dianpoint.summer.validation.validator.GenericValidator;
5+
import com.dianpoint.summer.validation.validator.Validator;
46

57
import java.util.Objects;
68
import java.util.function.Predicate;
@@ -32,11 +34,15 @@ public static GenericValidator<Integer> integer() {
3234
.addRule(Objects::nonNull, "整数不能为空", "integer");
3335
}
3436

35-
public <T> ValidationRule<T> rule(Predicate<T> condition, String errorMessage, String fieldName) {
37+
public static <T> ValidationRule<T> rule(Predicate<T> condition, String errorMessage, String fieldName) {
3638
return target -> condition.test(target) ?
3739
ValidationResult.success() :
3840
ValidationResult.failure(errorMessage, fieldName);
3941
}
4042

43+
public static <T> Validator<T> annotated(Class<T> targetClass) {
44+
return AnnotationValidatorAdapter.create(targetClass);
45+
}
46+
4147

4248
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package com.dianpoint.summer.validation.annotations;
2+
3+
import java.lang.annotation.ElementType;
4+
import java.lang.annotation.Retention;
5+
import java.lang.annotation.RetentionPolicy;
6+
import java.lang.annotation.Target;
7+
8+
/**
9+
* @author: congccoder
10+
* @email: congccoder@gmail.com | <a href="https://github.com/ccoderJava">github-homepage</a>
11+
* @date: 2025/5/20 21:10
12+
*/
13+
14+
@Retention(RetentionPolicy.RUNTIME)
15+
@Target({ElementType.FIELD, ElementType.TYPE})
16+
public @interface NotNull {
17+
18+
String message() default "不能为空";
19+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package com.dianpoint.summer.validation.annotations;
2+
3+
import java.lang.annotation.ElementType;
4+
import java.lang.annotation.Retention;
5+
import java.lang.annotation.RetentionPolicy;
6+
import java.lang.annotation.Target;
7+
8+
/**
9+
* @author: congccoder
10+
* @email: congccoder@gmail.com | <a href="https://github.com/ccoderJava">github-homepage</a>
11+
* @date: 2025/5/20 21:11
12+
*/
13+
14+
@Retention(RetentionPolicy.RUNTIME)
15+
@Target({ElementType.FIELD, ElementType.TYPE})
16+
public @interface Pattern {
17+
18+
String regex();
19+
20+
String message() default "格式不符合要求";
21+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package com.dianpoint.summer.validation.constraintvalidators;
2+
3+
import com.dianpoint.summer.validation.ValidationResult;
4+
import com.dianpoint.summer.validation.annotations.NotNull;
5+
import com.dianpoint.summer.validation.processor.AnnotationProcessor;
6+
7+
import java.lang.annotation.Annotation;
8+
import java.lang.reflect.Field;
9+
import java.util.Collections;
10+
import java.util.List;
11+
12+
/**
13+
* @author: congccoder
14+
* @email: congccoder@gmail.com | <a href="https://github.com/ccoderJava">github-homepage</a>
15+
* @date: 2025/5/20 21:21
16+
*/
17+
18+
public class NotNullProcessor implements AnnotationProcessor {
19+
@Override
20+
public boolean support(Class<? extends Annotation> annotationType) {
21+
return NotNull.class.isAssignableFrom(annotationType);
22+
}
23+
24+
@Override
25+
public List<ValidationResult> process(Object target, Field field, Annotation annotation) {
26+
NotNull notNull = (NotNull) annotation;
27+
try {
28+
field.setAccessible(true);
29+
Object value = field.get(target);
30+
if (value == null) {
31+
return Collections.singletonList(ValidationResult.failure(notNull.message(), field.getName()));
32+
}
33+
} catch (Exception e) {
34+
return Collections.singletonList(ValidationResult.failure("无法访问字段" + field.getName(), field.getName()));
35+
}
36+
return Collections.emptyList();
37+
}
38+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package com.dianpoint.summer.validation.constraintvalidators;
2+
3+
import com.dianpoint.summer.validation.ValidationResult;
4+
import com.dianpoint.summer.validation.annotations.Pattern;
5+
import com.dianpoint.summer.validation.processor.AnnotationProcessor;
6+
7+
import java.lang.annotation.Annotation;
8+
import java.lang.reflect.Field;
9+
import java.util.Collections;
10+
import java.util.List;
11+
12+
/**
13+
* @author: congccoder
14+
* @email: congccoder@gmail.com | <a href="https://github.com/ccoderJava">github-homepage</a>
15+
* @date: 2025/5/20 21:25
16+
*/
17+
18+
public class PatternProcessor implements AnnotationProcessor {
19+
@Override
20+
public boolean support(Class<? extends Annotation> annotationType) {
21+
return Pattern.class.isAssignableFrom(annotationType);
22+
}
23+
24+
@Override
25+
public List<ValidationResult> process(Object target, Field field, Annotation annotation) {
26+
Pattern pattern = (Pattern) annotation;
27+
try {
28+
field.setAccessible(true);
29+
Object value = field.get(target);
30+
if (value == null) {
31+
return Collections.emptyList();
32+
}
33+
if (value instanceof String) {
34+
java.util.regex.Pattern regexPattern = java.util.regex.Pattern.compile(pattern.regex());
35+
if (!regexPattern.matcher(value.toString()).matches()) {
36+
return Collections.singletonList(ValidationResult.failure(pattern.message(), field.getName()));
37+
}
38+
}
39+
} catch (Exception e) {
40+
return Collections.singletonList(ValidationResult.failure("无法访问字段" + field.getName(), field.getName()));
41+
}
42+
return Collections.emptyList();
43+
}
44+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,40 @@
11
package com.dianpoint.summer.validation.processor;
22

3+
import com.dianpoint.summer.validation.annotations.NotNull;
4+
import com.dianpoint.summer.validation.annotations.Pattern;
5+
import com.dianpoint.summer.validation.constraintvalidators.NotNullProcessor;
6+
import com.dianpoint.summer.validation.constraintvalidators.PatternProcessor;
7+
8+
import java.lang.annotation.Annotation;
9+
import java.util.HashMap;
10+
import java.util.Map;
11+
312
/**
413
* @author: congccoder
514
* @email: congccoder@gmail.com | <a href="https://github.com/ccoderJava">github-homepage</a>
615
* @date: 2025/5/20 20:59
716
*/
817

918
public class AnnotationProcessorRegister {
19+
20+
private static final Map<Class<? extends Annotation>, AnnotationProcessor> PROCESSORS = new HashMap<>();
21+
22+
static {
23+
PROCESSORS.put(NotNull.class, new NotNullProcessor());
24+
PROCESSORS.put(Pattern.class, new PatternProcessor());
25+
}
26+
27+
public static void register(Class<? extends Annotation> annotationType, AnnotationProcessor annotationProcessor) {
28+
PROCESSORS.put(annotationType, annotationProcessor);
29+
}
30+
31+
public static AnnotationProcessor getProcessor(Class<? extends Annotation> annotationType) {
32+
return PROCESSORS.get(annotationType);
33+
}
34+
35+
public static boolean hasProcessor(Class<? extends Annotation> annotationType) {
36+
return PROCESSORS.containsKey(annotationType);
37+
}
38+
39+
1040
}

src/main/java/com/dianpoint/summer/validation/validator/AbstractValidator.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ public boolean isValid(T target) {
6969
return validate(target).isEmpty();
7070
}
7171

72+
@Override
7273
public Validator<T> skipOnFirstFailure(boolean skipOnFirstFailure) {
7374
this.skipOnFirstFailure = skipOnFirstFailure;
7475
return this;
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package com.dianpoint.summer.validation.validator;
2+
3+
import com.dianpoint.summer.validation.ValidationResult;
4+
import com.dianpoint.summer.validation.ValidationRule;
5+
import com.dianpoint.summer.validation.Validators;
6+
import com.dianpoint.summer.validation.processor.AnnotationProcessor;
7+
import com.sun.tools.javac.comp.Todo;
8+
9+
import java.util.Collections;
10+
import java.util.List;
11+
import java.util.function.Predicate;
12+
13+
/**
14+
* @author: congccoder
15+
* @email: congccoder@gmail.com | <a href="https://github.com/ccoderJava">github-homepage</a>
16+
* @date: 2025/5/20 21:59
17+
*/
18+
19+
public class AnnotationValidatorAdapter<T> implements Validator<T> {
20+
21+
public AnnotationValidatorAdapter(Class<T> targetClass) {
22+
this.targetClass = targetClass;
23+
}
24+
25+
public static <T> AnnotationValidatorAdapter<T> create(Class<T> clazz) {
26+
return new AnnotationValidatorAdapter<T>(clazz);
27+
}
28+
29+
private Class<T> targetClass;
30+
private boolean skipOnFirstFailure = false;
31+
32+
@Override
33+
public Validator<T> addRule(ValidationRule<T> rule) {
34+
throw new UnsupportedOperationException("注解校验器不支持手动添加规则");
35+
}
36+
37+
@Override
38+
public Validator<T> addRule(Predicate<T> condition, String errorMessage) {
39+
throw new UnsupportedOperationException("注解校验器不支持手动添加规则");
40+
}
41+
42+
@Override
43+
public Validator<T> addRule(Predicate<T> condition, String errorMessage, String fieldName) {
44+
throw new UnsupportedOperationException("注解校验器不支持手动添加规则");
45+
}
46+
47+
@Override
48+
public List<ValidationResult> validate(T target) {
49+
//TODO 处理注解类校验
50+
return Collections.emptyList();
51+
}
52+
53+
@Override
54+
public boolean isValid(T target) {
55+
return validate(target).isEmpty();
56+
}
57+
58+
@Override
59+
public Validator<T> skipOnFirstFailure(boolean skip) {
60+
this.skipOnFirstFailure = skip;
61+
return this;
62+
}
63+
64+
65+
}

src/main/java/com/dianpoint/summer/validation/validator/Validator.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,6 @@ public interface Validator<T> {
2424

2525
boolean isValid(T target);
2626

27+
Validator<T> skipOnFirstFailure(boolean skip);
28+
2729
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package com.dianpoint.summer.test.validator.cases;
2+
3+
import com.dianpoint.summer.validation.annotations.NotNull;
4+
import com.dianpoint.summer.validation.annotations.Pattern;
5+
6+
/**
7+
* @author: congccoder
8+
* @email: congccoder@gmail.com | <a href="https://github.com/ccoderJava">github-homepage</a>
9+
* @date: 2025/5/20 21:52
10+
*/
11+
12+
public class User {
13+
@NotNull(message = "用户名不能为空")
14+
private String username;
15+
16+
@Pattern(regex = "^[\\w-\\.]+@([\\w-]+\\.)+[\\w-]{2,4}$", message = "邮箱地址不正确")
17+
private String email;
18+
19+
public User(String username, String email) {
20+
this.username = username;
21+
this.email = email;
22+
}
23+
24+
public String getUsername() {
25+
return username;
26+
}
27+
28+
public void setUsername(String username) {
29+
this.username = username;
30+
}
31+
32+
public String getEmail() {
33+
return email;
34+
}
35+
36+
public void setEmail(String email) {
37+
this.email = email;
38+
}
39+
}

0 commit comments

Comments
 (0)