表单验证在Web开发中是非常常见和重要的一部分,它用于确保用户提交的数据符合预期的规则和限制。
通过表单验证,我们可以有效地捕获并处理用户输入中的错误或不正确的数据,从而提高应用程序的数据质量和用户体验。在本教程中,我们将学习如何使用Spring MVC的表单验证功能来验证用户提交的表单数据,并处理验证结果。
在接下来的内容中,我们将深入了解Spring MVC表单验证的各个方面,包括如何定义验证规则、如何显示验证错误信息以及如何处理验证结果等。我们还将探讨常见的表单验证场景,并提供实际示例来演示如何实现这些验证逻辑。
org.springframework
spring-webmvc
5.3.23
org.projectlombok
lombok
1.18.30
ch.qos.logback
logback-classic
1.4.5
org.hibernate.validator
hibernate-validator
6.0.13.Final
hibernate-validator
是一个基于Hibernate Validator的Java Bean验证框架。它提供了一组用于验证Java Bean属性的注解,并具有灵活、可扩展的验证机制。
使用hibernate-validator
可以实现对Java Bean对象进行数据验证和校验,确保对象符合预期的规则和约束。它可以用于以下方面:
参数校验:在方法参数上添加注解,对传入的参数进行验证,以确保参数满足指定的条件。例如,可以验证参数是否为非空、是否满足正则表达式、是否在指定的范围内等。
表单验证:在表单提交时,对表单中的字段进行验证,以确保用户输入的数据符合要求。例如,可以验证用户名、密码、邮箱等字段的格式和有效性。
实体类验证:在保存或更新实体对象时,对实体类中的字段进行验证,以确保数据的完整性和一致性。例如,可以验证实体对象的属性是否为空、长度是否符合要求、是否满足特定的业务规则等。
自定义验证:除了使用内置的验证注解外,还可以自定义验证注解和验证器,以实现更复杂的验证逻辑。通过自定义注解和验证器,可以灵活地定义和扩展验证规则。
通过引入hibernate-validator
的依赖,可以在项目中使用其提供的注解来对Java Bean对象进行验证。在验证过程中,如果发现验证不通过,将会抛出相关的异常或返回验证结果,从而方便开发者处理验证失败的情况。
dispatcher
org.springframework.web.servlet.DispatcherServlet
1
dispatcher
/
用于配置 Servlet 的映射和加载。在 Spring MVC 中,它用于配置 DispatcherServlet 的初始化和请求映射。
具体来说,这段配置的作用如下:
- 定义了一个名为 "dispatcher" 的 Servlet,并指定了 org.springframework.web.servlet.DispatcherServlet 作为其处理类。
- 设置了 load-on-startup 属性为 1,表示在应用启动时就加载该 Servlet。
- 使用
元素将 "dispatcher" Servlet 映射到所有的请求路径上(即 / ),意味着所有的请求都会经过该 Servlet 进行处理。
这段配置的作用是将所有的请求交给 DispatcherServlet 处理,并让它成为应用的核心控制器。DispatcherServlet 将根据请求的 URL 和其他配置信息,将请求分发给相应的处理器方法进行处理,然后返回响应结果。
user.userName.notEmpty = 请输入用户名
user.age.notNull = 请输入年龄
user.age.min = 年龄不能小于18
user.birth.notNull = 请输入出生年月日
user.email.notEmpty = 请输入邮箱地址
user.email.legal = 请填写合法的email邮箱
这里面的值会在实体类中获取。
@Data
public class User {
/**
* 验证空字符串
*/
@NotEmpty(message = "{user.userName.notEmpty}")
private String userName;
/**
* 验证空值
*/
@NotNull(message = "{user.age.notNull}")
/**
* 最小值范围
*/
@Min(value = 18,message = "{user.age.min}")
private Integer age;
@NotNull(message = "{user.birth.notNull}")
//@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date brith;
@NotEmpty(message = "{user.email.notEmpty}")
@Email(message = "{user.email.legal}")
private String email;
}
这段代码是一个User类的定义,使用了一些注解来进行数据验证。下面是每个注解的作用:
@NotEmpty(message = "{user.userName.notEmpty}")
:该注解用于验证字符串属性值是否非空。如果userName属性为空字符串,则会产生一个指定消息的验证错误。
@NotNull(message = "{user.age.notNull}")
:该注解用于验证属性值是否非空。如果age属性为空值(null),则会产生一个指定消息的验证错误。
@Min(value = 18, message = "{user.age.min}")
:该注解用于验证数值属性值是否大于等于指定的最小值。在这个例子中,如果age属性的值小于18,则会产生一个指定消息的验证错误。
@NotNull(message = "{user.birth.notNull}")
:该注解用于验证属性值是否非空。如果birth属性为空值(null),则会产生一个指定消息的验证错误。
//@DateTimeFormat(pattern = "yyyy-MM-dd")
:这是一个注释,用于指定日期类型属性的格式化规则。在这个例子中,如果取消注释并指定了合适的格式化规则,可以对brith属性的日期进行格式验证。
@NotEmpty(message = "{user.email.notEmpty}")
:该注解用于验证字符串属性值是否非空。如果email属性为空字符串,则会产生一个指定消息的验证错误。
@Email(message = "{user.email.legal}")
:该注解用于验证字符串属性值是否符合Email的格式要求。如果email属性不是合法的Email格式,则会产生一个指定消息的验证错误。
通过在User类的属性上添加这些注解,可以对属性值进行验证,确保满足特定的条件和格式要求。当验证失败时,会生成相应的错误消息供使用者查看和处理。
@Data
public class ResultVO {
// 响应状态码,默认 200
private Integer code = HttpStatus.OK.value();
private String message;
private T data;
}
泛型类ResultVO,用于封装接口的响应结果。下面是每个属性的作用:
private Integer code = HttpStatus.OK.value()
:该属性表示响应的状态码,默认为200,表示成功。HttpStatus.OK.value()是Spring提供的常量,表示HTTP状态码200。
private String message
:该属性表示响应的消息,用于描述响应的详细信息。根据具体的业务需求,可以设置不同的消息内容。
private T data
:该属性表示响应的数据,是一个泛型类型,可以根据实际情况指定具体的数据类型。根据接口的需求,可以将查询结果、返回对象等放在这个属性中。
通过定义这个ResultVO类,可以将接口的响应结果统一封装并返回给前端。它包含了响应的状态码、消息和数据,可以方便地进行操作和处理。在实际使用中,可以根据业务需要对ResultVO类进行扩展,添加更多的属性和方法。
@RestController
public class UserController {
/**
* 注册日期格式化器
* @param binder
*/
@InitBinder
public void regFormatter (WebDataBinder binder){
binder.addCustomFormatter(new DateFormatter("yyyy-MM-dd"));
}
/**
* @Valid 注解:标注的参数实体要参与 Bean 验证
* 通常放在实体上
*
* @param user
* @param result 这个结果集存放了验证信息,如果这个校验未通过
* 就从这个结果集中获取验证消息
* @return
*/
@PostMapping("/add")
public ResultVO add(@Valid User user, BindingResult result) throws JsonProcessingException {
ResultVO vo = new ResultVO();
// 先验证是否校验通过,如果存在错误消息则表示未通过
if ( result.hasErrors() ){
// 创建一个 map 来保存这些错误信息
Map error = new HashMap<>();
// 循环遍历所有的错误信息
result.getFieldErrors().forEach(fieldError -> {
// 以字段名作为 key ,错误信息作为 value 保存到 map 中
error.put(fieldError.getField(), fieldError.getDefaultMessage());
});
// 设置响应状态码
vo.setCode(HttpStatus.INTERNAL_SERVER_ERROR.value());
// 将 map 序列化成 JSON 字符串
String messages = new ObjectMapper().writeValueAsString(error);
vo.setMessage(messages);
// 直接将 errors 保存到 data 中
// vo.setData(Keymap);
return vo;
}
return vo;
}
}
UserController类,用于处理用户相关的请求。下面是每个方法的作用:
regFormatter
方法:该方法使用@InitBinder
注解,用于注册日期格式化器。在这个例子中,通过调用binder.addCustomFormatter(new DateFormatter("yyyy-MM-dd"))
方法,将日期格式化器注册到WebDataBinder中,指定日期的格式为"yyyy-MM-dd"。
add
方法:该方法使用@PostMapping("/add")
注解,用于处理添加用户的请求。在这个例子中,通过@Valid
注解标注了User
参数,表示要对User
对象进行Bean验证。同时,该方法还接受一个BindingResult
参数,用于存放验证结果的信息。
- 首先,通过创建一个
ResultVO
对象vo
来存放响应结果。- 然后,通过
result.hasErrors()
判断是否存在验证错误消息。如果存在错误,则进行错误处理。- 在错误处理中,创建一个
Map
对象error
来保存错误信息,循环遍历所有的错误信息,并将字段名作为键,错误信息作为值,保存到error
中。- 设置响应状态码为500(
HttpStatus.INTERNAL_SERVER_ERROR.value()
),并将error
对象序列化为JSON字符串,赋给vo
的message
属性。- 如果需要,可以将
error
对象直接保存到vo
的data
属性中。- 最后,返回
vo
对象作为响应结果。
通过定义这个UserController
类,并使用注解进行日期格式化注册和Bean验证,可以处理用户添加请求,并根据验证结果返回相应的响应结果。在实际使用中,可以根据业务需求对方法进行扩展和优化。
classpath:message
每个属性的作用:
:该配置用于告诉Spring扫描指定包下的类,以便自动注册为Spring的组件(如控制器、服务等)。
:该配置启用Spring MVC对注解驱动的支持,其中
validator
属性指定用于处理验证的验证器Bean的ID。它会自动将验证错误与错误消息关联起来。
:该配置用于将静态资源的请求交给默认的Servlet处理,而不是通过DispatcherServlet处理。这样可以让静态资源(如CSS、JavaScript等)能够直接访问。
:这是一个内部资源视图解析器的配置,用于解析并返回JSP视图的路径。
prefix
属性指定JSP文件所在的目录,suffix
属性指定JSP文件的后缀名。
:该配置用于配置资源消息,即国际化文本消息的配置。
basenames
属性指定资源文件的位置,defaultEncoding
属性指定资源文件的编码格式。
:这是一个校验器的配置,用于对验证框架进行配置。
providerClass
属性指定所使用的验证器的提供者,validationMessageSource
属性引用了前面配置的消息资源。
用户注册
这段代码是一个简单的前端页面,用于用户注册。它使用了jQuery库来处理表单提交和异步请求。
在页面中,有一个
标签,包含了用户需要填写的字段,如姓名、年龄、出生日期和电子邮件等。其中,每个字段都使用了
标签,并通过
name
属性指定了字段名。在页面底部的JavaScript代码中,使用了jQuery的
$(function(){})
方法,确保文档加载完成后执行相应代码。首先,通过$(':button')
选择器选中所有元素,并绑定了一个点击事件处理函数。当按钮被点击时,触发了一个AJAX请求。
AJAX请求使用了
$.ajax()
方法,其中传入了请求的URL、请求类型和数据等参数。请求的URL为../add
,表示将请求发送到服务器上的/add
路径。请求类型为POST,即使用HTTP POST方法发送请求。数据使用$('#f1').serialize()
方法对表单进行序列化,将表单中的输入值转换为URL编码的字符串。当请求成功返回时,会执行
success
回调函数。在回调函数中,首先判断响应的result
对象中的code
属性是否为500(表示服务器内部错误)。如果是500,则说明存在验证错误消息。然后,通过$('#msg')
选中页面中的
元素,并清空其内容。接下来,将响应的message
属性(包含错误信息的JSON字符串)转换为JSON对象,并使用$.each()
方法遍历错误信息,将每条错误信息添加到
元素中显示出来。总体而言,这段代码实现了一个简单的用户注册页面,并使用AJAX请求将表单数据发送到服务器进行处理。在服务器端,通过验证结果返回不同的响应。在前端页面中,通过jQuery来处理和显示服务器返回的验证错误信息。
4、运行效果
我们测试的结果,刚开始什么都不写的时候都提示了为空,当一个一个输进去后,就没有了提示,不满足条件的也会提示。
三、使用 Springmvc 表单验证的好处
Spring MVC的表单验证功能具有以下几个好处:
提高数据的有效性和完整性:通过表单验证,可以确保用户提交的数据符合预期的格式、长度、范围等要求。这可以避免因为不合法的数据导致程序出错或产生意外结果。有效的表单验证可以提高数据的质量和可靠性。
减少后端开发工作量:使用Spring MVC的表单验证,可以在后端自动执行验证逻辑,而无需手动编写大量的验证代码。框架会根据注解配置或自定义验证规则,自动完成验证过程。这样可以极大地减少开发人员的工作量,并提高开发效率。
支持代码重用和模块化:通过使用Spring MVC的表单验证,可以将验证逻辑从业务逻辑中分离出来,形成独立的验证模块。这样可以提高代码的重用性和可维护性,减少重复代码的编写。同时,验证模块可以针对不同的实体对象进行复用,进一步提高开发效率。
提供友好的用户反馈:通过表单验证,可以及时地向用户提供错误信息或者警告信息,帮助用户发现并纠正输入错误。这可以提升用户体验,让用户更加轻松地填写正确的数据。同时,通过在前端页面显示验证错误信息,可以帮助开发人员快速定位并修复问题。
防止安全漏洞和数据损坏:表单验证还可以用于防范安全漏洞,例如输入校验、XSS(跨站脚本攻击)预防等。通过限制输入的数据格式和内容,可以有效地防止恶意用户提交恶意代码或其他危险数据,提高应用程序的安全性。
总之,Spring MVC的表单验证功能在提高数据质量、减少开发工作量、提供友好用户反馈、增强应用程序安全性等方面具有重要的好处。它是开发Web应用程序时不可或缺的一部分,能够提升开发效率和用户体验。
四、gitee 案例
地址:CH07 · qiuqiu/SpringMVC - 码云 - 开源中国 (gitee.com)