Spring Boot2 系列教程 (十五) | 服务端参数校验之一
估计很多朋友都认为参数校验是客户端的职责,不关服务端的事。其实这是错误的,学过 Web 安全的都知道,客户端的验证只是第一道关卡。它的参数验证并不是安全的,一旦被有心人抓到可乘之机,他就可以有各种方法来摸拟系统的 Http 请求,访问数据库的关键数据。轻则导致服务器宕机,重则泄露数据。所以,这时就需要设置第二道关卡,服务端验证了。
老项目的服务端校验
@RestController
@RequestMapping("/student")
public class ValidateOneController {
@GetMapping("/id")
public Student findStudentById(Integer id){
if(id == null){
logger.error("id 不能为空!");
throw new NullPointerException("id 不能为空");
}
return studentService.findStudentById(id);
}
}
看以上代码,就一个的校验就如此麻烦。那我们是否有好的统一校验方法呢?鉴于 SpringBoot 无所不能。答案当然是有的。
其中,Bean Validator 和 Hibernate Validator 就是两套用于验证的框架,二者都遵循 JSR-303 ,可以混着用,鉴于二者的某些 Validator 注解有差别,例如 @Length 在 Bean Validator 中是没有的,所以这里我选择混合用。
JSR-303
JSR-303 是JAVA EE 6 中的一项子规范,叫做 Bean Validation,Hibernate Validator 是 Bean Validation 的参考实现, Hibernate Validator 提供了 JSR 303 规范中所有内置 Constraint(约束) 的实现,除此之外还有一些附加的 Constraint 。这些 Constraint (约束) 全都通过注解的方式实现,请看下面两个表。
Bean Validation 中内置的约束:
| 注解 | 作用 |
|---|---|
| @Null | 被注解参数必须为空 |
| @NotNull | 被注解参数不能为空 |
| @AssertTrue | 被注解参数必须为 True |
| @AssertFalse | 被注解参数必须为 False |
| @Min(value) | 被注解参数必须是数字,且其值必须大于等于 value |
| @Max(value) | 被注解参数必须是数字,且其值必须小于等于 value |
| @DecimaMin(value) | 被注解参数必须是数字,且其值必须大于等于 value |
| @DecimaMax(value) | 被注解参数必须是数字,且其值必须小于等于 value |
| @Size(max, min) | 被注解参数大小必须在指定范围内 |
| @Past | 被注解参数必须是一个过去的日期 |
| @Future | 被注解参数必须是一个将来的日期 |
| @Pattern(value) | 被注解参数必须符合指定的正则表达式 |
| @Digits(integer, fraction) | 被注解参数必须是数字,且其值必须在可接受范围内 |
| @NotBlank | 被注解参数的值不为空(不为 null、去除首位空格后长度为 0),不同于 @NotEmpty,@NotBlank 只应用于字符串且在比较时会去除字符串的空格 |
Hibernate Validator 附加的约束:
| 注解 | 作用 |
|---|---|
| @NotEmpty | 被注解参数的值不为 null 且不为空(字符串长度不为0、集合大小不为0) |
| 被注解参数必须是电子邮箱地址 | |
| @Length | 被注解的字符串长度必须在指定范围内 |
| @Range | 被注解的参数必须在指定范围内 |
准备工作
- SpringBoot 2.1.3
- IDEA
- JDK8
Pom 文件依赖
<!-- web 启动类 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- test 单元测试类 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- lombok 依赖用于简化 bean -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
实体类
用于测试,加入了参数校验规则。
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
private Integer id;
@NotBlank(message = "学生名字不能为空")
@Length(min = 2, max = 10, message = "name 长度必须在 {min} - {max} 之间")
private String name;
@NotNull(message = "年龄不允许为空")
@Min(value = 0, message = "年龄不能低于 {value} 岁")
private Integer age;
}
Controller 层
写了两个方法,一个用于校验普通参数,一个用于校验对象
@Validated //开启数据校验,添加在类上用于校验方法,添加在方法参数中用于校验参数对象。(添加在方法上无效)
@RestController
@RequestMapping("/student")
public class ValidateOneController {
/**
* 普通参数校验
* @param name
* @return
*/
@GetMapping("/name")
public String findStudentByName(@NotBlank(message = "学生名字不能为空")
@Length(min = 2, max = 10, message = "name 长度必须在 {min} - {max} 之间")String name){
return "success";
}
/**
* 对象校验
* @param student
* @return
*/
@PostMapping("/add")
public String addStudent(@Validated @RequestBody Student student){
return "success";
}
}
Postman 测试
校验普通参数测试结果:
下图可以看见,我没有在 http://localhost:8080/student/name 地址后添加 name 参数,传到后台马上就校验出异常了。而这个异常信息就是我定义的校验异常信息。

校验对象测试结果:

结果有点长:
下图可以看见,我访问 http://localhost:8080/student/add 传入了参数对象,但对象是不能通过校验规则的,比如 age 参数为负数,name 参数长度太大,传到后台马上就校验出异常了。而这个异常信息就是我定义的校验异常信息。

完整代码
https://github.com/turoDog/Demo/tree/master/springboot_validateone_demo
如果觉得对你有帮助,请给个 Star 再走呗,非常感谢。
最后
如果看到这里,说明你喜欢这篇文章,请转发、点赞。微信搜索「一个优秀的废人」,关注后回复「1024」送你一套完整的 java 教程。
Spring Boot2 系列教程 (十五) | 服务端参数校验之一的更多相关文章
- Spring Boot2 系列教程(十五)定义系统启动任务的两种方式
在 Servlet/Jsp 项目中,如果涉及到系统任务,例如在项目启动阶段要做一些数据初始化操作,这些操作有一个共同的特点,只在项目启动时进行,以后都不再执行,这里,容易想到web基础中的三大组件( ...
- Spring Boot2 系列教程(十)Spring Boot 整合 Freemarker
今天来聊聊 Spring Boot 整合 Freemarker. Freemarker 简介 这是一个相当老牌的开源的免费的模版引擎.通过 Freemarker 模版,我们可以将数据渲染成 HTML ...
- Spring Boot2 系列教程(十四)CORS 解决跨域问题
今天和小伙伴们来聊一聊通过CORS解决跨域问题. 同源策略 很多人对跨域有一种误解,以为这是前端的事,和后端没关系,其实不是这样的,说到跨域,就不得不说说浏览器的同源策略. 同源策略是由 Netsca ...
- Spring Boot2 系列教程 (十六) | 整合 WebSocket 实现广播
前言 如题,今天介绍的是 SpringBoot 整合 WebSocket 实现广播消息. 什么是 WebSocket ? WebSocket 为浏览器和服务器提供了双工异步通信的功能,即浏览器可以向服 ...
- Spring Boot2 系列教程(十二)@ControllerAdvice 的三种使用场景
严格来说,本文并不算是 Spring Boot 中的知识点,但是很多学过 SpringMVC 的小伙伴,对于 @ControllerAdvice 却并不熟悉,Spring Boot 和 SpringM ...
- Spring Boot2 系列教程(十六)定时任务的两种实现方式
在 Spring + SpringMVC 环境中,一般来说,要实现定时任务,我们有两中方案,一种是使用 Spring 自带的定时任务处理器 @Scheduled 注解,另一种就是使用第三方框架 Qua ...
- Spring Boot2 系列教程(十八)Spring Boot 中自定义 SpringMVC 配置
用过 Spring Boot 的小伙伴都知道,我们只需要在项目中引入 spring-boot-starter-web 依赖,SpringMVC 的一整套东西就会自动给我们配置好,但是,真实的项目环境比 ...
- Spring Boot2 系列教程(十九)Spring Boot 整合 JdbcTemplate
在 Java 领域,数据持久化有几个常见的方案,有 Spring 自带的 JdbcTemplate .有 MyBatis,还有 JPA,在这些方案中,最简单的就是 Spring 自带的 JdbcTem ...
- Spring Boot2 系列教程 (十八) | 整合 MongoDB
微信公众号:一个优秀的废人.如有问题,请后台留言,反正我也不会听. 前言 如题,今天介绍下 SpringBoot 是如何整合 MongoDB 的. MongoDB 简介 MongoDB 是由 C++ ...
随机推荐
- java框架之shiro
#shiro简介 一.简介 Apache Shiro 是一个强大而灵活的开源安全框架,可以用于应用程序的身份验证,授权,会话管理和加密. Authentication:有时也简称为“登录”,这是一个证 ...
- pycharm解析器找不到
pycharm每个项目都需要设定解释器位置吧,把自己解释器位置添加到项目设置就好了 先装python,再装pycharm,不然找不到解析器的,解析器其实就是python.exe.
- Python 3里,reduce()函数已经被从全局名字空间里移除了,它现在被放置在fucntools模块里
reduce函数:在Python 3里,reduce()函数已经被从全局名字空间里移除了,它现在被放置在fucntools模块里 用的话要 先引入:>>> from functool ...
- maven环境隔离
pom <build>节点下增加节点 <resources> <resource> <directory> src/main/resources.${d ...
- thinkphp3.2如何自动生成后台模块并且怎么访问
https://blog.csdn.net/whulovely/article/details/72773729 步骤一:在入口文件index.php下绑定Admin模块(这时候别再Home同级手动创 ...
- ASP.NET MVC 实现页落网资源分享网站+充值管理+后台管理(14)之会员中心管理
源码下载地址:http://www.yealuo.com/Sccnn/Detail?KeyValue=c891ffae-7441-4afb-9a75-c5fe000e3d1c 会员中心,主要包含了会员 ...
- H3C STP基本配置
- linux ioctl 接口
大部分驱动需要 -- 除了读写设备的能力 -- 通过设备驱动进行各种硬件控制的能力. 大 部分设备可进行超出简单的数据传输之外的操作; 用户空间必须常常能够请求, 例如, 设 备锁上它的门, 弹出它的 ...
- Qt4.5 QFrame(相当于Delphi里的TPanel,有各种凹凸方式)
QFrame类是有框架的窗口部件的基类. QPopupMenu使用这个来把菜单“升高”,高于周围屏幕.QProgressBar有“凹陷”的外观.QLabel有平坦的外观.这些有框架的窗口部件可以被改变 ...
- 清晰架构(Clean Architecture)的Go微服务: 设计原则
我最近写了一个Go微服务应用程序,这个程序的设计来自三个灵感: 清晰架构"Clean Architecture"¹ and SOLID (面向对象设计)² 设计 原则³ Sprin ...