则会返回如下定制化返回结果:
{ "status": 1, "data": "电子邮箱不能为空;联系人长度只允许1到3之间;年龄不能为空;联系人不允许为空;姓名不能为空;手机号格式不正确;", "msg": "FAIL", "success": false } 四、自定义校验器像是@NotNull、@Email等注解都是hibernate validation 内置的注解,我们想开发像是@Email注解一样功能的注解,如何做呢,比如@Mobile,它的使用方法将和@Email一模一样。
首先,先定义一个工具类存放ValidationUtil两个常量值
public class ValidationUtil { //手机号校验正则 public static final String MOBILE_REGX = "^[1][3-9][0-9]{9}$"; public static final String MOBILE_MSG = "手机号格式错误"; } 1.定义注解Mobile具体代码可以参考@Email的实现,直接将Email名字改成Mobile即可,如下所示:
@Documented @Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE}) @Retention(RUNTIME) public @interface Mobile { String message() default ValidationUtil.MOBILE_MSG; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; String regexp() default ValidationUtil.MOBILE_REGX; Pattern.Flag[] flags() default {}; @Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE}) @Retention(RUNTIME) @Documented public @interface List { Mobile[] value(); } } 2.定义MobileValidator实现对参数的校验逻辑 public class MobileValidator implements ConstraintValidator<Mobile, String> { private String regexp; @Override public void initialize(Mobile constraintAnnotation) { //获取校验的手机号的格式 this.regexp = constraintAnnotation.regexp(); } @Override public boolean isValid(String value, ConstraintValidatorContext context) { if (!StringUtils.hasText(value)) { return true; } return value.matches(regexp); } } 3.使用方法和@Email一模一样不赘述
五、分组校验假设一个用户注册的场景,用户注册有三种方式
用户名+图形验证码注册
邮箱+邮箱验证码注册
手机号+短信验证码注册
用户注册的时候除了方式不一样,其他用户信息基本相同,后端开了三个接口对应着着三种注册方式,请求体中我们使用一个Model封装了以上所有信息,包含着用户名、邮箱、手机号等信息,这时候不同的接口被调用,model中需要校验的参数就不一样了:
用户名注册的时候邮箱地址和手机号可以为空,但是用户名不能为空;通过邮箱注册的时候,邮箱地址不能为空,但是用户名和手机号可以为空;......
分组校验专门应对这种情况。
1.首先定义三个接口,表示三种组类别 public interface ValidEmail { } public interface ValidMobile { } public interface ValidUserName { } 2.在UserModel实体类上指名组类别 @Data @Builder @NoArgsConstructor @AllArgsConstructor @Accessors(chain = true) public class UserModel { @NotEmpty(message = "姓名不能为空", groups = {ValidUserName.class}) @UserName(groups = {ValidUserName.class}) private String name; @NotEmpty(message = "手机号不能为空", groups = {ValidMobile.class}) @Mobile(groups = {ValidMobile.class}) private String mobile; @NotEmpty(message = "电子邮箱不能为空", groups = {ValidEmail.class}) @Email(message = "电子邮箱格式不正确", groups = {ValidEmail.class}) private String email; private String password; private String address; @NotNull(message = "年龄不能为空") @Min(value = 12, message = "允许注册年龄最小为12岁", groups = {ValidEmail.class,ValidMobile.class,ValidUserName.class}) @Max(value = 24, message = "允许年龄最大为24岁",groups = {ValidEmail.class,ValidMobile.class,ValidUserName.class}) private Integer age; @NotEmpty(message = "联系人不允许为空",groups = {ValidEmail.class,ValidMobile.class,ValidUserName.class}) @Size(min = 1, max = 3, message = "联系人长度只允许1到3之间",groups = {ValidEmail.class,ValidMobile.class,ValidUserName.class}) private List<String> contacts; } 3.Controller方法上指名验证组别 /** * 手机号注册 * * @param userModel * @return */ @PostMapping("/mobile-regist") public WrapperResult<Boolean> mobileRegit(@Validated(ValidMobile.class) @RequestBody UserModel userModel) { return WrapperResult.success(true); }这时候进行如下请求:
POST :8080/user/mobile-regist
{ "mobile":"12666666666", "password":"", "address":"", "age": null, "contacts":[ ] }则会返回结果:
{ "status": 1, "data": "联系人长度只允许1到3之间;手机号格式错误;联系人不允许为空;", "msg": "FAIL", "success": false }该请求中并没有传递email和username字段,而且结果中也未校验出这两个字段,符合预期结果。
六、手动校验此处的手动校验并非是使用if/else进行简单的手动校验,而是使用Validation自带的校验工具对使用了@NotNull等注解的实体对象进行属性校验。