Hibernate Validator校验数据详解(附带实例)
使用 Hibernate Validator 校验数据需要定义一个接收的数据模型,使用注解的形式描述字段校验的规则。
下面以 User 对象为例演示如何使用 Hibernate Validator 校验数据。
首先,创建 Java Bean 实体类:
在上面的示例中,每个注解中的属性 message 是数据校验不通过时要给出的提示信息,如 @Email(message="邮件格式错误"),当邮件格式校验不通过时,提示邮件格式错误。
然后,添加数据校验方法:
注意,BindingResult 必须跟在被校验参数之后,若被校验参数之后没有 BindingResult 对象,则会抛出 BindException。
最后,运行验证。启动项目,在 postman 中请求 /user/check 接口,后台输出了数据验证的结果:
示例代码如下:
下面通过示例演示分组校验。首先,创建分组 GroupA 和 GroupB,示例代码如下:
然后,创建实体类 Person,并在相关的字段中定义校验分组规则,示例代码如下:
最后,使用校验分组:
下面以 User 对象为例演示如何使用 Hibernate Validator 校验数据。
JavaBean参数校验
Post 请求参数较多时,可以在对应的数据模型(Java Bean)中进行数据校验,通过注解来指定字段校验的规则。下面以具体的实例来进行演示。首先,创建 Java Bean 实体类:
public class User { @NotBlank(message = "姓名不允许为空!") @Length(min = 2,max = 10,message = "姓名长度错误,姓名长度2-10!") private String name; @NotNull(message = "年龄不能为空!") @Min(18) private int age; @NotBlank(message = "地址不能为空!") private String address; @Pattern(regexp = "^((13[0-9])|(14[5,7,9])|(15([0-3]|[5-9]))|(166)|(17[0,1,3,5,6,7,8])|(18[0-9])|(19[8|9]))\\d{8}$", message = "手机号格式错误") private String phone; @Email(message = "邮箱格式错误") private String email; // 省略get和set方法 }
在上面的示例中,每个注解中的属性 message 是数据校验不通过时要给出的提示信息,如 @Email(message="邮件格式错误"),当邮件格式校验不通过时,提示邮件格式错误。
然后,添加数据校验方法:
@PostMapping(path = "/check") public String check(@RequestBody @Valid User user, BindingResult result) { String name = user.getName(); if(result.hasErrors()) { List<ObjectError> list = result.getAllErrors(); for (ObjectError error : list) { System.out.println(error.getCode()+ "-" + error.getDefaultMessage()); } } return name; }在上面的示例中,在 @RequestBody 注解后面添加了 @Valid 注解,然后在后面添加了 BindingResult 返回验证结果,BindingResult 是验证不通过时的结果集合。
注意,BindingResult 必须跟在被校验参数之后,若被校验参数之后没有 BindingResult 对象,则会抛出 BindException。
最后,运行验证。启动项目,在 postman 中请求 /user/check 接口,后台输出了数据验证的结果:
Length-密码长度错误,密码长度6-20!
Min-最小不能小于18
Length-姓名长度错误,姓名长度2-10!
URL参数校验
一般 GET 请求都是在 URL 中传入参数。对于这种情况,可以直接通过注解来指定参数的校验规则。下面通过实例进行演示:import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import javax.validation.constraints.*; @Validated public class UserController { @RequestMapping("/query") public String query( @Length(min = 2, max = 10, message = "姓名长度错误,姓名长度2-10!") @RequestParam(name = "name", required = true) String name, @Min(value = 1, message = "年龄最小只能1") @Max(value = 99, message = "年龄最大只能99") @RequestParam(name = "age", required = true) int age) { System.out.println(name + "," + age); return name + "," + age; } }在上面的示例中,使用 @Range、@Min、@Max 等注解对 URL 中传入的参数进行校验。需要注意的是,使用 @Valid 注解是无效的,需要在方法所在的控制器上添加 @Validated 注解来使得验证生效。
JavaBean对象级联校验
对于 JavaBean 对象中的普通属性字段,我们可以直接使用注解进行数据校验,那如果是关联对象呢?其实也很简单,在属性上添加 @Valid 注解就可以作为属性对象的内部属性进行验证(验证 User 对象,可以验证 UserDetail 的字段)。示例代码如下:
public class User { @Size(min = 3,max = 5,message = "list的Size在[3,5]") private List<String> list; @NotNull @Valid private Demo3 demo3; } public class UserDetail { @Length(min = 5, max = 17, message = "length长度在[5,17]之间") private String extField; }在上面的示例中,在属性上添加 @Valid 就可以对 User 中的关联对象 UserDetail 的字段进行数据校验。
分组校验
在不同情况下,可能对JavaBean对象的数据校验规则有所不同,有时需要根据数据状态对JavaBean中的某些属性字段进行单独验证。这时就可以使用分组校验功能,即根据状态启用一组约束。Hibernate Validator的注解提供了groups参数,用于指定分组,如果没有指定groups参数,则默认属于javax.validation.groups.Default分组。下面通过示例演示分组校验。首先,创建分组 GroupA 和 GroupB,示例代码如下:
public interface GroupA { } public interface GroupB { }在上面的示例中,我们定义了 GroupA 和 GroupB 两个接口作为两个校验规则的分组。
然后,创建实体类 Person,并在相关的字段中定义校验分组规则,示例代码如下:
public class User { @NotBlank(message = "userId不能为空",groups = {GroupA.class}) /**用户id*/ private Integer userId; @NotBlank(message = "用户名不能为空",groups = {GroupA.class}) /**用户id*/ private String name; @Length(min = 30,max = 40,message = "必须在[30,40]",groups = {GroupB.class}) @Length(min = 20,max = 30,message = "必须在[20,30]",groups = {GroupA.class}) /**用户名*/ private int age; }在上面的示例中,userName 字段定义了 GroupA 和 GroupB 两个分组校验规则。GroupA 的校验规则为年龄在 20~30,GroupB 的校验规则为年龄在 30~40。
最后,使用校验分组:
@RequestMapping("/save") public String save(@RequestBody @Validated({GroupA.class,Default.class}) Person person, BindingResult result){ System.out.println(JSON.toJSONString(result.getAllErrors())); return "success"; }在上面的示例中,在 @Validated 注解中增加了 {GroupA.class,Default.class} 参数,表示对于定义了分组校验的字段使用 GroupA 校验规则,其他字段使用默认规则。