Spring实现Controller中方法参数校验
目录
- 前言
- `Controller` 中方法参数校验示例
- 使用 `@Valid` 或 `@Validated` 注解
- `Maven` 依赖
- 实体类字段加上相关注解
- `Controller` 方法参数加上 `@Valid` 或 `@Validated` 注解
- 单个参数校验
- 多个参数校验
- 接口测试
- 参数合法结果
- `name` 字段为空的结果
- 年龄不合法的结果
- `@Validated` 注解特有的功能
- 参数分组校验
- 分组接口(空接口)
- 实体类
- `Controller` 控制类
- 参数分组校验测试
- 新增时传入参数 `id`
- 更新时不传入参数 `id`
- 嵌套校验
- 实体类
- `Controller` 控制类
- 嵌套校验测试
- `Teacher` 和 `Student` 都校验不通过
- `Student` 都校验不通过
- 控制分组校验顺序
- 手动校验
- 使用 `Hibernate Validation` 提供 `Validator`
- 使用 `Spring Validation` 的 `Validator`
- 参数校验常用注解
前言
数据的校验是网站一个不可或缺的功能,前端的 js
校验可以涵盖大部分的校验职责,如用户名唯一性,生日格式,邮箱格式校验等等常用的校验。但是为了避免用户绕过浏览器,使用 http
工具直接向后端请求一些违法数据,服务端的数据校验也是必要的
Controller
中方法参数校验示例
使用 @Valid
或 @Validated
注解
Maven
依赖
@Valid
:新版本的springBoot
需要手动引入下面的依赖,老版本只需引入spring-boot-starter-web
即可,里面集成了Hibernate-Validator
<dependency><groupId>org.hibernate.validator</groupId><artifactId>hibernate-validator</artifactId><version>6.0.13.Final</version>
</dependency>
@Validated
:是对hibernate-validator
的封装,是spring
提供的校验机制,只要引入spring-context
依赖即可
实体类字段加上相关注解
public class User implements Serializable {@NotBlank(message = "姓名不能为空")private String name;@NotNull(message = "年龄不能为空")@Range(min = 0, max = 200, message = "年龄不合法")private Integer age;public User(String name, Integer age) {this.name = name;this.age = age;}// setter,getter 方法省略......
}
@NotBlank
:只用于字符串,字符串不能为null
,并且去除两端空白字符后的长度大于0
,例:""
," "
@NotEmpty
:只用于字符串、集合、map
、数组,且不能为null
,并且长度或者大小大于1
@NotNull
:适用于所有类型,且不能为null
@AssertTrue
:被注释的元素必须为true
@AssertFalse
:被注释的元素必须为false
@Min(value)
:被注释的元素必须是一个数字,其值必须大于等于指定的最小值@Max(value)
:被注释的元素必须是一个数字,其值必须小于等于指定的最大值@Size(max,min)
:被注释的元素的大小必须在指定的范围内@Email
:被注释的元素必须是电子邮件地址@Length
:被注释的字符串的大小必须在指定的范围内@Range
:被注释的元素必须在合适的范围内
Controller
方法参数加上 @Valid
或 @Validated
注解
单个参数校验
@Controller
public class UserController {@RequestMapping(path = "validatorUser", method = RequestMethod.POST)@ResponseBodypublic ResponseResult validatorUser(@Valid User user, BindingResult bindingResult) {if (bindingResult.hasErrors()) {// 用于获取相应字段上添加的 message 中的内容String message = bindingResult.getFieldError().getDefaultMessage();return new ResponseResult(500, message, null);}return new ResponseResult(200, "成功", user);}
}
多个参数校验
public Objet test(@Validated Object param1, BindingResult result1 ,@Validated Object param2, BindingResult Result2) {// ......
}
接口测试
参数合法结果
name
字段为空的结果
年龄不合法的结果
@Validated
注解特有的功能
@Valid
不具备的功能,而注解 @Validated
注解特有的功能。源码分别如下
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Validated {Class<?>[] value() default {};
}@Target({ METHOD, FIELD, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RUNTIME)
@Documented
public @interface Valid {}
参数分组校验
当一个实体类需要多种验证方式时,例如:对于一个实体类的 id
来说,新增的时候是不需要的,对于更新时是必须的。可以通过 groups
对验证进行分组
分组接口(空接口)
通过向 groups
分配不同类的 class
对象,达到分组目的
public interface UserServiceInsert {}public interface UserServiceUpdate {}
实体类
public class UserInfo implements Serializable {@Null(message = "新增时id必须为空", groups = {UserServiceInsert.class})@NotNull(message = "更新时id不能为空", groups = {UserServiceUpdate.class})private Integer id;@NotBlank(message = "姓名不能为空")private String name;@NotNull(message = "年龄不能为空")@Range(min = 0, max = 200, message = "年龄不合法")private Integer age;public UserInfo(Integer id, String name, Integer age) {this.id = id;this.name = name;this.age = age;}// setter,getter 方法省略......
}
Controller
控制类
@Controller
public class UserController {@RequestMapping(path = "insertUser", method = RequestMethod.POST)@ResponseBodypublic ResponseResult insertUser(@Validated(value = UserServiceInsert.class) UserInfo userInfo, @NotNull BindingResult bindingResult) {if (bindingResult.hasErrors()) {String message = bindingResult.getFieldError().getDefaultMessage();return new ResponseResult(500, message, null);}return new ResponseResult(200, "成功", userInfo);}@RequestMapping(path = "updateUser", method = RequestMethod.POST)@ResponseBodypublic ResponseResult updateUser(@Validated(value = UserServiceUpdate.class) UserInfo userInfo, @NotNull BindingResult bindingResult) {if (bindingResult.hasErrors()) {String message = bindingResult.getFieldError().getDefaultMessage();return new ResponseResult(500, message, null);}return new ResponseResult(200, "成功", userInfo);}
}
参数分组校验测试
新增时传入参数 id
更新时不传入参数 id
@Validated
添加了groups
属性时,其只会校验实体分组的属性。如只会校验UserInfo
中的id
属性,而不会校验name,age
属性
嵌套校验
@Valid
加在方法参数时,不会自动进行嵌套验证,而是用在需要嵌套验证类内的相应字段上,来配合方法参数上 @Validated
或 @Valid
来进行嵌套验证
实体类
public class Teacher implements Serializable {@NotEmpty(message = "Teacher 姓名不能为空")private String teacher_name;@NotNull(message = "Teacher 年龄不能为空")@Range(min = 0, max = 200, message = "Teacher 年龄不合法")private Integer teacher_age;@Valid@Size(min = 1, max = 10, message = "列表中的元素数量为1~10")private List<Student> students;public Teacher(String teacher_name, Integer teacher_age, List<Student> students) {this.teacher_name = teacher_name;this.teacher_age = teacher_age;this.students = students;}// setter,getter 方法省略......
}public class Student implements Serializable {@Valid@NotEmpty(message = "Student 姓名不能为空")private String name;@Valid@NotNull(message = "Student 年龄不能为空")@Range(min = 0, max = 200, message = "Student 年龄不合法")private Integer age;public Student(String name, Integer age) {this.age = age;this.name = name;}// setter,getter 方法省略......
}
Controller
控制类
@Controller
public class UserController {@RequestMapping(path = "nestValid", method = RequestMethod.POST)@ResponseBodypublic ResponseResult nestValid(@Validated @RequestBody Teacher teacher, @NotNull BindingResult bindingResult) {if (bindingResult.hasErrors()) {String message = bindingResult.getFieldError().getDefaultMessage();return new ResponseResult(500, message, null);}return new ResponseResult(200, "成功", teacher);}
}
嵌套校验测试
Teacher
和 Student
都校验不通过
Student
都校验不通过
控制分组校验顺序
@GroupSequence
它是 JSR
标准提供的注解,可以按指定的分组先后顺序进行验证;前面的分组校验不通过,后面的分组校验就不执行
- 如:
@GroupSequence({One.class, Two.class, Three.class})
先执行One
分组校验,然后执行Two
分组校验。如果One
分组校验失败了,则不会进行Two
分组的校验。即必须第一个组校验正确了,才执行第二组校验
控制分组校验顺序示例:https://blog.csdn.net/qq877728715/article/details/113795082
手动校验
在某些场景下需要我们手动校验 bean
,用校验器对需要被校验的 bean
发起 validate
获得校验结果
- 既可以使用
Hibernate Validation
提供Validator
,也可以使用Spring Validation
的Validator
使用 Hibernate Validation
提供 Validator
public class ValidationTest {public static void main(String[] args) {Foo foo = new Foo();foo.setUsername(null);foo.setPassword(null);foo.setUserType("");// 构建ValidatorValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();Validator validator = validatorFactory.getValidator();// 使用Validator校验beanSet<ConstraintViolation<Foo>> set = validator.validate(foo);for (ConstraintViolation<Foo> constraintViolation : set) {System.out.println(constraintViolation.getMessage());}}@Datapublic static class Foo {@NotNull(message = "username不能为空")private String username;@NotNull(message = "password不能为空")private String password;@NotBlank(message = "userType不能为空")private String userType;}
}
使用 Spring Validation
的 Validator
@Component
@Configuration
public class GlobalWebConfig {@Beanpublic Validator validator() {return new LocalValidatorFactoryBean();}
}
如果使用 springBoot
,LocalValidatorFactoryBean
已经成为了 Validator
的默认实现,使用时只需要自动注入即可
@Autowired
Validator globalValidator;
参数校验常用注解
注解 | 说明 |
---|---|
@Null
|
限制只能为null |
@NotNull
|
限制必须不为null |
@NotEmpty
|
验证注解的元素值不为null且不为空 (字符串长度不为0、集合大小不为0 )(主要用于:String,Collection,Map,array)
|
@NotBlank
|
只支持字符串类型字段,验证注解的元素值不为空 (不为null、去除首位空格后长度为0 ),不同于@NotEmpty,@NotBlank只应用于字符串,且在比较时会去除字符串的空格
|
@Pattern(value)
|
限制必须符合指定的正则表达式 |
@Size(max,min)
|
限制字符长度必须在min到max之间,(主要用于: String, Collection, Map and array) |
@Range(min, max)
|
被注释的元素必须在合适的范围内 (主要用于 : BigDecimal, BigInteger, String, byte, short, int, long ,原始类型的包装类 ) |
@Length(min, max)
|
被注解的对象必须是字符串,大小必须在制定的范围内 |
@DecimalMax(value) | 限制必须为一个不大于指定值的数字 |
@DecimalMin(value) | 限制必须为一个不小于指定值的数字 |
@Max(value)
|
限制必须为一个不大于指定值的数字 |
@Min(value)
|
限制必须为一个不小于指定值的数字 |
@Digits(integer,fraction) | 限制必须为一个小数,且整数部分的位数不能超过integer,小数部分的位数不能超过fraction |
@AssertFalse | 限制必须为false |
@AssertTrue | 限制必须为true |
@Future | 限制必须是一个将来的日期 |
@Past | 验证注解的元素值(日期类型)比当前时间早 |
@Email
|
验证注解的元素值是Email,也可以通过正则表达式和flag指定自定义的email格式 |
Spring实现Controller中方法参数校验相关推荐
- java注解返回不同消息,Spring MVC Controller中的一个读入和返回都是JSON的方法如何获取javax.validation注解的异常信息...
Spring MVC Controller中的一个读入和返回都是JSON的方法怎么获取javax.validation注解的错误信息? 本帖最后由 LonelyCoder2012 于 2014-03- ...
- 使用 Spring Validation 优雅地进行参数校验
引言 不知道大家平时的业务开发过程中 controller 层的参数校验都是怎么写的?是否也存在下面这样的直接判断? public String add(UserVO userVO) {if(user ...
- 头信息_如何在 Spring REST Controller 中获取 HTTP 头信息
介绍 在本篇文章中,我们将研究如何在 Spring Rest Controller 中访问 HTTP 头信息. 首先,我们将使用 @RequestHeader 注解分别或同时读取 HTTP 头信息. ...
- python @classmethod 和 @staticmethod区别,以及类中方法参数cls和self的区别
一.@classmethod 和 @staticmethod 1.staticmethod 作用:让类中的方法变成一个普通函数(普通函数没有绑定在任何一个特定的类或者实例上.所以与不需要对象实例化就可 ...
- Java中方法参数的传递
Java中方法参数的传递: 众所周知,Java语言中只有值传递,看起来很好理解的一句话,那么来看一个例子: 输出结果: 这是一个经典问题,我想说说自己的理解: 首先,变量sa和sb分别包含一个字符串对 ...
- numpy中方法参数axis取值理解
numpy中方法参数axis取值理解 首先不要使用什么横纵轴去理解,因为时间长了就忘记了,而且如果a是一个三维数组就没法解释了. axis等于0时,在shape中表示的是二维数组.那么np.amin( ...
- 中value大小_如何在Spring/SpringBoot 中做参数校验?你需要了解的都在这里!
数据的校验的重要性就不用说了,即使在前端对数据进行校验的情况下,我们还是要对传入后端的数据再进行一遍校验,避免用户绕过浏览器直接通过一些 HTTP 工具直接向后端请求一些违法数据. 本文结合自己在项目 ...
- 面试官 | 如何在 Spring Boot 中进行参数校验?
作者 | 狂乱的贵公子 来源 | cnblogs.com/cjsblog/p/8946768.html 开发过程中,后台的参数校验是必不可少的,所以经常会看到类似下面这样的代码 这样写并没有什么错,还 ...
- Springboot中请求参数校验
1.添加依赖 <!-- 参数校验 --> <dependency><groupId>org.springframework.boot</groupId> ...
- Spring MVC Controller中返回json数据中文乱码处理
问题 在使用spring MVC Controller的过程中,发现返回到客户端的的中文出现乱码.后台Java代码: @RequestMapping(value = "/upload&quo ...
最新文章
- 【驱动】内核打印级别设置
- “人脸识别”是一柄双刃剑 如何趋利避害?
- 大脑简史(2)-研究大脑的手段
- servlet config 初始化参数
- ROS Indigo下安装测试Xtion Pro
- linux条件表达式例子,Linux的Iptables命令的基本知识(三)-常用匹配条件示例和执行动作...
- 你认为手机会取代个人电脑吗?
- 求正整数N(N1)的质因数的个数,相同的质因数需要重复计算(java)
- linux文件测试操作
- PHP学习总结(4)——PHP入门篇之PHP计算表达式
- linux-unit1
- PHP专家陪练营试听课程下载
- 网络通讯协议——TCP/IP协议
- 世界各国1960年到2020年gdp数据抓取
- 自定义IDM的网页嗅探下载浮条样式
- 因为涉嫌歧视女性被开除的那位工程师到底在备忘录上写了什么?
- 万众瞩目--腾讯云数据库TDSQL第一届征文正式大赛开启
- 家装产业的数字化,正在成为越来越多人的新共识
- matlab中magy是什么意思,MATLAB入门基本知识——音频处理
- python 手机自动化交易股票_通达信转python,机智股票自动交易手机版