述
在我们日常编码中,服务端需要校验很多字段的格式,比如是不是为空,字段长度等等各种验证,这些验证如果写到我们的代码逻辑中的话,每次开始都需要做大量的校验,而且还有可能在不同的方法中校验的逻辑相同,那就可能会复制大量相同的代码,看着很烦
java给我们提供了很多验证的注解,比如下面这个model1
2
3
4
5
6
7
8
9
10
11
12
13
14
15@Data
public class User implements Serializable {
private Long id;
@Length(min=0, max=20)
private String name;
@NotBlank
private String password;
private Integer sex;
private String phoneNo;
}
这里就规定了说,传过来的 name的长度最大是20,最小是0, 密码不能是空, 如果不满足的话直接就返回了,就不需要我们再写这些验证的逻辑代码了.
但是有时候需要一些其他的通用校验,那也可以自定义一个这样的注解来实现,比如说要验证一个字段格式必须是手机号,下面看一下具体如何实现
自定义注解
首先我们需要创建一个注解,名称是PhoneNo
,具体代码如下:1
2
3
4
5
6
7
8
9
10
11
12@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = PhoneNoValidator.class)
public @interface PhoneNo {
String message() default "手机号格式有误";
Class<?>[] groups() default { };
Class<? extends Payload>[] payload() default { };
}
先来看一下上面的几个注解:
@Target({ElementType.METHOD, ElementType.FIELD})
: 用来定义这个注解能加在哪里,我们这里就是说可以加在方法上,也可以加在字段上面@Retention(RetentionPolicy.RUNTIME)
: 表示是一个运行时的注解@Constraint(validatedBy = PhoneNoValidator.class)
: 表示具体的验证逻辑类,是PhoneNoValidator
下面有个方法是message()
,用来表示验证不通过后返回的信息,默认的是手机号格式有误
具体验证逻辑
这里还需要一个具体的验证类,就是我们上面指定的 PhoneNoValidator.class
, 代码如下 :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@Slf4j
public class PhoneNoValidator implements ConstraintValidator<PhoneNo, Object> {
/**
* 手机号码正则表达式
*/
public static final String REG_PHONE = "^((13[0-9])|(15[^4,\\D])|(14[57])|(17[0])|(17[7])|(18[0,0-9]))\\d{8}$";
/**
* 验证器的初始化工作
* @param constraintAnnotation
*/
@Override
public void initialize(PhoneNo constraintAnnotation) {
log.info("进入手机号码验证器....");
}
/**
* 验证的具体逻辑
* @param value
* @param context
* @return
*/
@Override
public boolean isValid(Object value, ConstraintValidatorContext context) {
return Pattern.matches(REG_PHONE, (String)value);
}
}
这里首先是实现了ConstraintValidator<PhoneNo, Object>
接口,这里的PhoneNo
,就是我们注解的名称,然后这里需要重写两个方法, initialize()
和 isValid()
, 前面的是一个初始化的方法, 就是说,在验证方法被执行之前需要做的事情
然后是下面的验证的具体逻辑,我们上面就是写了个正则去验证手机号,最后返回的是 true/false, 对应验证通过/不通过
扩展
这个类中,可以使用@Autowired
来注入SpringBean,比如我们需要验证这个字段在数据库里面有没有,那就需要注入具体的service来跟数据库进行交互了
这里这个类是不需要加@Component
注解的,只要实现了 ConstraintValidator<PhoneNo, Object>
这个接口,Spring就会自动管理这个类的
具体使用
上面我们注解和具体的逻辑都写好了,那再来看一下如何去使用, 跟java提供的那些注解的用法是一样的,如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14@Data
public class User implements Serializable {
private Long id;
private String name;
private String password;
private Integer sex;
@PhoneNo
private String phoneNo;
}
这里如果手机号格式不正确的话,就会返回默认的错误信息, 如果需要自定义的话就在注解后面加个message就好了, 比如: @PhoneNo(message = "自定义信息")