springboot 参数校验详解
https://www.jianshu.com/p/89a675b7c900
在日常开发写rest接口时,接口参数校验这一部分是必须的,但是如果全部用代码去做,显得十分麻烦,spring也提供了这部分功能,本文来探究一下如何实现
1.配置
spring-boot-starter-web包自动依赖hibernate-validator,不用再重复引入,直接开搞
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.3.1.Final</version>
</dependency>
声明一个bean注册到spring容器,这个bean是一个容器后处理器,会把校验的逻辑通过AOP织入有@Validated注解的class,具体可以看这个类的源码
这一步在springboot其实也不用做,ValidationAutoConfiguration这个配置类自动帮我们做了
@Bean
public MethodValidationPostProcessor methodValidationPostProcessor(){
return new MethodValidationPostProcessor();
}
验证不通过会产生异常,因为我们项目提供rest接口,所以通过全局捕获异常,然后转换为json给前台
@ControllerAdvice
public class GlobalExceptionHandler {
/**
* 用来处理bean validation异常
* @param ex
* @return
*/
@ExceptionHandler(ConstraintViolationException.class)
@ResponseBody
public WebResult resolveConstraintViolationException(ConstraintViolationException ex){
WebResult errorWebResult = new WebResult(WebResult.FAILED);
Set<ConstraintViolation<?>> constraintViolations = ex.getConstraintViolations();
if(!CollectionUtils.isEmpty(constraintViolations)){
StringBuilder msgBuilder = new StringBuilder();
for(ConstraintViolation constraintViolation :constraintViolations){
msgBuilder.append(constraintViolation.getMessage()).append(",");
}
String errorMessage = msgBuilder.toString();
if(errorMessage.length()>1){
errorMessage = errorMessage.substring(0,errorMessage.length()-1);
}
errorWebResult.setInfo(errorMessage);
return errorWebResult;
}
errorWebResult.setInfo(ex.getMessage());
return errorWebResult;
}
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseBody
public WebResult resolveMethodArgumentNotValidException(MethodArgumentNotValidException ex){
WebResult errorWebResult = new WebResult(WebResult.FAILED);
List<ObjectError> objectErrors = ex.getBindingResult().getAllErrors();
if(!CollectionUtils.isEmpty(objectErrors)) {
StringBuilder msgBuilder = new StringBuilder();
for (ObjectError objectError : objectErrors) {
msgBuilder.append(objectError.getDefaultMessage()).append(",");
}
String errorMessage = msgBuilder.toString();
if (errorMessage.length() > 1) {
errorMessage = errorMessage.substring(0, errorMessage.length() - 1);
}
errorWebResult.setInfo(errorMessage);
return errorWebResult;
}
errorWebResult.setInfo(ex.getMessage());
return errorWebResult;
}
}
这两个异常分别对应校验的两种使用方式
- 在方法里面校验
- 在bean对象里面校验
经过测试,以上两种形式的数据验证不仅仅对controller层有用,在service层也行,只要这个类在spring ioc容器里面
2.使用
2.1常用校验注解
@AssertFalse 校验false
@AssertTrue 校验true
@DecimalMax(value=,inclusive=) 小于等于value,
inclusive=true,是小于等于
@DecimalMin(value=,inclusive=) 与上类似
@Max(value=) 小于等于value
@Min(value=) 大于等于value
@NotNull 检查Null
@Past 检查日期
@Pattern(regex=,flag=) 正则
@Size(min=, max=) 字符串,集合,map限制大小
@Valid 对po实体类进行校验
2.2在方法参数上使用
@Controller
@Validated
public class ValidationController {
@GetMapping("/validate1")
@ResponseBody
public String validate1(
@Size(min = 1,max = 10,message = "姓名长度必须为1到10")@RequestParam("name") String name,
@Min(value = 10,message = "年龄最小为10")@Max(value = 100,message = "年龄最大为100") @RequestParam("age") Integer age,
@Future @RequestParam("birth")@DateTimeFormat(pattern = "yyyy-MM-dd hh:mm:ss") Date birth){
return "validate1";
}
}
注意类名需要加注解@Validated
校验失败会抛出ConstraintViolationException异常
然后我们在全局异常捕获类捕获这个异常,返回给前台对应的错误json
2.3在bean内属性上使用
给model类增加校验注解
public class User {
@Size(min = 1,max = 10,message = "姓名长度必须为1到10")
private String name;
@NotEmpty
private String firstName;
@Min(value = 10,message = "年龄最小为10")@Max(value = 100,message = "年龄最大为100")
private Integer age;
@Future
@JSONField(format="yyyy-MM-dd HH:mm:ss")
private Date birth;
...getter setter
}
在controller对应User实体前增加@Valid注解
@PostMapping("/validate2")
@ResponseBody
public User validate2(@Valid @RequestBody User user){
return user;
}
3.扩展
除了默认提供的校验注解外,我们可以定义自己的校验注解
3.1.创建约束注解类
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = { HandsomeBoyValidator.class})
public @interface HandsomeBoy {
String message() default "盛超杰最帅";
String name();
Class<?>[] groups() default { };
Class<? extends Payload>[] payload() default {};
}
注意:message用于显示错误信息这个字段是必须的,groups和payload也是必须的
@Constraint(validatedBy = { HandsomeBoyValidator.class})用来指定处理这个注解逻辑的类
一开始写了这个自定义注解和验证类,发现没有生效,最后发现是@Constraint这个注解里的类没有配置,还跟了很多源码,蛋疼,总的来讲,这个配置还是挺方便的
3.2.创建验证器类
public class HandsomeBoyValidator implements ConstraintValidator<HandsomeBoy, User> {
private String name;
/**
* 用于初始化注解上的值到这个validator
* @param constraintAnnotation
*/
@Override
public void initialize(HandsomeBoy constraintAnnotation) {
name =constraintAnnotation.name();
}
/**
* 具体的校验逻辑
* @param value
* @param context
* @return
*/
@Override
public boolean isValid(User value, ConstraintValidatorContext context) {
return name ==null || name.equals(value.getName());
}
}
这边的功能是user类里面的name字段必须和配置的一样,否则输出一个事实
3.3. 测试
@PostMapping("/validate3")
@ResponseBody
public User validate3(@Valid @HandsomeBoy(name = "scj",message = "盛超杰第二帅") @RequestBody User user){
return user;
}
如果验证不通过,会输出盛超杰第二帅,全局异常处理器不要忘记配置
4.demo源码下载
小礼物走一走,来简书关注我
springboot 参数校验详解的更多相关文章
- 补习系列(4)-springboot 参数校验详解
目录 目标 一.PathVariable 校验 二.方法参数校验 三.表单对象校验 四.RequestBody 校验 五.自定义校验规则 六.异常拦截器 参考文档 目标 对于几种常见的入参方式,了解如 ...
- SpringBoot Validation参数校验 详解自定义注解规则和分组校验
前言 Hibernate Validator 是 Bean Validation 的参考实现 .Hibernate Validator 提供了 JSR 303 规范中所有内置 constraint 的 ...
- Springboot mini - Solon详解(六)- Solon的校验框架使用、定制与扩展
Springboot min -Solon 详解系列文章: Springboot mini - Solon详解(一)- 快速入门 Springboot mini - Solon详解(二)- Solon ...
- Spring全家桶——SpringBoot之AOP详解
Spring全家桶--SpringBoot之AOP详解 面向方面编程(AOP)通过提供另一种思考程序结构的方式来补充面向对象编程(OOP). OOP中模块化的关键单元是类,而在AOP中,模块化单元是方 ...
- Springboot mini - Solon详解(三)- Solon的web开发
Springboot min -Solon 详解系列文章: Springboot mini - Solon详解(一)- 快速入门 Springboot mini - Solon详解(二)- Solon ...
- Springboot mini - Solon详解(七)- Solon Ioc 的注解对比Spring及JSR330
Springboot min -Solon 详解系列文章: Springboot mini - Solon详解(一)- 快速入门 Springboot mini - Solon详解(二)- Solon ...
- SpringBoot之DispatcherServlet详解及源码解析
在使用SpringBoot之后,我们表面上已经无法直接看到DispatcherServlet的使用了.本篇文章,带大家从最初DispatcherServlet的使用开始到SpringBoot源码中Di ...
- SpringBoot Profile使用详解及配置源码解析
在实践的过程中我们经常会遇到不同的环境需要不同配置文件的情况,如果每换一个环境重新修改配置文件或重新打包一次会比较麻烦,Spring Boot为此提供了Profile配置来解决此问题. Profile ...
- Springboot mini - Solon详解(二)- Solon的核心
Springboot min -Solon 详解系列文章: Springboot mini - Solon详解(一)- 快速入门 Springboot mini - Solon详解(二)- Solon ...
随机推荐
- scrollspy.js--bug
/** * 20140505 14.33 ycx * scrollspy.js中存在的bug!!!---为什么ui.tabs必须在scrollspy.js中的window.onload之前执行,也就是 ...
- 【转】 Pro Android学习笔记(四七):Dialog(4):一些补充和思考
目录(?)[-] 编程思想封装接口 fragment和activity以其他fragment之间的通信 编程思想:封装接口 在小例子中,fragment会调用activity的onDialogDone ...
- 【转】Pro Android学习笔记(三六):Fragment(1):基本概念
目录(?)[-] 为何引入Fragment 大小屏幕的适配 横屏竖屏切换 返回键 什么是Fragment 为何引入Fragment 我们之前的Activity都是都是全屏处理较为简单的单一事务功能,适 ...
- linux-java环境安装以及ssh
1 下载Java8 http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html 2 使用 ...
- 树莓派 Learning 002 装机后的必要操作 --- 07 设置静态IP地址
树莓派 装机后的必要操作 之 设置静态IP地址 我的树莓派型号:Raspberry Pi 2 Model B V1.1 装机系统:NOOBS v1.9.2 为了避免IP变来变去,我们将IP地址设置为静 ...
- unreal3控制台窗口属性调整
在windows平台上,unreal3的console窗口类是FOutputDeviceConsoleWindows 启动时,它可以从XXXGame.ini中读取诸如窗口大小之类的属性,具体的代码在 ...
- R: which(查询位置)、%in% (是否存在)、ifelse(判断是否):
################################################### 问题:ifelse.which.%in% 18.4.27 解决方案: > x < ...
- p1640&bzoj1854 连续攻击游戏(游戏)
传送门(洛谷) 传送门(bzoj) 题目 lxhgww最近迷上了一款游戏,在游戏里,他拥有很多的装备,每种装备都有2个属性,这些属性的值用[1,10000]之间的数表示.当他使用某种装备时,他只能使用 ...
- 阶段2-新手上路\项目-移动物体监控系统\Sprint2-摄像头子系统开发\第2节-V4L2图像编程接口深度学习
参考资料: http://www.cnblogs.com/emouse/archive/2013/03/04/2943243.htmlhttp://blog.csdn.net/eastmoon5021 ...
- C#中读写自定义的web 配置文件
开发程序的过程中,有时候我们需要自己编写一个config文件,比如取名App.config, 然后写一些配置信息在里面.然后我们需要编写C#代码来对这个配置文件进行读写 比如:App.Config & ...