Spring Boot参数校验
1. 概述
作为接口服务提供方,非常有必要在项目中加入参数校验,比如字段非空,字段长度限制,邮箱格式验证等等,数据校验常用到概念:
JSR303/JSR-349: JSR303是一项标准,只提供规范不提供实现,规定一些校验规范即校验注解,如@Null,@NotNull,@Pattern,位于javax.validation.constraints包下。JSR-349是其的升级版本,添加了一些新特性。
hibernate validation:hibernate validation是对这个规范的实现,并增加了一些其他校验注解,如@Email,@Length,@Range等等
spring validation:spring validation对hibernate validation进行了二次封装,在springmvc模块中添加了自动校验,并将校验信息封装进了特定的类中,能够通过BindingResult类在Controller层的处理方法中取得错误信息
如何校验
引入Maven依赖
在pom.xml中加入maven依赖, validation-api, hibernate-validator
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.1.0.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.4.0.Final</version>
</dependency>
spring-boot-starter-web已经依赖了validation-api和hibernate-validator,所以引入spring-boot-starter-web之后就不需要引入这两个依赖了。

Model上加JSR-303注解类型
空检查:
@Null 验证对象是否为null
@NotNull 验证对象是否不为null, 无法查检长度为0的字符串
@NotBlank 检查约束字符串是不是Null还有被Trim的长度是否大于0,只对字符串,且会去掉前后空格.
@NotEmpty 检查约束元素是否为NULL或者是EMPTY.
Booelan检查:
@AssertTrue 验证 Boolean 对象是否为 true
@AssertFalse 验证 Boolean 对象是否为 false
长度检查:
@Size(min=, max=) 验证对象(Array,Collection,Map,String)长度是否在给定的范围之内
@Length(min=, max=) Validates that the annotated string is between min and max included.
日期检查:
@Past 验证 Date 和 Calendar 对象是否在当前时间之前
@Future 验证 Date 和 Calendar 对象是否在当前时间之后
数值检查:
建议使用在Stirng,Integer类型,不建议使用在int类型上,因为表单值为“”时无法转换为int,但可以转换为Stirng为”“,Integer为null
@Min 验证 Number 和 String 对象是否大等于指定的值
@Max 验证 Number 和 String 对象是否小等于指定的值
@DecimalMax 被标注的值必须不大于约束中指定的最大值. 这个约束的参数是一个通过BigDecimal定义的最大值的字符串表示.小数存在精度
@DecimalMin 被标注的值必须不小于约束中指定的最小值. 这个约束的参数是一个通过BigDecimal定义的最小值的字符串表示.小数存在精度
@Digits 验证 Number 和 String 的构成是否合法
@Digits(integer=,fraction=) 验证字符串是否是符合指定格式的数字,interger指定整数精度,fraction指定小数精度。
@Range(min=, max=) Checks whether the annotated value lies between (inclusive) the specified minimum and maximum.
@Range(min=10000,max=50000,message=”range.bean.wage”)
private BigDecimal wage;
@Valid 递归的对关联对象进行校验, 如果关联对象是个集合或者数组,那么对其中的元素进行递归校验,如果是一个map,则对其中的值部分进行校验.(是否进行递归验证)
@CreditCardNumber信用卡验证
@Email 验证是否是邮件地址,如果为null,不进行验证,算通过验证。
@ScriptAssert(lang= ,script=, alias=)
@URL(protocol=,host=, port=,regexp=, flags=)
@Pattern 验证 String 对象是否符合正则表达式的规则
hibernate validator校验demo
先来看一个简单的demo,添加了Validator的注解:
package com.winner.model;
import org.hibernate.validator.constraints.Length;
import javax.validation.Valid;
import javax.validation.constraints.AssertFalse;
import javax.validation.constraints.DecimalMin;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import java.math.BigDecimal;
import java.util.List;
/**
* @author winner_0715
* @description:
* @date 2018/12/5
*/
public class ParamRo {
@NotBlank(message = "userName不允许为空")
@Length(min = 2, max = 5, message = "userName长度必须在{min}-{max}之间")
private String userName;
@NotBlank(message="年龄不能为空")
@Pattern(regexp="^[0-9]{1,2}$",message="年龄不正确")
private String userAge;
@NotNull(message = "price不允许为空")
@DecimalMin(value = "15.5", message = "价格不能低于 {value}")
private BigDecimal price;
@AssertFalse(message = "必须为false")
private Boolean isFalse;
/**
* 如果是空,则不校验,如果不为空,则校验
*/
@Pattern(regexp="^[0-9]{4}-[0-9]{2}-[0-9]{2}$",message="出生日期格式不正确")
private String birthday;
/**
* 注意这里必须加@Valid注解
*/
@Valid
private List<ParamItem> list;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public BigDecimal getPrice() {
return price;
}
public void setPrice(BigDecimal price) {
this.price = price;
}
public String getUserAge() {
return userAge;
}
public void setUserAge(String userAge) {
this.userAge = userAge;
}
public Boolean getFalse() {
return isFalse;
}
public void setFalse(Boolean aFalse) {
isFalse = aFalse;
}
public String getBirthday() {
return birthday;
}
public void setBirthday(String birthday) {
this.birthday = birthday;
}
public List<ParamItem> getList() {
return list;
}
public void setList(List<ParamItem> list) {
this.list = list;
}
}
POST接口验证,验证不通过的结果在全局处理器中处理,略
@RequestMapping(value = "/param/validate/post", method = RequestMethod.POST)
public ResultBean paramValidationPost(@Valid @RequestBody ParamRo ro) {
return ResultBeanUtils.success(ro);
}
http://localhost:8080/param/validate/post,请求参数如下
{
"userName": "zhangsan",
"userAge":"1000",
"price": 25.6,
"isFalse":true,
"birthday":"1990-09-09",
"list": [
{
"address": "beijing"
}
]
}
响应结果
{
"success": false,
"msg": "年龄不正确;address长度必须在2-5之间;userName长度必须在2-5之间;",
"data": null,
"errorCode": 0
}
参数验证非常方便,字段上注解+验证不通过提示信息即可代替手写一大堆的非空和字段限制验证代码。
hibernate的校验模式
上面例子中一次性返回了所有验证不通过的集合,通常按顺序验证到第一个字段不符合验证要求时,就可以直接拒绝请求了。
Hibernate Validator有以下两种验证模式:
普通模式
普通模式(会校验完所有的属性,然后返回所有的验证失败信息)
快速失败返回
快速失败返回模式(只要有一个验证失败,则返回)
两种验证模式配置方式:
failFast:true 快速失败返回模式 false 普通模式
ValidatorFactory validatorFactory = Validation.byProvider( HibernateValidator.class )
.configure()
.failFast( true )
.buildValidatorFactory();
Validator validator = validatorFactory.getValidator();
和 (hibernate.validator.fail_fast:true 快速失败返回模式 false 普通模式)
ValidatorFactory validatorFactory = Validation.byProvider( HibernateValidator.class )
.configure()
.addProperty( "hibernate.validator.fail_fast", "true" )
.buildValidatorFactory();
Validator validator = validatorFactory.getValidator();
配置hibernate Validator为快速失败返回模式:
package com.winner.validate;
import org.hibernate.validator.HibernateValidator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
@Configuration
public class ValidatorConfiguration {
@Bean
public Validator validator(){
ValidatorFactory validatorFactory = Validation.byProvider( HibernateValidator.class )
.configure()
.addProperty( "hibernate.validator.fail_fast", "true" )
.buildValidatorFactory();
Validator validator = validatorFactory.getValidator();
return validator;
}
}
此时相同的输入,输出变成
{
"success": false,
"msg": "年龄不正确;",
"data": null,
"errorCode": 0
}
即快速失败
GET参数校验(@RequestParam参数校验)
使用校验bean的方式,没有办法校验RequestParam的内容,一般在处理Get请求(或参数比较少)的时候,会使用下面这样的代码:
@RequestMapping(value = "/param/validate/get/2", method = RequestMethod.GET)
public ResultBean paramValidationGet2(@RequestParam String name,
@RequestParam String address) {
return ResultBeanUtils.success(name + address);
}
使用@Valid注解,对RequestParam对应的参数进行注解,是无效的,需要使用@Validated注解来使得验证生效。如下所示:
a.此时需要使用MethodValidationPostProcessor 的Bean:
package com.winner.validate;
import org.hibernate.validator.HibernateValidator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.validation.beanvalidation.MethodValidationPostProcessor;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
@Configuration
public class ValidatorConfiguration {
@Bean
public Validator validator(){
ValidatorFactory validatorFactory = Validation.byProvider( HibernateValidator.class )
.configure()
.addProperty( "hibernate.validator.fail_fast", "true" )
.buildValidatorFactory();
Validator validator = validatorFactory.getValidator();
return validator;
}
//@Bean
//public MethodValidationPostProcessor methodValidationPostProcessor() {
// /**默认是普通模式,会返回所有的验证不通过信息集合*/
// return new MethodValidationPostProcessor();
//}
@Bean
public MethodValidationPostProcessor methodValidationPostProcessor() {
MethodValidationPostProcessor postProcessor = new MethodValidationPostProcessor();
/**设置validator模式为快速失败返回*/
postProcessor.setValidator(validator());
return postProcessor;
}
}
b.方法所在的Controller上加注解@Validated
package com.winner.web;
import com.winner.model.ParamRo;
import com.winner.model.ResultBean;
import com.winner.util.ResultBeanUtils;
import org.hibernate.validator.constraints.Length;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
/**
* @author winner_0715
* @description:
* @date 2018/12/5
*/
@RestController
@Validated
public class HelloController {
@RequestMapping(value = "/param/validate/get/2", method = RequestMethod.GET)
public ResultBean paramValidationGet2(
@NotBlank(message = "name不允许为空")
@Length(min = 2, max = 5, message = "name长度必须在{min}-{max}之间")
@RequestParam String name,
@Min(value = 18, message = "年龄必须大于18")
@RequestParam int age) {
return ResultBeanUtils.success(name + age);
}
}
c.返回验证信息提示
验证不通过时,抛出了ConstraintViolationException异常,使用同一捕获异常处理:略
d.验证
http://localhost:8080/param/validate/get/2?name=zhangsan&age=16
快速失败模式结果
{
"success": false,
"msg": "name长度必须在2-5之间;",
"data": null,
"errorCode": 0
}
默认模式结果
{
"success": false,
"msg": "name长度必须在2-5之间;年龄必须大于18;",
"data": null,
"errorCode": 0
}
对象级联校验
对象内部包含另一个对象作为属性,属性上加@Valid,可以验证作为属性的对象内部的验证:(验证Demo2示例时,可以验证Demo2的字段)
@Data
public class Demo2 {
@Size(min = 3,max = 5,message = "list的Size在[3,5]")
private List<String> list;
@NotNull
@Valid
private Demo3 demo3;
}
@Data
public class Demo3 {
@Length(min = 5, max = 17, message = "length长度在[5,17]之间")
private String extField;
}
参考:
https://www.cnblogs.com/mr-yang-localhost/p/7812038.html
Spring Boot参数校验的更多相关文章
- Spring Boot 参数校验
1.背景介绍 开发过程中,后台的参数校验是必不可少的,所以经常会看到类似下面这样的代码 这样写并没有什么错,还挺工整的,只是看起来不是很优雅而已. 接下来,用Validation来改写这段 2.Spr ...
- Validated 注解完成 Spring Boot 参数校验
1. @Valid 和 @Validated @Valid 注解,是 Bean Validation 所定义,可以添加在普通方法.构造方法.方法参数.方法返回.成员变量上,表示它们需要进行约束校验. ...
- spring boot输入数据校验(validation)
Spring Boot 集成教程 Spring Boot 介绍 Spring Boot 开发环境搭建(Eclipse) Spring Boot Hello World (restful接口)例子 sp ...
- spring boot 参数传递(spring boot 参数传数 arg0 每一个参数 arg0#{arg0},arg1 #{arg1})
spring boot 参数传数 arg0 每一个参数 arg0#{arg0},arg1 #{arg1} @Select("select * from sys_user where nam ...
- Spring Boot (一) 校验表单重复提交
一.前言 在某些情况下,由于网速慢,用户操作有误(连续点击两下提交按钮),页面卡顿等原因,可能会出现表单数据重复提交造成数据库保存多条重复数据. 存在如上问题可以交给前端解决,判断多长时间内不能再次点 ...
- 59. Spring Boot Validator校验【从零开始学Spring Boot】
大纲: (1) 入门例子: (2) 国际化: (3) 在代码中添加错误信息: (1) 入门例子: Validator主要是校验用户提交的数据的合理性的,比如是否为空了,密码长度是否大于6位,是否是纯数 ...
- spring mvc参数校验
一.在SringMVC中使用 使用注解 1.准备校验时使用的JAR validation-api-1.0.0.GA.jar:JDK的接口: hibernate-validator-4.2.0.Fina ...
- spring boot参数验证
必须要知道 简述 JSR303/JSR-349,hibernate validation,spring validation 之间的关系 JSR303 是一项标准,JSR-349 是其的升级版本,添加 ...
- Spring boot validation校验
使用 Hibernate validator 的步骤:1. 在 Pojo 类的字段上, 加上 Hibernate validator 注解2. 在Controller 函数的形参前加上 @Valid ...
随机推荐
- XXE (XML External Entity Injection) 外部实体注入漏洞案例分析
ENTITY 实体 在一个甚至多个XML文档中频繁使用某一条数据,我们可以预先定义一个这条数据的“别名”,即一个ENTITY,然后在这些文档中需要该数据的地方调用它. XML定义了两种类型的ENTIT ...
- DataFrames和Kudu
Kudu为Kudu表提供了一个自定义的原生数据源.可以和DataFrame API紧密集成: 使用DataFrame的好处就是可以从很多的数据源创建dataframe,包括现有的RDD,Hive表或S ...
- 线程、进程、协程 异步io
https://www.cnblogs.com/wupeiqi/articles/6229292.html
- jenkins(1): jenkins安装以及从gitlab拉取代码
1. gitlab前面已经写过了,自己去参考 https://www.cnblogs.com/yitianyouyitian/p/9214940.html 2. jenkins安装 2.1 jdk 安 ...
- Java中String直接赋字符串和new String的区别(面试常考)
摘取自:https://www.cnblogs.com/guozhenqiang/p/5633269.html 解析Java中的String对象的数据类型 1. String是一个对象. 因为对象的 ...
- Python交互图表可视化Bokeh:4. 折线图| 面积图
折线图与面积图 ① 单线图.多线图② 面积图.堆叠面积图 1. 折线图--单线图 import numpy as np import pandas as pd import matplotlib.py ...
- Linux 常用基本指令
1.ls 参数: -a:列出所有目录(“.”开头的是隐藏文件) -l: 以长格式列出目录下的内容列表 2.cd cd 切换到家目录 cd ~ 切换到家目录 cd .. 切换到上一级目录 3.pwd ...
- BZOJ 4260 Codechef REBXOR (区间异或和最值) (01字典树+DP)
<题目链接> 题目大意:给定一个序列,现在求出两段不相交的区间异或和的最大值. 解题分析: 区间异或问题首先想到01字典树.利用前缀.后缀建树,并且利用异或的性质,相同的两个数异或变成0, ...
- Emoji表情编解码库XXL-EMOJI
<Emoji表情编解码库XXL-EMOJI> 一.简介 1.1 概述 XXL-EMOJI 是一个灵活可扩展的Emoji表情编解码库,可快速实现Emoji表情的编解码. 1.2 特性 1.简 ...
- CLR Via第一 章 知识点整理(3)CLR执行程序集的IL代码
在了解CLR运行之前让我们先简单了解一下IL 除了编译器编译的IL代码,IL也是一种汇编语言,也就是说我们可以直接编写IL代码,当然也有对应的IL编译器,值得一提的是对于面向CLR的其他语言,CLR只 ...