Spring-自定义注解校验字段格式

在我们日常编码中,服务端需要校验很多字段的格式,比如是不是为空,字段长度等等各种验证,这些验证如果写到我们的代码逻辑中的话,每次开始都需要做大量的校验,而且还有可能在不同的方法中校验的逻辑相同,那就可能会复制大量相同的代码,看着很烦

java给我们提供了很多验证的注解,比如下面这个model

1
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 = "自定义信息")