阿昌教你自定义注解验证Bean对象属性
阿昌 Java小菜鸡
## 前言

在之前阿昌写过一篇 【Springboot的注解字段校验,并统一设置返回值 】的文章,讲了常见的一些注解,和自定义的报错返回处理器,没看过的可以去看一下。

在Springboot中本身就可以通过大量的注解来实现对一些请求参数的校验。

这里在做一点的补充,关于自定义注解,去校验MVC,Web请求中的数据校验


正文

接下来我们就通过自定义注解的方式,为大家介绍两个手机号 & 是否是日期

在此之前,都到这里了,你别问我注解是一个什么东西,这边建议您回炉一下 (≖‿≖

1、自定义手机号校验

  • 自定义注解
1
2
3
4
5
6
7
8
9
10
11
@Target({ElementType.FIELD})//用来描述属性字段
@Retention(RetentionPolicy.RUNTIME)//用来描述运行时状态
@Constraint(validatedBy = IsPhoneValidator.class)//指定自定义校验器
public @interface IsPhone {
//校验错误信息
String message() default "手机号格式有误";
//是否强制校验
boolean isRequired() default false;
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
  • 自定义校验器

这里我用了hutool包的【正则表达式池】 (ฅ’ω’ฅ

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
//实现ConstraintValidator,泛型为: <校验注解,需要校验的值的类型>
public class IsPhoneValidator implements ConstraintValidator<IsPhone,String> {

private Boolean isRequired = false;

@Override
public void initialize(IsPhone constraintAnnotation) {
isRequired = constraintAnnotation.isRequired();
}

//参数1:传来的参数内容
//参数2:上下文(可以获取到注解填写的内容)
@Override
public boolean isValid(String phone, ConstraintValidatorContext constraintValidatorContext) {
if (isRequired){
return isPhone(phone);
}else {
if (!StringUtils.isEmpty(phone)){
return isPhone(phone);
}else {
return true;
}
}
}

//采用hutool包中的正则表达式池来校验手机号
public boolean isPhone(String phone){
return ReUtil.isMatch(Validator.MOBILE,phone);
}
}
  • 测试

这样子定义完就可以使用了

image

1
2
3
4
5
@PostMapping("/test")
public R test(@Validated @RequestBody TestBean testBean){
System.out.println(testBean.getPhone());
return R.ok();
}

因为我这里没有定义自定义拦截校验拦截器,就是如下的情况:↓

image

这样子就算完成了 (•˘_˘•


2、自定义校验时间是否为合法

那一开始肯定也是定义我们的自定义注解 ・ω・)

  • 自定义注解
1
2
3
4
5
6
7
8
9
10
11
12
/**
* @author 阿昌 自定义校验时间是否为合法
*/
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = DateValidator.class)
public @interface IsDate {
String message() default "时间格式不正确";
String formatter() default "";//校验的格式
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
  • 自定义日期合法校验器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class DateValidator implements ConstraintValidator<IsDate, String> {
@Override
public void initialize(IsDate isDate) {}

//time:传入需要校验的字符串时间
//constraintValidatorContext:注解上下文内容
@Override
public boolean isValid(String time, ConstraintValidatorContext constraintValidatorContext) {
try {
// 获取指定的时间格式化formatter
// 获取到上下文中传入的校验日期格式
String formatter =
(String) ((ConstraintDescriptorImpl) ((ConstraintValidatorContextImpl) constraintValidatorContext).getConstraintDescriptor()).getAnnotationDescriptor().getAttribute("formatter");
// 如果时间传值为 04-31,DateUtils.toLocalDate()返回结果会是 04-30,
// 所以需要比较一下转换为时间之后的值与原值是否相同,不同则格式输入有误
// 如果这里formatter格式不是yyyy-MM-dd,那么需要判断转换之前是否是以转换之后的日结尾,因为不同的话也只是最后的日不同
LocalDate date = DateUtils.toLocalDate(time,formatter);
return time.endsWith(String.valueOf(date.getDayOfMonth()));
} catch (Exception e) {
return false;
}
}
}
  • 对对应Bean类型的时间字段进行验证

image


以上就是这次的所有内容,感谢你能看到这里! `・ω・´)ゞ!

 请作者喝咖啡