SpringBoot 使用validation数据校验之自定义校验注解·源码分析+实例 - 第410篇
在前面我们介绍了validation的基本使用以及分组校验,但是我们会发现有些场景下,上面提供的注解不能满足我们多样化的需求,那这种情况下,要怎么办呢?
那我们会想validation框架是否允许我们自定义校验注解呢?
如果可以的话,那么问题就不攻自破了。欧了,这节我们就来一探究竟。
Spring Boot validation系列:
(1)✅《SpringBoot 使用validation数据校验-超级详细超级多干货》
(2)✅《SpringBoot 使用validation数据校验之分组校验怎么玩?·分组还有这么多的讲究》
(3)✅《SpringBoot 使用validation数据校验之自定义校验注解·源码分析+实例》
(4)《SpringBoot 使用validation数据校验之国际化问题怎么搞?》满满的干货
这一节我们先来看看《SpringBoot 使用validation数据校验之自定义校验注解》。
一、如何实现
具体要怎么实现呢,最简单的方式就是百度找个例子,就可以看看别人怎么搞就可以搞定了。
但这里我采用解读源码的方式进行探索(要是百度没有例子的话,那不是就玩玩了)。
这里我们看看@Email是如何实现的?
1.1 进入到@Email
进入到注解Email
这里有一个重要的属性@Constraint(validatedBy = { }):约束/限定,被校验,但是这里居然没有指向具体的实现类,那就是底层自己进行约定俗成进行查找了。
那我们查找Email可以可以找到搜索出来EmailValidator,这个类很有可能就是它的实现类。
1.2 进入到EmailValidator
进入到EmailValidator:
可以看到核心的两个方法,一个方法用于初始化,一个方法用于校验。
此类又是继承了AbstractEmailValidator,我们进入看下:
所以这里的核心是接口ConstraintValidator:
到这里我们就有了一个大概的思路了:
(1)定义注解接口
(2)通过实现ConstraintValidator来实现注解
二、实现一个电话验证的例子
2.1步骤说明
(1)定义注解接口
(2)通过实现ConstraintValidator来实现注解
2.2 具体编码
2.2.1 定义注解Mobile
定义注解:
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 电话校验
*
* @author 悟纤「公众号SpringBoot」
* @date 2021-10-15
* @slogan 大道至简 悟在天成
*/
@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy={MobileValidator.class})
public @interface Mobile {
String message() default"手机号校验错误";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
注解的实现:
2.2.2 注解的实现
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Mobile校验 的实现类
*
* @author 悟纤「公众号SpringBoot」
* @date 2021-10-15
* @slogan 大道至简 悟在天成
*/
public class MobileValidator implements ConstraintValidator<Mobile,String> {
//电话正则表达式
private Pattern p = Pattern.compile("^0?1[1|2|3|4|5|6|7|8|9][0-9]\\d{8}$");
//初始化方法 - 非必须要实现
// @Override
// public void initialize(Mobile constraintAnnotation) {
//
// }
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
System.out.println(value);
if(value == null){
//如果没有的情况下?认为是正确的
return true;
}
Matcher m = p.matcher(value);
boolean b = m.matches();
return b;
}
}
2.2.3 使用自定义注解
这里就可以使用我们自定的注解了@Mobile:
@NotBlank(message = "手机号不能为空")
@Mobile(message="手机号格式有误")
private String mobile;
到这里自定义注解就搞定了,是不是很轻松,很easy.
当然对于分组校验,我们这个也是支持的:
@NotBlank(message = "手机号不能为空")
@Mobile(message="手机号格式有误",groups ={ ValidGroup.Insert.class})
private String mobile;
2.3 更简单的实现方式
@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
//@Constraint(validatedBy={MobileValidator.class})
@Constraint(validatedBy = {})
@Pattern(regexp = "^0?1[1|2|3|4|5|6|7|8|9][0-9]\\d{8}$")
public @interface Mobile {
String message() default"手机号校验错误";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
这里使用@Pattern进行实现,那么@Constraint可以不需要具体的实现了。
购买完整视频,请前往:http://www.mark-to-win.com/TeacherV2.html?id=287