Skip to content

Commit 8b61699

Browse files
committed
docs: 完善文档 自定义约束注解
1 parent f320c05 commit 8b61699

File tree

1 file changed

+77
-25
lines changed

1 file changed

+77
-25
lines changed
+77-25
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,106 @@
11
# 自定义约束注解
22

3-
如果你使用过 `javax.validation` 的自定义约束注解,那么你会发现 `SpEL Validator` 的自定义约束注解几乎与 `javax.validation`
4-
一致。
3+
::: tip
4+
如果你使用过 `javax.validation` 的自定义约束注解,那么你会发现 `SpEL Validator` 的自定义约束注解几乎与 `javax.validation` 一致。
5+
:::
56

6-
下面以 `@SpelNotNull` 为例,展示如何实现自定义约束注解。
7-
8-
**以下内容还没写完**
7+
下面以 `@SpelNotBlank` 为例,展示如何实现自定义约束注解。
98

109
## 创建约束注解类
1110

11+
每个约束注释必须包含以下属性:
12+
- `String message() default "";` 用于指定约束校验失败时的错误消息。
13+
- `String condition() default "";` 用于指定约束开启条件的SpEL表达式。
14+
- `String[] group() default {};` 用于指定分组条件的SpEL表达式。
15+
1216
```java
13-
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})
14-
@Retention(RetentionPolicy.RUNTIME)
1517
@Documented
16-
@Constraint(validatedBy = SpelNotNullValidator.class)
17-
public @interface SpelNotNull {
18+
@Retention(RetentionPolicy.RUNTIME)
19+
@Target(ElementType.FIELD)
20+
@Repeatable(SpelNotBlank.List.class)
21+
public @interface SpelNotBlank {
1822

19-
String message() default "{javax.validation.constraints.NotNull.message}";
23+
String message() default "不能为空字符串";
2024

21-
Class<?>[] groups() default {};
25+
String condition() default "";
2226

23-
Class<? extends Payload>[] payload() default {};
27+
String[] group() default {};
2428

25-
String condition() default "";
29+
@Target(FIELD)
30+
@Retention(RUNTIME)
31+
@Documented
32+
@interface List {
33+
34+
SpelNotBlank[] value();
35+
36+
}
2637

2738
}
2839
```
2940

3041
## 创建约束验证器
3142

43+
创建类 `SpelNotBlankValidator`,实现 `SpelConstraintValidator<T>` 接口,其中泛型 `T` 为要校验的约束注解类,在这里是 `SpelNotBlank`
44+
45+
实现 `isValid` 方法,校验逻辑在该方法中实现。
46+
47+
`isValid` 方法的参数说明如下:
48+
- `annotation`:当前约束注解的实例。
49+
- `obj`:当前校验的根对象。
50+
- `field`:当前校验的字段。
51+
3252
```java
33-
public class SpelNotNullValidator implements ConstraintValidator<SpelNotNull, Object> {
53+
public class SpelNotBlankValidator implements SpelConstraintValidator<SpelNotBlank> {
54+
55+
@Override
56+
public FieldValidResult isValid(SpelNotBlank annotation, Object obj, Field field) throws IllegalAccessException {
57+
CharSequence fieldValue = (CharSequence) field.get(obj);
58+
return new FieldValidResult(StringUtils.hasText(fieldValue));
59+
}
60+
61+
}
62+
```
63+
64+
一般情况下,只需要校验当前字段的值,通过 `field.get(obj)` 即可获取。
65+
66+
有些约束注解可能仅支持特定类型的字段,可以通过重写 `supportType()` 方法来指定支持的类型。默认情况下,支持所有类型。
3467

35-
private String condition;
68+
```java
69+
public class SpelNotBlankValidator implements SpelConstraintValidator<SpelNotBlank> {
3670

3771
@Override
38-
public void initialize(SpelNotNull constraintAnnotation) {
39-
this.condition = constraintAnnotation.condition();
72+
public FieldValidResult isValid(SpelNotBlank annotation, Object obj, Field field) throws IllegalAccessException {
73+
CharSequence fieldValue = (CharSequence) field.get(obj);
74+
return new FieldValidResult(StringUtils.hasText(fieldValue));
4075
}
4176

77+
private static final Set<Class<?>> SUPPORT_TYPE = Collections.singleton(CharSequence.class);
78+
4279
@Override
43-
public boolean isValid(Object value, ConstraintValidatorContext context) {
44-
if (value == null) {
45-
return false;
46-
}
47-
if (StringUtils.hasText(condition)) {
48-
return SpelUtils.evaluate(condition, value, Boolean.class);
49-
}
50-
return true;
80+
public Set<Class<?>> supportType() {
81+
return SUPPORT_TYPE;
5182
}
5283

5384
}
5485
```
86+
87+
## 关联注解和验证器
88+
89+
`SpelNotBlank` 注解上添加 `@SpelConstraint` 注解,指定该注解的验证器为 `SpelNotBlankValidator`
90+
91+
```java
92+
@Documented
93+
@Retention(RUNTIME)
94+
@Target(FIELD)
95+
@Repeatable(SpelNotBlank.List.class)
96+
@SpelConstraint(validatedBy = SpelNotBlankValidator.class) // 关联验证器
97+
public @interface SpelNotBlank {
98+
// ...
99+
}
100+
```
101+
102+
## 使用自定义约束注解
103+
104+
完成上面的步骤,就可以在需要校验的字段上使用 `@SpelNotBlank` 注解了,使用方法就和内置的约束注解一样,[使用指南](user-guide.md)
105+
106+
已经大功告成了,这里我就不举例了。

0 commit comments

Comments
 (0)