校验实践
前提
SpringBoot+web
添加依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency>
修改实体类
package com.example.springbootvalidator.entity; import lombok.Data; import javax.validation.constraints.Email; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; /** * @author CBeann * @create 2020-01-11 16:01 */ @Data//lombok注解 public class Student { private Integer id; @NotBlank(message = "name不能为空") private String name; //@NotBlank(message = "name不能为空")//会报错 @NotNull(message = "age不能为空") private Integer age; @NotBlank(message = "email不能为空") @Email(message = "邮箱不合法") private String email; }
控制层
@RequestMapping("/hello") public String hello(@Valid Student student,//实体类前面加@Valid,异常信息存在BindingResult result中 BindingResult result) { List<String> list = new ArrayList<>(); if (result.hasErrors()) { List<ObjectError> allErrors = result.getAllErrors(); for (ObjectError allError : allErrors) { list.add(allError.getDefaultMessage()); } } return list.toString(); }
请求及请求结果
校验模式
如上图所示,默认会校验完所有属性,然后将错误信息一起返回,但很多时候不需要这样,一个校验失败了,其它就不必校验了
package com.example.springbootvalidator.config; import org.hibernate.validator.HibernateValidator; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import javax.validation.Validation; import javax.validation.Validator; import javax.validation.ValidatorFactory; /** * @author CBeann * @create 2020-01-11 19:00 */ @Configuration public class Configulation { @Bean public Validator validator() { ValidatorFactory validatorFactory = Validation.byProvider(HibernateValidator.class).configure().failFast(true).buildValidatorFactory(); Validator validator = validatorFactory.getValidator(); return validator; } }
测试如下
自定义校验规则
前提
上面的 校验实践 的基础之上进行
需求
验证sex性别参数是否合法,添加自己定义的校验注解进行校验
实践
自定义的属性注解
package com.example.springbootvalidator.myvalidator; import javax.validation.Constraint; import javax.validation.Payload; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.Target; import static java.lang.annotation.RetentionPolicy.RUNTIME; /** * @author CBeann * @create 2020-01-11 20:25 */ @Target({ElementType.FIELD}) @Retention(RUNTIME) @Documented @Constraint(validatedBy = SexValidator.class)//关联校验规则 public @interface SexAnnotation { String message() default "sex参数错误"; //下面这两个属性必须添加 Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
定义的属性校验规则
package com.example.springbootvalidator.myvalidator; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; public class SexValidator implements ConstraintValidator<SexAnnotation, String> { @Override public boolean isValid(String value, ConstraintValidatorContext context) { //符合条件 if ("男".equals(value) || "女".equals(value)) { return true; } else { //禁用默认的message的值,否则它会出现两条信息:一条是SexAnnotation中message属性的默认消息,一条是下面“不男不女”的消息 context.disableDefaultConstraintViolation(); //重新添加错误提示语句 context.buildConstraintViolationWithTemplate("不男不女").addConstraintViolation(); return false; } } }
实体类
package com.example.springbootvalidator.myvalidator; import lombok.Data; /** * @author CBeann * @create 2020-01-11 20:31 */ @Data//lombok注解 public class Person { @SexAnnotation//自定义的校验规则 private String sex;//性别 }
控制层
@RequestMapping("/hello2") public String hello2(@Valid Person person,//实体类前面加@Valid,异常信息存在BindingResult result中 BindingResult result) { List<String> list = new ArrayList<>(); if (result.hasErrors()) { List<ObjectError> allErrors = result.getAllErrors(); for (ObjectError allError : allErrors) { list.add(allError.getDefaultMessage()); } } return list.toString(); }
测试
参考
快速入手 Spring Boot 参数校验
遇到的问题
1)javax.validation.UnexpectedTypeException
字符串非空用@NotEmpty,数字非空用@NotNull二者是不一样的
如果@NotEmpty用在类型是Integer的属性上就会报错
参考:Validation异常:No validator could be found for constraint '.....' validating type 'java.lang.Integer'._king_qc的博客-CSDN博客