SpringMvc 对提交的数据进行验证
在网页上提交数据到后端,除了在前端用 js 对相关数据进行验证之外,考虑到安全性,服务器端也是必须需要验证的。尤其是对于当前比较流行的前后端分离的开发方案,前端调用后端的接口提交数据,后端的接口需要对提交过来的数据进行验证无误,才能确保业务的正常开展。SpringMvc 借助第三方 hibernate-validator 组件,能够减轻后端验证数据的代码量,提高开发效率。
本博客主要通过代码的方式,简单介绍 SpringMvc 如何使用第三方 hibernate-validator 的 jar 包组件,实现对提交到后端数据的简单验证,在本博客的最后会提交源代码的下载。
有关 hibernate-validator 的 jar 包组件的详细细节,请查看其官网:https://github.com/hibernate/hibernate-validator
一、搭建工程
新建一个 maven 项目,导入相关 jar 包,我所导入的 jar 包都是最新的,内容如下:
有关具体的 jar 包地址,可以在 https://mvnrepository.com 上进行查询。
<dependencies> <!--导入 servlet 相关的 jar 包--> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.1</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>jsp-api</artifactId> <version>2.2</version> <scope>provided</scope> </dependency> <!--导入 Spring 核心 jar 包--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.3.18</version> </dependency> <!--导入 SpringMvc 的 jar 包--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.3.18</version> </dependency> <!--导入 jackson 相关的 jar 包--> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.13.1</version> </dependency> <!--导入校验相关的 jar 包--> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>6.1.0.Final</version> </dependency> </dependencies>
需要注意最后导入的 hibernate-validator 这个 jar 包,这个是本篇博客的重点 jar 包。另外需要的是对于 hibernate-validator 的版本,6 以上的版本必须使用 tomcat 8 以上的版本才能支持,所以这里不能使用官网提供的 tomcat 插件在运行 demo ,因为目前 tomcat 插件的最高版本为 tomcat7 ,不能满足要求,本篇博客采用的 tomcat 9.5 来运行 demo 。
配置好引用的 jar 包后,打开右侧的 Maven 窗口,刷新一下,这样 Maven 会自动下载所需的 jar 包文件。
搭建好的项目工程整体目录比较简单,具体如下图所示:
com.jobs.config 包下存储的是 SpringMvc 的配置文件和 Servlet 的初始化文件
com.jobs.controller 包下存储的是用于提供 api 接口的类
com.jobs.domain 包下存储的是用来接收数据的实体类
com.jobs.group 包下存储的是空接口,主要是对验证字段进行分组
web 目录下放置的是网站文件,只有一个静态页面和一些 js 文件
二、字段验证配置细节
有关 SpringMvc 纯注解配置( ServletInitConfig 和 SpringMvcConfig)内容,跟之前的博客相比,没有任何变化,这里就不介绍了。我们先从简单的内容进行介绍,首选介绍两个分组的接口,内容如下:
package com.jobs.group; public interface GroupValidateA { }
package com.jobs.group; public interface GroupValidateB { }
这是两个空的接口,没有任何内容。本博客前端页面提交过来的数据,会自动封装到实体类中,我们会对实体类的相关字段进行数据验证。但是并不是每次都需要验证所有的字段,比如添加用户的时候,可能需要验证提交过来的所有字段,包括密码等内容。但是在修改用户的时候,并不需要修改密码,所以不需要对密码进行验证。此时就需要对用户需要验证的字段进行分组,比如把添加用户时需要验证的字段标记上 A 组,把修改用户时需要验证的字段标记上 B 组。当然实体类中的一个字段,可以同时属于多个验证组,比如同时属于 A 组和 B 组。
在本篇博客中,我们验证提交过来的员工信息,在 Employee 实体类和 Department 实体类中对相关字段进行分组验证。
package com.jobs.domain; import com.jobs.group.GroupValidateA; import com.jobs.group.GroupValidateB; import javax.validation.Valid; import javax.validation.constraints.*; public class Employee { //员工名称 @Size(min = 2, max = 10, message = "员工姓名不能为空,且字符长度必须在 2 到 10 之间", groups = {GroupValidateA.class, GroupValidateB.class}) private String name; //员工年龄 @Min(value = 18, message = "员工的年龄不能小于 18 岁", groups = {GroupValidateA.class}) @Max(value = 60, message = "员工的年龄不能大于 60 岁", groups = {GroupValidateA.class}) @NotNull(message = "请填写员工的年龄", groups = {GroupValidateA.class}) private Integer age; //性别 @NotNull(message = "请选择员工的性别", groups = {GroupValidateA.class, GroupValidateB.class}) private Integer gender; @Valid private Department department; //这里省略 get 和 set 方法... @Override public String toString() { return "Employee{" + "name='" + name + '\'' + ", age=" + age + ", gender=" + gender + ", department=" + department + '}'; } }
package com.jobs.domain; import com.jobs.group.GroupValidateA; import javax.validation.constraints.Size; //所属部门 public class Department { //部门名称 @Size(min = 3, max = 10, message = "部门名称不能为空,且字符长度必须在 3 到 10 之间", groups = {GroupValidateA.class}) private String departName; //职位 private String position; //这里省略 get 和 set 方法... @Override public String toString() { return "Department{" + "departName='" + departName + '\'' + ", position='" + position + '\'' + '}'; } }
员工 Employee 实体类,有一个属性是 Dempartment ,这又是一个实体类。上边的 @Size ,@Min,@Max,@NotNull 都是字段数据验证的注解,从其 message 内容就很容易看出其验证的具体功能。需要注意的是:由于 Department 是一个实体类,如果想要验证 Department 类中的相关字段,需要在 Employee 类的 Department 字段是增加 @Valid 注解。
上面的验证字段,除了 Department 类中的 position 字段没有添加验证注解外,其它字段都被归属到了 GroupValidateA 验证组,同时又把 Employee 类的 name 和 gender 也归属到了 GroupValidateB 组。下面让我们看一下 TestController 的内容:
package com.jobs.controller; import com.jobs.domain.Employee; import com.jobs.group.GroupValidateA; import com.jobs.group.GroupValidateB; import org.springframework.validation.Errors; import org.springframework.validation.FieldError; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.List; import java.util.Set; import java.util.stream.Collectors; @RequestMapping("/test") @RestController public class TestController { //验证 GroupValidateA 组的规则 @PostMapping(value = "/validate1") public String validateRequest1( @Validated({GroupValidateA.class}) Employee employee, Errors errors) { System.out.println(employee); if (errors.hasErrors()) { List<FieldError> fieldErrors = errors.getFieldErrors(); System.out.println("验证发现的错误如下:"); for (FieldError error : fieldErrors) { System.out.println(error.getField() + "---->" + error.getDefaultMessage()); } Set<String> setError = fieldErrors.stream().map(s -> s.getDefaultMessage()) .collect(Collectors.toSet()); return setError.toString(); } else { return "提交成功,没有任何问题"; } } //验证 GroupValidateB 组的规则(只验证两个字段:员工姓名和员工性别) @PostMapping(value = "/validate2") public String validateRequest2( @Validated({GroupValidateB.class}) Employee employee, Errors errors) { System.out.println(employee); if (errors.hasErrors()) { List<FieldError> fieldErrors = errors.getFieldErrors(); System.out.println("验证发现的错误如下:"); for (FieldError error : fieldErrors) { System.out.println(error.getField() + "---->" + error.getDefaultMessage()); } Set<String> setError = fieldErrors.stream().map(s -> s.getDefaultMessage()) .collect(Collectors.toSet()); return setError.toString(); } else { return "提交成功,没有任何问题"; } } }
TestController 开发了两个接口,其中 /test/validate1 接口只验证 GroupValidateA 组的字段,/test/validate2 接口只验证 GroupValidateB 组的字段。
三、前端页面细节
在本 Demo 的首页 index.html 编写了两个 ajax 数据请求,分别请求 TestController 中的两个接口,分别验证 GroupValidateA 和 GroupValidate 两个组的提交过来的字段内容。index.html 和所引用的 apitest.js 具体细节如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>SpringMvc提交数据验证</title> </head> <body> <fieldset> <legend>对 GroupValidateA 组设置的字段进行验证</legend> 员工姓名:<input type="text" id="name1"/><br/> 员工年龄:<input type="text" id="age1"/><br/> 员工性别: <select id="gender1"> <option value="" selected>请选择</option> <option value="1">男</option> <option value="0">女</option> </select><br/> 部门名称:<input type="text" id="depname1"/><br/> 工作职位:<input type="text" id="position1"/><br/> <input type="button" id="btn1" value="提交"> </fieldset> <hr/> <fieldset> <legend>对 GroupValidateB 组设置的字段进行验证</legend> 员工姓名:<input type="text" id="name2"/><br/> 员工年龄:<input type="text" id="age2"/><br/> 员工性别: <select id="gender2"> <option value="" selected>请选择</option> <option value="1">男</option> <option value="0">女</option> </select><br/> 部门名称:<input type="text" id="depname2"/><br/> 工作职位:<input type="text" id="position2"/><br/> <input type="button" id="btn2" value="提交"> </fieldset> <script src="./js/jquery-3.6.0.min.js"></script> <script src="js/apitest.js"></script> </body> </html>
$(function () { $('#btn1').click(function () { let name1 = $('#name1').val().trim(); let age1 = $('#age1').val().trim(); let gender1 = $('#gender1').val(); let depname1 = $('#depname1').val().trim(); let position1 = $('#position1').val().trim(); $.ajax({ type: "post", url: "/test/validate1", dataType: "text", data: { name: name1, age: age1, gender: gender1, 'department.departName': depname1, 'department.position': position1 }, success: function (data) { alert("返回的数据:" + data); }, error: function (data) { console.log(data.responseText); } }); }); $('#btn2').click(function () { let name2 = $('#name2').val(); let age2 = $('#age2').val(); let gender2 = $('#gender2').val(); let depname2 = $('#depname2').val(); let position2 = $('#position2').val(); $.ajax({ type: "post", url: "/test/validate2", dataType: "text", data: { name: name2, age: age2, gender: gender2, 'department.departName': depname2, 'department.position': position2 }, success: function (data) { alert("返回的数据:" + data); }, error: function (data) { console.log(data.responseText); } }); }); })
启动 Demo 网站,分别进行相关数据的填写或者清除,提交数据,查看后端验证效果。
到此为止,有关 SpringMvc 使用第三方 hibernate-validator 的 jar 包组件,实现对提交到后端数据的简单验证,基本介绍完毕。
本博客 Demo 的源代码下载地址为:https://files.cnblogs.com/files/blogs/699532/SpringMvc_validate.zip
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理