前言
之前也用过hibernate的校验注解,但是没有去做一个总结,这里参考一篇博客去做一个总结。简述JSR303/JSR-349,hibernate validation,spring validation之间的关系。JSR303是一项标准,JSR-349是其的升级版本,添加了一些新特性,他们规定一些校验规范即校验注解,如@Null,@NotNull,@Pattern,他们位于javax.validation.constraints包下,只提供规范不提供实现。而hibernate validation是对这个规范的实践(不要将hibernate和数据库orm框架联系在一起),他提供了相应的实现,并增加了一些其他校验注解,如@Email,@Length,@Range等等,他们位于org.hibernate.validator.constraints包下。而万能的spring为了给开发者提供便捷,对hibernate validation进行了二次封装,显示校验validated bean时,你可以使用spring validation或者hibernate validation,而spring validation另一个特性,便是其在springmvc模块中添加了自动校验,并将校验信息封装进了特定的类中。这无疑便捷了我们的web开发。本文主要介绍在springmvc中自动校验的机制。
引入依赖
因为我们构建的是spring boot项目,所以直接引入web的starter的依赖即可。
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
如果查看其子依赖,可以发现如下的依赖:
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
进行校验
校验的实体类
这里用了lombok的@Data注解,也是非常推荐大家使用的一个插件。
@Data
public class ValidateBO {
@NotBlank(message = "name不能为空")
private String name;
@Min(value = 18, message = "年龄不能小于18岁")
private Integer age;
@Email(message = "email格式错误")
private String email;
/**
* 自定义注解 不能包含空格字符串
*/
@CannotHaveBlank
private String blank;
/**
* 正则校验
*/
@Pattern(regexp = "^1(3|4|5|7|8)\\d{9}$", message = "手机号码格式错误")
private String phone;
}
可以看到这里用到了一些常见的注解。(自定义校验注解在下边会提到)
controller进行校验
在controller中进行这个字段的校验,可以看到每个需要校验的对象,都需要一个BindingResult去承接校验的结果,并且也要对要校验的类去加上@Validated注解。
@GetMapping(value = "/validate")
public String validate(ValidateBO validateBO, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
StringBuilder stringBuilder = new StringBuilder();
for (String s : bindingResult.getFieldErrors().stream()
.map(FieldError::getDefaultMessage).collect(Collectors.toList())) {
stringBuilder.append(s);
}
return stringBuilder.toString();
}
return "success";
}
启动项目,在url中输入对项目进行debug。
可以看到,校验在碰到第一个字段不符合要求之后,并不是直接返回错误,而是会对所有的要校验字段去校验。当然这个也是可以配置的,下边会提到fast-fail的配置。最后返回的结果: