数据校验是一项常见的任务,在没有引入框架之前,我们通常的做法都是一堆的if
、 else
等等,在代码中非常不美观,只用Hibernate Validator可以简化代码。
环境搭建
javaSE版本
1.引入pom.xml文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| <dependency> <groupId>org.hibernate.validator</groupId> <artifactId>hibernate-validator</artifactId> <version>6.1.6.Final</version> </dependency>
<dependency> <groupId>org.glassfish</groupId> <artifactId>jakarta.el</artifactId> <version>3.0.3</version> </dependency>
<dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.5.6</version> </dependency>
|
2.编写ValidatorUtil工具类
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 29 30 31 32 33 34 35 36 37 38 39 40
| public class ValidationUtil { private static Validator validator; private static Validator faliFastValidator; private static ExecutableValidator executableValidator;
static { validator = Validation.buildDefaultValidatorFactory().getValidator(); faliFastValidator = Validation.byProvider(HibernateValidator.class).configure().failFast(true).buildValidatorFactory().getValidator(); executableValidator = validator.forExecutables(); }
public static void validateParameters(Object var1, Method var2, Object[] var3, Class<?>... var4) { Set<ConstraintViolation<Object>> constraintViolations = executableValidator.validateParameters(var1, var2, var3, var4); constraintViolations.forEach(i -> { throw new RuntimeException(i.getMessage()); }); }
public static void valid(Object o) { Set<ConstraintViolation<Object>> validate = validator.validate(o); validate.stream().forEach(v -> { System.out.println(v.getMessage());
}); }
public static void fastValid(Object o) { Set<ConstraintViolation<Object>> validate = faliFastValidator.validate(o); validate.stream().forEach(v -> { System.out.println(v.getMessage());
}); } }
|
3.声明和验证bean约束
编写bean类UserInfo.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| public class UserInfo { @NotBlank(message = "姓名不能为空") private String name; @Min(value = 18, message = "未成年人禁止使用") private int age;
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; } }
|
编写测试类Main.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public class Main { public static void main(String[] args) { UserInfo userInfo = new UserInfo(); userInfo.setAge(12); userInfo.setName("");
ValidationUtil.valid(userInfo);
}
|
4.声明和验证方法约束
编写service接口和类(为什么要使用接口呢?因为要使用动态代理)
1 2 3 4 5 6
| public interface IUserInfoService { void add(@NotBlank(message = "用户名不能为空") String username); void add(@Valid UserInfo userInfo); }
|
@Valid :注解于参数为bean的情况
1 2 3 4 5 6 7 8 9 10
| public class UserInfoService implements IUserInfoService { public void add(String username) { System.out.println("添加成功["+username+"]"); }
@Override public void add(UserInfo userInfo) { System.out.println(userInfo); } }
|
编写代理类
1 2 3 4 5 6 7 8
| public class ValidatorAspect extends SimpleAspect { @Override public boolean before(Object target, Method method, Object[] args) { ValidationUtil.validateParameters(target, method, args); return true; } }
|
编写测试类Main.java
1 2 3 4 5 6 7 8 9 10 11 12 13
| public class Main { public static void main(String[] args) { UserInfo userInfo = new UserInfo(); userInfo.setAge(12); userInfo.setName(""); IUserInfoService proxy = ProxyUtil.proxy(new UserInfoService(), ValidatorAspect.class); proxy.add(""); proxy.add(userInfo); } }
|
本案例只是对hibernate-validator方法约束的入门使用,在实际使用中都是通过spring aop等工具来完成,spring已经提供的提供了和hibernate-validator的整合,在后面的案例会有
springMVC版本(纯java配置)
1.引入jar包
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 29
| <dependency> <groupId>javax</groupId> <artifactId>javaee-api</artifactId> <version>7.0</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.3.2</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.12.0</version> </dependency> <dependency> <groupId>org.hibernate.validator</groupId> <artifactId>hibernate-validator</artifactId> <version>6.1.6.Final</version> </dependency>
<dependency> <groupId>org.glassfish</groupId> <artifactId>jakarta.el</artifactId> <version>3.0.3</version> </dependency>
|
2.springmvc相关配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected Class<?>[] getRootConfigClasses() { return null; }
@Override protected Class<?>[] getServletConfigClasses() { return new Class[]{WebConfig.class}; } @Override protected String[] getServletMappings() { return new String[]{"/"}; } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| @Configuration @EnableWebMvc @ComponentScan(value = "zone.lxy",includeFilters = @ComponentScan.Filter(classes = {Controller.class})) public class WebConfig implements WebMvcConfigurer {
@Bean public MethodValidationPostProcessor methodValidationPostProcessor() { return new MethodValidationPostProcessor(); } }
|
3.在controller中使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| @Validated @RestController public class IndexController {
@GetMapping("/") public Object index(@NotEmpty String s) { return s; }
@RequestMapping("/user") public User info(@Valid User user) { return user; } }
|
注: 此时不满足条件会报异常,还需要配置一个全局异常拦截器就好了
springboot版本
- 在springboot 2.3以下时已经默认给你整合好了,直接用就即可。
- 在使用2.3及以上版本时,需要添加额外jar包
1 2 3 4
| <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency>
|
常见内置约束
Hibernate Validator包含一组基本的常用约束。更多
名称 |
说明 |
支持的数据类型 |
@AssertFalse |
检查被注解的元素是否为false |
Boolean, boolean |
@DecimalMax(value=, inclusive=) |
inclusive= false时,检查被注解的值是否小于指定的最大值。否则,该值是否小于或等于指定的最大值。 |
BigDecimal,BigInteger,byte,short,int,long和原始类型的相应的包装; CharSequence的任何子类型,Number和的javax.money.MonetaryAmoun任何子类型 |
@DecimalMin(value=, inclusive=) |
inclusive= false时,检查被注解的值是否大于指定的最小值。否则,该值是否大于或等于指定的最小值。 |
同上 |
@Digits(integer=, fraction=) |
检查被注解的值是否是最多由integer数字和fraction小数位组成的数字 |
同上 |
@Max(value=) |
检查被注解的值是否小于或等于指定的最大值 |
同上 |
@Min(value=) |
检查被注解的值是否大于或等于指定的最小值 |
同上 |
@Range(min=, max=) |
检查带注释的值是否介于(包括)指定的最小值和最大值之间 |
同上 |
@Negative |
检查元素是否严格为负。零值被视为无效。 |
同上 |
@Positive |
检查元素是否严格为正。零值被视为无效。 |
同上 |
@NegativeOrZero |
检查元素是否为负数或零。 |
同上 |
@PositiveOrZero |
检查元素是否为正数或零。 |
同上 |
@Future |
检查被注解的日期是否是将来的日期 |
java.util.Date,java.util.Calendar,java.time.Instant,java.time.LocalDate,java.time.LocalDateTime,java.time.LocalTime,java.time.MonthDay,java.time.OffsetDateTime,java.time.OffsetTime,java.time.Year,java.time.YearMonth,java.time.ZonedDateTime,java.time.chrono.HijrahDate,java.time.chrono.JapaneseDate,java.time.chrono.MinguoDate,java.time.chrono.ThaiBuddhistDate; |
@FutureOrPresent |
检查被注解的日期是否为现在或将来的日期 |
同上 |
@Past |
检查带注释的日期是否是过去的日期 |
同上 |
@PastOrPresent |
检查带注释的日期是否为过去或现在的日期 |
同上 |
@NotEmpty |
检查带注释的元素是否不为null或为空 |
CharSequence,Collection,Map和数组 |
@Size(min=, max=) |
检查带注释的元素的大小是否介于min和之间max(包括) |
同上 |
@NotNull |
检查注释的值不是 null |
任意种类 |
@Null |
检查注释的值是 null |
同上 |
@Pattern(regex=, flags=) |
检查带注释的字符串是否与正则表达式匹配 |
CharSequence |
@URL(protocol=, host=, port=, regexp=, flags=) |
根据RFC2396检查带注释的字符序列是否为有效URL。 |
同上 |
@Email |
检查指定的字符序列是否为有效的电子邮件地址。 |
同上 |
@NotBlank |
检查被注解的字符序列是否不为null以及修剪后的长度是否大于0。与的区别@NotEmpty在于,此约束只能应用于字符序列,并且尾随空白将被忽略。 |
同上 |
__END__