上一篇博客中介紹了使用validation-api結合spring validation驗證restful接口參數,但是有時候需要對請求數據的格式是否規範進行驗證。比如用戶註冊填寫的身份證、郵箱地址等,一般情況我們都是在業務代碼中獲取身份證或郵箱地址後使用正則表達式校驗是否合法,使得業務代碼中包含大量的數據校驗代碼。
比如下面這段代碼對郵箱地址正確性的校驗:
public final class Constants {
/**
* email校驗正則表達式
*/
public static final String EMAIL_VALIDATION_REGP="^([a-zA-Z0-9_\\.\\-])+\\@(([a-zA-Z0-9\\-])+\\.)+([a-zA-Z0-9]{2,4})+$";
}
@Override
public void addUser(User user) {
String email=user.getEmail();
//
if (!Pattern.matches(Constants.EMAIL_VALIDATION_REGP,email)) {
throw new BusinessException("郵箱地址格式不正確");
}
}
要解決上面這段代碼存在的問題,這時就輪到自定義Constraint出手了,使用自定義的驗證約束可以將數據驗證的從業務代碼中抽取出來,在編寫接口時只需要關注業務而不用再關注數據的格式是否合法,使用起來十分的方便。
一、編寫自定義約束校驗
使用自定義約束包含兩部分
1.編寫一個自定義註解,用來標註需要校驗的字段
@Documented
@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE})
@Constraint(validatedBy = EmailConstraintValidator.class)
@Retention(RetentionPolicy.RUNTIME)
public @interface EmailConstraint {
String message() default "email格式錯誤";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
2.編寫一個自定義Constraint Validator實現ConstraintValidator接口,在接口的泛型參數中使用第一步定義的註解(EmailConstraint),重寫接口中的isValid方法,在該方法中編寫數據的校驗規則。
public class EmailConstraintValidator implements ConstraintValidator<EmailConstraint,Object> {
@Override
public boolean isValid(Object value, ConstraintValidatorContext context) {
System.out.println("start validate ");
return VerifyUtil.verifyEmail(value.toString());
}
}
二、在實體類中使用自定義註解
@Getter
@Setter
public class Movie {
private String id;
@NotEmpty(message = "Movie name cannot be empty")
private String name;
@NotNull(message = "電影時長不能爲空")
private Integer duration;
@NotNull(message = "演員不能爲空")
@NotEmpty(message = "演員不能爲空")
private List<@Valid Actor> actors;
@NotEmpty(message = "電影描述不能爲空")
private String description;
/**
* 使用自定義註解驗證郵箱格式是否合法
*/
@EmailConstraint(message = "郵箱地址格式不正確")
@NotEmpty(message = "郵箱地址不能爲空")
private String email;
}
三、在Controller中使用@Validated註解及方法參數中使用@Valid註解
@Validated
@RestController
@RequestMapping(value = "/movies")
public class MovieController {
@PostMapping
public ResponseResult addMovie(@RequestBody @Valid Movie movie) {
movieService.addMovie(movie);
System.out.println("test");
System.out.println(movie);
return ResponseResult.success();
}
}
四、使用postmain測試自定義註解的校驗