数据校验-springboot

时间:2022-12-20 17:52:48

前置知识

先了解一下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!"
  }
}

常用注解

数据校验-springboot

所有的注解都包含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>


笔记摘自:CSDN-故屿γ《Spring Boot从入门到实战》-章为忠