当前位置: 首页 > news >正文

JSR303校验(1)

前言

在讨论什么是JSR303之前,我们需要思考一下我们在日常开发中是如何对前端传过来的参数做校验的,这时候就会有人会问了:前端不是已经校验过数据了吗?为什么我们还要做校验呢,直接用不就好了?草率了,假如说前端代码校验没写好又或者是对于会一点编程的人来说,直接绕过前端发请求,把一些错误的参数传过来,你后端代码不就危险了嘛。所以我们一般都是前端一套校验,后端在一套校验,这样安全性就能够大大得到提升了。而没有没有接触过JSR303之前我们一般都是这样校验数据的:

显然这样的操作太过于繁琐,太多的if,else。而接触过JSR303之后我们可以这样来校验参数:
在这里插入图片描述

是不是很简单,废话不多说让我们开始学习JSR303吧。

什么是JSR303

JSR是Java Specification Requests的缩写,意思是Java 规范提案。是指向JCP(Java Community Process)提出新增一个标准化技术规范的正式请求。任何人都可以提交JSR,以向Java平台增添新的API和服务。JSR已成为Java界的一个重要标准。
JSR-303 是JAVA EE 6 中的一项子规范,叫做Bean Validation,Hibernate Validator 是 Bean Validation 的参考实现 . Hibernate Validator 提供了 JSR 303 规范中所有内置 constraint(约束) 的实现,除此之外还有一些附加的 constraint。

初体验

依赖

在pom.xml引入依赖

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

实际上,spring-boot-starter-validation依赖主要是为了引入下面这个依赖:

<dependency>
  <groupId>org.hibernate.validator</groupId>
  <artifactId>hibernate-validator</artifactId>
  <version>6.2.4.Final</version>
  <scope>compile</scope>
</dependency>

使用

在我们的用来接收参数的类上加上hibernate-validator提供的注解

@Data
public class SysUser {
    
    private Integer userId;
    @NotEmpty(message = "密码不能为空")
    @Size(min = 6, max = 20, message = "用户名长度在6-20位")
    private String username;
    
    @Min(value = 1, message = "年龄最小值为1")
    @Max(value = 120, message = "年龄最大值为120")
    private Integer age;
    
    @Email(message = "邮箱格式不正确")
    private String email;
    
    @Past(message = "出身年月不能在未来")
    private LocalDate birthday;
}

Controller代码,在类前面加上@Validated

@RestController
@RequestMapping("/sys/user")
public class SysUserController {
    @PostMapping()
    public Result saveSysUser(@Validated @RequestBody SysUser sysUser) {
        return Result.success(HttpStatus.SUCCESS, "保存用户成功", sysUser);
    }
}

测试

然后我们用api fox发送一下请求
先来个正常请求:
在这里插入图片描述

当然一切正常


接下来我们把用户名加长一点点OvO
在这里插入图片描述

很显然后端抛了异常,说明我们已经成功对参数做了校验,但是这样写依旧没有达到我们的目的,我们需要在参数校验失败之后给前端返回错误信息,所以我们还有要加一点点的代码。
image.png
在这里插入图片描述

改进代码

 @PostMapping()
    public Result saveSysUser(@Validated @RequestBody SysUser sysUser, BindingResult result) {
        if (result.hasErrors()) {
            Map<String, String> map = new HashMap<>();
            result.getFieldErrors().forEach(fieldError -> map.put(fieldError.getField(), fieldError.getDefaultMessage()))
            ;
            return Result.error(HttpStatus.ERROR, "数据校验失败", map);
        }
        return Result.success(HttpStatus.SUCCESS, "保存用户成功", sysUser);
    }

我们传参的时候再传一个BindingResult,顾名思义就是和数据捆绑的校验结果。一旦校验失败,我们就用一个map来接受出错的字段,这里用了jdk8的流来做遍历操作,当然用迭代器可以啦,然后返回给前端,这样前端也可以根据相应结果做出对应操作。

再次测试

在这里插入图片描述

这次我们的响应不会再报500了,而是把我们出错的字段显示了出来,对照我们之前写的代码是不是一下子就牛逼起来了(不是)。

总结

hibernate-validator可以帮助我们把繁多的校验ifelse去除,用注解来代替,简化我们的代码。但是现在这种校验我们需要在每个controller中都要写,这样冗余度还是太高了,所以我们可以搭配Spring提供的全局异常处理(RestControllerAdvice)来写的更加优雅。接着我们在做校验的时候,通常会遇到一个实体类的添加和修改,他们的校验规则是不同的,所以分组显得尤为重要。他可以帮助我们少建一个冗余的实体类。而分组和全局异常处理就留到下一次在聊吧,学习是个循序渐进的过程,慢慢来。

相关文章:

  • Nacos - 支持PostgreSQL
  • CFD网格质量评估标准
  • 网课答案公众号题库系统
  • 详解AVL树(二叉搜索平衡树)【C++实现】
  • 网课答案公众号搭建方法
  • 牛客网练习题(函数部分)
  • 仿everything的文件搜索工具项目详解:Part3
  • React中this.setState方法原理解析(详解)
  • jquary
  • nginx-vts监控模块
  • “刷脸”看健康码的电子哨兵,一旦遭破解,让你无路可走
  • var、let、const声明变量和不用var声明变量的区别
  • 【uni-app系列】uni-ui扩展组件和uViewUI的安装使用
  • Python Excel xlsx,xls,csv 格式互转
  • JavaScript系列(一):浏览器及内核介绍
  • .pyc 想到的一些问题
  • __proto__ 和 prototype的关系
  • 【跃迁之路】【585天】程序员高效学习方法论探索系列(实验阶段342-2018.09.13)...
  • java B2B2C 源码多租户电子商城系统-Kafka基本使用介绍
  • Java,console输出实时的转向GUI textbox
  • Javascript弹出层-初探
  • Linux编程学习笔记 | Linux多线程学习[2] - 线程的同步
  • Linux各目录及每个目录的详细介绍
  • mysql 5.6 原生Online DDL解析
  • Python打包系统简单入门
  • 从输入URL到页面加载发生了什么
  • 代理模式
  • 更好理解的面向对象的Javascript 1 —— 动态类型和多态
  • 前端面试之闭包
  • 通过获取异步加载JS文件进度实现一个canvas环形loading图
  • 网络应用优化——时延与带宽
  • 你对linux中grep命令知道多少?
  • ​sqlite3 --- SQLite 数据库 DB-API 2.0 接口模块​
  • # Python csv、xlsx、json、二进制(MP3) 文件读写基本使用
  • #HarmonyOS:软件安装window和mac预览Hello World
  • #Linux(权限管理)
  • (Oracle)SQL优化技巧(一):分页查询
  • (接口封装)
  • (四)图像的%2线性拉伸
  • (学习日记)2024.04.04:UCOSIII第三十二节:计数信号量实验
  • (轉貼) UML中文FAQ (OO) (UML)
  • .NET/C# 使用 ConditionalWeakTable 附加字段(CLR 版本的附加属性,也可用用来当作弱引用字典 WeakDictionary)
  • .Net中wcf服务生成及调用
  • .pyc文件还原.py文件_Python什么情况下会生成pyc文件?
  • .sh 的运行
  • ::
  • [ vulhub漏洞复现篇 ] JBOSS AS 5.x/6.x反序列化远程代码执行漏洞CVE-2017-12149
  • [ 攻防演练演示篇 ] 利用通达OA 文件上传漏洞上传webshell获取主机权限
  • []我的函数库
  • [17]JAVAEE-HTTP协议
  • [acm算法学习] 后缀数组SA
  • [AIGC] MySQL存储引擎详解
  • [AutoSAR系列] 1.3 AutoSar 架构
  • [AX]AX2012 AIF(四):文档服务应用实例
  • [C# 基础知识系列]专题十六:Linq介绍