前置知识
先了解一下JSR、Hibernate Validator、Spring Validation:
- JSR(Java Specification Request)规范是Java EE 6中的一项子规范,也叫作Bean Validation。它指定了一整套基于bean的验证API,通过标注给对象属性添加约束条件
- Hibernate Validator是对JSR规范的实现,并增加了一些其他校验注解,如@Email、@Length、@Range等。
- Spring Validation是Spring为了给开发者提供便捷,对Hibernate Validator进行了二次封装。
JSR定义了数据验证规范,而Hibernate Validator则是基于JSR规范,实现了各种数据验证的注解以及一些附加的约束注解。Spring Validation则是对Hibernate Validator的封装整合。
Spring Boot是从Spring发展而来的,所以自然支持Hibernate Validator和Spring Validation两种方式,默认使用的是Hibernate Validator组件。
案例
post请求参数较多时,可以在对应的数据模型(Java Bean)中进行数据校验,通过注解来指定字段校验的规则。
1、添加依赖
添加如下maven依赖:
<!-- 参数校验-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
2、定义数据模型
定义一个接收数据的数据模型(javabean),使用注解的形式描述字段校验的规则。下面以PostTag_form对象为例:
/**
* <p>
* 接收前端提交的表单数据
* </p>
*
* @author 轻率的保罗
* @since 2022-12-17
*/
@Getter
@Setter
@Accessors(chain = true)
@ApiModel(value = "标签form对象", description = "前端提交的表单数据")
public class PostTag_form implements Serializable {
@ApiModelProperty(value = "标签名",required = true)
@NotBlank(message = "标签名称不能为空!")
@Length(max = 20,message = "标签名称长度不合法,应大于0、小于等于20!")
private String tagName;
@ApiModelProperty(value = "创建者ID",required = true)
// @NotBlank(message = "创建者ID不能为空!")
@Length(min = 5,max = 25,message = "创建者ID长度不合法,应大于等于5、小于等于25!")//包含了 @NotBlank 的情况
private String userId;
}
注解@NotBlank,表示该字段必填(该字符串不能为空)。
注解中的属性message是数据校验不通过时要给出的提示信息。
3、应用
在controller中应用:
post请求中,@RequestBody PostTag_form form
接收前端所提交的数据。在@RequestBody注解后面添加了@Valid注解
,然后在后面添加了BindingResult返回验证结果
,BindingResult是验证不通过时的结果集合。
@ApiOperation(value = "新增标签",notes = "创建成功,则返回新创建标签的ID")
@PostMapping
public DataVo addTag(@RequestBody @Valid PostTag_form form, BindingResult result){
//参数校验
if(result.hasErrors()) {
return JSONResult.errorMap(result);
}
//参数校验通过,再调用service的addTag方法处理请求
return tagService.addTag(form);
}
注意,BindingResult必须跟在被校验参数之后,若被校验参数之后没有BindingResult对象,则会抛出BindException。
方法 JSONResult.errorMap(BindingResult result) 如下:
/**
* 异常 代码501
* 参数异常,map中放具体的异常参数(key/value)。例如 email = 邮箱格式不正确!
* @param result springboot参数校验(validation),返回BindingResult对象。
*/
public static DataVo errorMap(BindingResult result) {
HashMap<String, String> errMap = new HashMap<>(result.getFieldErrors().size());
for (FieldError error : result.getFieldErrors()) {
//示例: "tagName": "不能为空"
//error.getCode() 可获取校验不通过的注解,即@NotBlank 还是 @Length
errMap.put(error.getField(),error.getDefaultMessage());
}
return new DataVo(501, "参数异常!详情见data!", errMap);
}
4、测试
4.1提交空数据
请求参数如下:
{
"tagName": "",//长度0
"userId": ""//长度0
}
响应内容:
{
"code": 501,
"msg": "参数异常!详情见data!",
"data": {
"tagName": "标签名称不能为空!",
"userId": "创建者ID长度不合法,应大于等于5、小于等于25!"
}
}
4.2提交错误数据(超长度)
请求参数如下:
{
"tagName": "123451234512345123451",//长度21
"userId": "1234"//长度4
}
响应内容:
{
"code": 501,
"msg": "参数异常!详情见data!",
"data": {
"tagName": "标签名称长度不合法,应大于0、小于等于20!",
"userId": "创建者ID长度不合法,应大于等于5、小于等于25!"
}
}
常用注解
所有的注解都包含code和message这两个属性(见前边的代码result.getFieldErrors())。Message定义数据校验不通过时的错误提示信息。code定义错误的类型。
扩展
@NotNull、@NotEmpty、@NotBlank区别:
-
1、@NotNull
- 不能为 null,但可以为 empty,**一般用在 int、long、double、BigDecimal等数值类型 **的非空校验上,而且被其标注的字段可以使用 @size、@Max、@Min 对字段数值进行大小的控制
- @Range 一般用在 数值 类型上可对字段数值进行大小范围的控制。
-
2、@NotEmpty
- 不能为 null,且长度必须大于 0,一般用在 集合 类上或者 数组 上
-
3、@NotBlank
- 只能作用在接收的 String 类型上,不能为 null,而且调用 trim() 后,长度必须大于 0即:必须有实际字符
- @Length 一般用在 String 类型上可对字段数值进行最大长度限制的控制。
案例2
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方法
}
说明
本博客中的案例,使用的maven依赖如下:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<!-- 启用web支持-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 参数校验-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<!-- 启用lombok(lombok 与 日志@Slf4j)-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- 启用单元测试-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- mybatis-plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.2</version>
</dependency>