在 RESTful 的接口服务中,存在各种各样的请求参数。在跳入业务处理环节之前,通常会有一个基础的数据验证的机制,待验证通过,结果无误后,请求参数才会传递到正式的业务处理中。

maven 依赖引入

  Spring Boot项目中,Validation校验需要引入的两个包:

     <dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.16.Final</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>

如何使用javax.validation @Valid注解

  Hibernate-Validator的主要使用方式是在Controller的请求参数加@Valid 注解,并且是“零配置”的,无需配置也可以使用。 @Valid 注解表示需要对这个对象的属性进行验证:

public String saveUser(@RequestBody **@Valid** User user) {...}

  既然是属性验证,那么就肯定会有验证结果,验证结果可以通过在请求参数那直接添加一个BindingResult变量来获取。在 User类的属性上打上如下注解:

import org.hibernate.validator.constraints.Length;
import javax.validation.constraints.NotBlank; /**
* @author Wiener
* @since 2021/11/7
*/
@Data
public class User {
@NotBlank(
message = "姓名不能为空"
)
@Length(
message = "姓名最长为 {max}个字符"
, min = 1
, max = 20
)
private String name; @NotBlank(
message = "密码不能为空"
)
@Length(
message = "密码最少为{min}个字符,最长为 {max}个字符"
, min = 8
, max = 30
)
private String password; /** 年龄 */
@NotNull(message = "请输入年龄")
@Range(message = "年龄大小范围为 {min} 到 {max} 之间", min = 1, max = 150)
public Integer age;
@NotBlank
@Size(max=32,message="address is null")
private String address; /**
* 当前时间不能为空(必填)
*/
@NotBlank(message="当前时间不能为空")
@DateTimeStr(format ="yyyy-MM-dd HH:mm:ss", message = "格式错误,正确格式为:yyyy-MM-dd HH:mm:ss")
private String currentTime; }

  当输入不能满足条件时,就会抛出异常,而后统一由异常中心处理。也可以用BindingResult,但是用了这个后就必须手动处理异常,侵入了正常的业务逻辑,并不推荐。

常用注解

  这儿介绍Hibernate和 javax.validation 包下的一些常用校验注解。

@Null

限制只能为null

@NotNull

限制必须不为null

@AssertFalse

限制必须为false

@AssertTrue

限制必须为true

@DecimalMax(value)

限制必须为一个不大于指定值的数字

@DecimalMin(value)

限制必须为一个不小于指定值的数字

@Digits(integer,fraction)

限制必须为一个小数,且整数部分的位数不能超过integer,小数部分的位数不能超过fraction

@Future

限制必须是一个将来的日期

@Max(value)

限制必须为一个不大于指定值的数字

@Min(value)

限制必须为一个不小于指定值的数字

@Past

限制必须是一个过去的日期

@Pattern(value)

限制必须符合指定的正则表达式

@Size(max,min)

限制字符串长度必须在min到max之间

@Past

验证注解的元素值(日期类型)比当前时间早

@NotEmpty

验证注解的元素值不为null且不为空(字符串长度不为0、集合大小不为0)

@NotBlank

验证注解的元素值不为空(不为null、去除首位空格后长度为0),不同于@NotEmpty,@NotBlank只应用于字符串且在比较时会去除字符串的空格

@Email

验证注解的元素值是Email,也可以通过正则表达式和flag指定自定义的email格式

嵌套实体验证和测试用例

  温馨提示:实体类验证只是针对该实体内第一层的属性进行验证,如果被验证的实体类存在另一个实体类B,那么就需要在B类成员变量上加 @valid 注解。如在Student类中添加班级CurrentTimeDto类型的成员变量并校验其属性:

import lombok.Data;
import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.Range; import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
import java.io.Serializable; @Data
public class Student implements Serializable {
private static final long serialVersionUID = 5285725868010678653L; @NotNull(
message = "姓名不能为空"
)
@Length(
message = "姓名最长为 {max}个字符"
, min = 1
, max = 20
)
private String name; @NotNull(
message = "密码不能为空"
)
@Length(
message = "密码最少为{min}个字符,最长为 {max}个字符"
, min = 8
, max = 30
)
private String password; /** 年龄 */
@NotNull(message = "请输入年龄")
@Range(message = "年龄大小范围为 {min} 到 {max} 之间", min = 1, max = 150)
public Integer age;
@NotNull(message = "请输入address")
@Size(max=32,message="address is null")
private String address; @Pattern(regexp = "\\d{3}-\\d{8}|\\d{4}-\\d{7}|\\d{11}", message = "手机号码不正确")
private String telephone; @Valid
private CurrentTimeDto currentTimeDto;
}
import lombok.Data;

import javax.validation.constraints.NotBlank;
import java.io.Serializable; @Data
public class CurrentTimeDto implements Serializable { private static final long serialVersionUID = -7831097421296635187L;
/**
* 当前时间不能为空(必填)
*/
//设置时区为上海时区,时间格式自己据需求定。
// @JsonFormat(pattern="yyyy-MM-dd",timezone = "GMT+8") @NotBlank(message="当前时间不能为空")
private String currentTime;
}

  下面是两个基于Student类的测试用例,在请求参数前加上 @Valid注解即开启参数校验:

   /**
* 参数校验结果从bindingResult中读取
* @param student
* @param bindingResult
* @return
*/
@ApiOperation(value = "bindingResult")
@PostMapping("/bindingResult")
public Object bindingResult(@RequestBody @Valid Student student, BindingResult bindingResult) {
System.out.println("bindingResult---" + student);
if (bindingResult.getErrorCount() > 0) {
return bindingResult.getFieldError();
}
return student;
}
/**
* 参数校验结果仅仅可以从日志中查看
* @param student
* @return
*/
@ApiOperation(value = "validParam")
@PostMapping("/validParam")
public Object validParam(@RequestBody @Valid Student student) {
System.out.println("validParam---" + student);
return student;
}

小结

  愿各位新时代农民工不断打破自己,提升自己,重塑自己,从而让自己的职业和生活更加璀璨。

javax.validation @Valid注解实现参数校验的更多相关文章

  1. spring注解式参数校验

    很痛苦遇到大量的参数进行校验,在业务中还要抛出异常或者返回异常时的校验信息,在代码中相当冗长,今天我们就来学习spring注解式参数校验. 其实就是:hibernate的validator. 开始啦. ...

  2. spring boot中使用javax.validation以及org.hibernate.validator校验入参

    这里springboot用的版本是:<version>2.1.1.RELEASE</version> 自带了hibernate.validator,所以不用添加额外依赖 1.创 ...

  3. SpringBoot Validation优雅的全局参数校验

    前言 我们都知道在平时写controller时候,都需要对请求参数进行后端校验,一般我们可能会这样写 public String add(UserVO userVO) { if(userVO.getA ...

  4. spring注解式参数校验列表

    校验注释列表: @AssertFalse Boolean,boolean 验证注解的元素值是false @AssertTrue Boolean,boolean 验证注解的元素值是true @NotNu ...

  5. 转 spring注解式参数校验

    转自: https://blog.csdn.net/jinzhencs/article/details/51682830 转自: https://blog.csdn.net/zalan01408980 ...

  6. @Valid注解的使用springmvc pojo校验

    @Valid注解用于校验,所属包为:javax.validation.Valid. ① 首先需要在实体类的相应字段上添加用于充当校验条件的注解,如:@Min,如下代码(age属于User类中的属性): ...

  7. 【Java】使用@Valid+BindingResult进行controller参数校验

    @Valid @Valid注解用于校验,所属的包: javax.validation.Valid. 你可以定义实体,在实体的属性上添加校验规则,在API接收数据时添加@Valid注解,这时你的实体将会 ...

  8. Spring Validation最佳实践及其实现原理,参数校验没那么简单!

    之前也写过一篇关于Spring Validation使用的文章,不过自我感觉还是浮于表面,本次打算彻底搞懂Spring Validation.本文会详细介绍Spring Validation各种场景下 ...

  9. Validated 注解完成 Spring Boot 参数校验

    1.  @Valid 和 @Validated @Valid 注解,是 Bean Validation 所定义,可以添加在普通方法.构造方法.方法参数.方法返回.成员变量上,表示它们需要进行约束校验. ...

  10. 利用 Bean Validation 来简化接口请求参数校验

    团队新来了个校招实习生静静,相互交流后发现竟然是我母校同实验室的小学妹,小学妹很热情地认下了我这个失散多年的大湿哥,后来... 小学妹:大湿哥,咱们项目里的 Controller 怎么都看不到参数校验 ...

随机推荐

  1. 面试题53 - I. 在排序数组中查找数字 I

    地址:https://leetcode-cn.com/problems/zai-pai-xu-shu-zu-zhong-cha-zhao-shu-zi-lcof/ <?php /** 面试题53 ...

  2. 如何编写正确高效的Dockerfile

    Dockerfile是什么 Dockerfile 非常普通,它就是一个纯文本,里面记录了一系列的构建指令,比如选择基础镜像.拷贝文件.运行脚本等等,RUN, COPY, ADD指令都会生成一个 Lay ...

  3. Laravel 配置连接多个数据库以及如何使用

    目录 配置连接 配置 .env 文件 配置 \config\database.php 文件 使用 Schema Query Eloquent 配置连接 配置 .env 文件 /* 这部分是默认的数据库 ...

  4. 什么是swagger,一篇带你入门

    一.前言 在前后端分离开发的过程中,前端和后端需要进行api对接进行交互,就需要一个api规范文档,方便前后端的交互,但api文档不能根据代码的变化发生实时动态的改变,这样后端修改了接口,前端不能及时 ...

  5. 【单片机】滑稽AT89C52表情实现

    [单片机]滑稽AT89C52表情实现 零.原因 在群里看到了这样一个表情: 这是用51做的,刚好开发板上有8个小灯,想实现一下. 一.代码 新建工程,写入如下代码: #include<reg52 ...

  6. docker container 启动异常

    场景重现 阿里云ECS下新安装的CoreOS 1465.8.0 64-bit,没做过其他任何操作,直接执行以下命令出现异常: docker pull hello-world docker run -i ...

  7. 2. RabbitMQ 的详细安装步骤(两种方式,第一种:yum 安装;第二种:docker 容器安装)

    2. RabbitMQ 的详细安装步骤(两种方式,第一种:yum 安装:第二种:docker 容器安装) @ 目录 2. RabbitMQ 的详细安装步骤(两种方式,第一种:yum 安装:第二种:do ...

  8. zk源码—3.单机和集群通信原理

    大纲 1.单机版的zk服务端的启动过程 (1)预启动阶段 (2)初始化阶段 2.集群版的zk服务端的启动过程 (1)预启动阶段 (2)初始化阶段 (3)Leader选举阶段 (4)Leader和Fol ...

  9. 2025dsfz-KMP学习笔记

    KMP 前言:这把高端局 关于KMP 时间复杂度为 \(O(n+m)\) 的优秀字符串查找算法. 适用于在句子/文章中查找一段文字(词语). KMP实现 关于共同前后缀数组(PMT) 说人话就是 \( ...

  10. php 设置友好时间

    public static function formatTime($time){ if (is_int($time)) { $time = intval($time); } elseif ($tim ...