【工具】JSR-303后端参数校验框架的使用方法及说明

文章目录

  • 【工具】JSR-303后端参数校验框架的使用方法及说明
    • 1. 统一校验需求
    • 2. 使用说明
      • 2.1 引入依赖
      • 2.2 规则说明
      • 2.3 使用说明
      • 2.4 分组校验
      • 2.5 定制校验规则注解

1. 统一校验需求

有一句话是这样说的——“前端防君子,后端防小人”。这句话说明参数的校验在前端和后端都是十分重要的。不懂技术的人一般在前端页面无法找到系统的漏洞,但是懂技术又不怀好意的人如果获取到了你后端接口的地址,而恰好你后端又没有对参数进行校验,那么就很有可能会被他人乘虚而入,对系统造成很大的影响。为了避免这一情况的发生,所有我们需要在后端也进行参数的校验。

那么我们又有一个问题了,参数校验的代码是写在Controller层还是写在Service层呢?

对于一般的参数,我们应该是放在Controller层中进行校验,而对于业务逻辑的校验则在Service层中进行。Contoller中校验请求参数的合法性,包括:必填项校验,数据格式校验,比如:是否是符合一定的日期格式,等。Service中要校验的是业务规则相关的内容,比如:已存在的用户不能重复新增。

早在JavaEE6规范中就定义了参数校验的规范,它就是 JSR-303,它定义了Bean Validation,即对bean属性进行校验。

SpringBoot提供了JSR-303的支持,它就是 spring-boot-starter-validation,它的底层使用Hibernate Validator,Hibernate Validator是Bean Validation 的参考实现。

所以,我们准备在Controller层使用spring-boot-starter-validation完成对请求参数的基本合法性进行校验。


2. 使用说明

2.1 引入依赖

我们在项目的pom文件中添加如下依赖:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId>
</dependency>

2.2 规则说明

上面引入的依赖为我们提供了很多的注解,注解的使用规则如下:

了解了使用的规则之后我们就可以开始使用了。


2.3 使用说明

1)场景描述

设定一个场景,我们需要添加一门课程,前端传入一系列的参数,我们后端使用dto去接收这些参数。同时我们还需要在Controller校验这些参数是否合法。

首先设定dto类代码如下所示:

@Data
public class AddCourseDto {@NotEmpty(message = "课程名称不能为空")private String name;@NotEmpty(message = "适用人群不能为空")@Size(message = "适用人群内容过少",min = 10)private String users;@NotEmpty(message = "课程分类不能为空")private String mt;@NotEmpty(message = "课程分类不能为空")private String st;@NotEmpty(message = "课程等级不能为空")private String grade;@NotEmpty(message = "收费规则不能为空")private String charge;
}

我们在这个dto中用到了两个校验注解 @NotEmpty@Size ,注解含义如上图所示。


2)定义接口

我们已经定义好了dto,然后我们需要在接口层对dto进行校验,校验的方法也很简单,只需要在接口的参数列表中添加一个 @Validated 注解。接口代码如下所示:

@PostMapping("/course")
public CourseBaseInfoDto createCourseBase(@RequestBody @Validated AddCourseDto addCourseDto){//...return courseBaseInfoService.createCourseBase(companyId,addCourseDto);
}

如果传入的参数中有不合规范的,Spring会抛出一个 MethodArgumentNotValidException 异常,我们需要在统一异常处理器中捕获异常,解析出异常信息。


3)编写异常处理逻辑

我们在统一异常处理器中对异常进行捕获,编写异常处理逻辑:

@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)//状态码返回500
public RestErrorResponse doMethodArgumentNotValidException(MethodArgumentNotValidException e) {BindingResult bindingResult = e.getBindingResult();//校验的错误信息List<FieldError> fieldErrors = bindingResult.getFieldErrors();//收集错误StringBuffer errors = new StringBuffer();fieldErrors.forEach(error -> {errors.append(error.getDefaultMessage()).append(",");});//将错误信息以json的形式返回return new RestErrorResponse(errors.toString());
}

我们使用httpcilent今昔测试,我们将name属性的值设为空。

POST {{content_host}}/course
Content-Type: application/json{"mt": "1-1","st": "1-1-1","name": "","pic": "","teachmode": "200002","users": "初级人员","tags": "标签","grade": "204001","description": "","charge": "201001","price": 10,"originalPrice":100,"qq": "123","wechat": "123","phone": "123","validDays": 365
}

进行测试:

返回信息:

这时发现,参数校验已经生效了。但是我们这又会引发出另一个问题。那就是:

假如我们有两个接口的参数都包含了相同的dto,我们都需要对其进行校验,但是这两个接口对dto的校验规则又不一样,比如第一个接口要求dto的name属性不能为空,第二个接口却要求dto的name属性可以为空。那我们怎么办呢?我们是再创建一个和dto完全相同的类去重新编写校验规则吗?当然不是,Spring为我们提供了更好的解决方案——“分组校验”。


2.4 分组校验

有时候再同一个属性上设置一个校验规则并不能满足所有要求。

比如:订单编号由系统生成,在添加订单时要求订单编号为空,在更新订单时要求订单编写不能为空。此时就用到了分组校验,同一个属性定义多个校验规则属于不同的分组,比如:添加订单定义@NULL规则属于insert分组,更新订单定义@NotEmpty规则属于update分组,insert和update是分组的名称,是可以修改的。

1)分组

我们用class类型来表示不同的分组,所以我们定义不同的接口类型(空接口)表示不同的分组。代码如下所示:

public class ValidationGroups {public interface Inster{};public interface Update{};public interface Delete{};}

2)指定分组

在dto中定义校验规则是指定分组,比如上面的name属性,我们可以为其指定两个分组。

@NotEmpty(groups = {ValidationGroups.Inster.class},message = "添加课程名称不能为空")
@NotEmpty(groups = {ValidationGroups.Update.class},message = "修改课程名称不能为空")
// @NotEmpty(message = "课程名称不能为空")private String name;

3)接口层引用分组

在Controller方法中启动校验规则指定要使用的分组名:

@PostMapping("/course")
public CourseBaseInfoDto createCourseBase(@RequestBody @Validated({ValidationGroups.Inster.class}) AddCourseDto addCourseDto){//。。。return courseBaseInfoService.createCourseBase(companyId,addCourseDto);
}

再次测试,由于这里指定了Insert分组,所以抛出 异常信息:添加课程名称不能为空。

如果修改分组为ValidationGroups.Update.class,异常信息为:修改课程名称不能为空。


2.5 定制校验规则注解

如果javax.validation.constraints包下的校验规则满足不了需求怎么办?

我们有两种方法:

  1. 手写校验代码。
  2. 自定义校验规则注解。

自定义校验规则注解的方法可以查看:自定义校验注解

【工具】JSR-303后端参数校验框架的使用方法及说明相关推荐

  1. java validate校验_自定义工具类实现validate参数校验

    前言 相信项目中做一些htttp接口,避免不了要对参数进行校验,大多数情况下,其实我们只是校验是否为NULL就可以了 1.通过注解实现各种状态的字段 1.1.引入依赖 默认的版本是6.0.9.Fina ...

  2. JSR 303 - Bean Validation 简介及使用方法

    前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家.点击跳转到教程. 一.JSR-303简介 JSR-303 是 JAVA EE 6 中的一项子规范,叫做 Bean Va ...

  3. java校验参数防止攻击_程序员写接口参数校验,总是太多if else?一招让你避免体力活...

    对于写Java的程序员来说,不管是写单纯的接口.还是页面后台一把梭,后端参数校验的功能都是整个代码不可或缺的一部分,它可以从系统入口过滤掉一些不合法的数据,以确保我们的系统稳定. 还记得我刚入行Jav ...

  4. SpringBoot 如何进行参数校验,老鸟们都这么玩的!

    大家好,我是飘渺. 前几天写了一篇 SpringBoot如何统一后端返回格式?老鸟们都是这样玩的! 阅读效果还不错,而且被很多号主都转载过,今天我们继续第二篇,来聊聊在SprinBoot中如何集成参数 ...

  5. JSR 303 – Bean Validation 介绍及最佳实践

    关于 Bean Validation 在任何时候,当你要处理一个应用程序的业务逻辑,数据校验是你必须要考虑和面对的事情.应用程序必须通过某种手段来确保输入进来的数据从语义上来讲是正确的.在通常的情况下 ...

  6. JSR 303 - Bean Validation 介绍及最佳实践

    关于 Bean Validation 在任何时候,当你要处理一个应用程序的业务逻辑,数据校验是你必须要考虑和面对的事情.应用程序必须通过某种手段来确保输入进来的数据从语义上来讲是正确的.在通常的情况下 ...

  7. spring boot参数校验 告别校验胶水代码

    ​ springboot进行参数校验 文章目录 前言 普通的逻辑代码校验 PathVariable 路径变量校验 JSR规范是什么? springboot-JSR303参数校验 引入参数校验依赖 官网 ...

  8. SpringBoot Validation优雅的参数校验

    前言:大多数项目中都需要后台对传过来的对象进行校验,所以经常需要写一些字段校验的代码,比如特殊字段非空.字段长度限制和邮箱格式验证等等.之前我们可能都是使用if-else-,写这些与业务逻辑关系不大的 ...

  9. SpringMVC + Hibernate-Validator 参数校验

    2019独角兽企业重金招聘Python工程师标准>>> 前言: Web开发中,最为常见的场景就是前端表单数据.Json数据与后端实体类的绑定,即使JS能校验并阻止大部分的必填漏填的风 ...

最新文章

  1. perl中q,qq,qw,qr的区别。
  2. [html] 如何在网页中嵌入公司地址的地图?
  3. Jeecg-Boot 2.1.2版本发布,基于SpringBoot的快速开发平台
  4. WPF 浏览文件夹,获取其路径
  5. perl学习之:肯定匹配和否定匹配
  6. 立志做个有激情的coder
  7. mergsort.c
  8. 轻松上手Manjaro之Manjaro常用桌面软件(微信、TIM/QQ、网易云音乐、OneDrive等)安装
  9. 小米8SE 开箱及体验
  10. 第九批A级物流企业名单[2009年12越24日]
  11. tpadmin文档 框架更新
  12. matlab雨中行走代码,雨中行走数学建模雨中行走数学建模.doc
  13. python 调用淘宝客api
  14. Halcon区域特征
  15. 批量提取 srt 字幕文件中的文字
  16. C# 通过反射获取类属性标识名称
  17. AIOT-物模型(产品模型、数据模板)
  18. 计算机中休眠是哪个键,笔记本的睡眠键和休眠键区别和作用有哪些
  19. 字符串常见方法总结:方法的作用、参数、返回值
  20. TPS和QPS的区别

热门文章

  1. 大数据时代社交网络个人信息安全研究
  2. [ArcGIS Pro 时空模式挖掘工具] 时空立方体 第一弹
  3. java tasklist_java 调用 cmd 中的 tasklist 来获取特定进程的PID
  4. 德国大学计算机专业和经济信息学,德国留学 最新经济信息学专业大学排名一览...
  5. postgresql 修改表结构 alter table xxx alter column yyy type varchar(19)
  6. 专访实在智能CEO孙林君:聚焦AI+RPA赛道,为全社会贡献100万个数字员工
  7. 【我的OpenGL学习进阶之旅】关于OpenGL ES 开启深度测试,直接黑屏的问题的解决方法
  8. 服务器x3550m5配置信息,System x3550 M5内部简介_IBM服务器_服务器x86服务器-中关村在线...
  9. 独孤思维:项目靠什么赚钱
  10. 根号3加根号5加1用计算机怎么算,根号5等于多少怎么算