7.4、数据验证
7.4.1、编程式数据验证
Spring 2.x提供了编程式验证支持,详见【4.16.2 数据验证】章节,在此我们重写【4.16.2.4.1、编程式验证器】一节示例。
(1、验证器实现
复制cn.javass.chapter4.web.controller.support.validator.UserModelValidator
到cn.javass.chapter7.web.controller.support.validator.UserModelValidator。
(2、控制器实现
- @Controller
- public class RegisterSimpleFormController {
- private UserModelValidator validator = new UserModelValidator();
- @ModelAttribute("user") //① 暴露表单引用对象为模型数据
- public UserModel getUser() {
- return new UserModel();
- }
- @RequestMapping(value = "/validator", method = RequestMethod.GET)
- public String showRegisterForm() { //② 表单展示
- return "validate/registerAndValidator";
- }
- @RequestMapping(value = "/validator", method = RequestMethod.POST)
- public String submitForm(
- @ModelAttribute("user") UserModel user,
- Errors errors) { //③ 表单提交
- validator.validate(user, errors); //1 调用UserModelValidator的validate方法进行验证
- if(errors.hasErrors()) { //2如果有错误再回到表单展示页面
- return showRegisterForm();
- }
- return "redirect:/success";
- }
- }
在submitForm方法中,我们首先调用之前写的UserModelValidator的validate方法进行验证,当然此处可以直接验证并通过Errors接口来保留错误;此处还通过 Errors接口的hasErrors方法来决定当验证失败时显示的错误页面。
(3、spring配置文件chapter7-servlet.xml
- <bean class="cn.javass.chapter7.web.controller.RegisterSimpleFormController"/>
(4、错误码配置(messages.properties),需要执行NativeToAscii
直接将【springmvc-chapter4】项目中src下的messages.properties复制到src目录下。
在spring配置文件chapter7-servlet.xml中添加
messageSource:
- <bean id="messageSource"
- class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
- <property name="basename" value="classpath:messages"/>
- <property name="fileEncodings" value="utf-8"/>
- <property name="cacheSeconds" value="120"/>
- </bean>
(5、视图页面(/WEB-INF/jsp/registerAndValidator.jsp)
直接将【springmvc-chapter4】项目中的/WEB-INF/jsp/registerAndValidator.jsp复制到当前项目下的/WEB-INF/jsp/validate/registerAndValidator.jsp。
(6、启动服务器测试:
在浏览器地址栏输入http://localhost:9080/springmvc-chapter7/validator进行测试,测试步骤和【4.16.2.4.1、编程式验证器】一样。
其他编程式验证的使用,请参考【4.16.2 数据验证】章节。
7.4.2、声明式数据验证
Spring3开始支持JSR-303验证框架,JSR-303支持XML风格的和注解风格的验证,接下来我们首先看一下如何和Spring集成。
7.4.2.1、集成
(1、添加jar包:
此处使用Hibernate-validator实现(版本:hibernate-validator-4.3.0.Final-dist.zip),将如下jar包添加到classpath(WEB-INF/lib下即可):
dist/hibernate-validator-4.3.0.Final.jar Hibernate 参考实现
(2、在Spring配置总添加对JSR-303验证框架的支持
- <!-- 以下 validator ConversionService 在使用 mvc:annotation-driven 会 自动注册-->
- <bean id="validator"
- class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
- <property name="providerClass" value="org.hibernate.validator.HibernateValidator"/>
- <!-- 如果不加默认到 使用classpath下的 ValidationMessages.properties -->
- <property name="validationMessageSource" ref="messageSource"/>
- </bean>
此处使用Hibernate validator实现:
validationMessageSource属性:指定国际化错误消息从哪里取,此处使用之前定义的messageSource来获取国际化消息;如果此处不指定该属性,则默认到classpath下的ValidationMessages.properties取国际化错误消息。
通过ConfigurableWebBindingInitializer注册validator:
- <bean id="webBindingInitializer"
- class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
- <property name="conversionService" ref="conversionService"/>
- <property name="validator" ref="validator"/>
- </bean>
其他配置和之前学习7.2.2.4一节一样。
如上集成过程看起来比较麻烦,后边我们会介绍<mvc:annotation-driven>和@EnableWebMvc,ConversionService会自动注册,后续章节再详细介绍。
(3、使用JSR-303验证框架注解为模型对象指定验证信息
- package cn.javass.chapter7.model;
- import javax.validation.constraints.NotNull;
- public class UserModel {
- @NotNull(message="{username.not.empty}")
- private String username;
- }
通过@NotNull指定此username字段不允许为空,当验证失败时将从之前指定的messageSource中获取“username.not.empty”对于的错误信息,此处只有通过“{错误消息键值}”格式指定的才能从messageSource获取。
(4、控制器
- package cn.javass.chapter7.web.controller.validate;
- //省略import
- @Controller
- public class HelloWorldController {
- @RequestMapping("/validate/hello")
- public String validate(@Valid @ModelAttribute("user") UserModel user, Errors errors) {
- if(errors.hasErrors()) {
- return "validate/error";
- }
- return "redirect:/success";
- }
- }
通过在命令对象上注解@Valid来告诉Spring MVC此命令对象在绑定完毕后需要进行JSR-303验证,如果验证失败会将错误信息添加到errors错误对象中。
(5、验证失败后需要展示的页面(/WEB-INF/jsp/validate/error.jsp)
- <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
- <%@taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
- <form:form commandName="user">
- <form:errors path="*" cssStyle="color:red"></form:errors><br/>
- </form:form>
(6、测试
在浏览器地址栏中输入http://localhost:9080/springmvc-chapter7/validate/hello,即没有username数据,请求后将直接到验证失败界面并显示错误消息“用户名不能为空”,如果请求时带上“?username=zhang”将重定向到成功页面。
到此集成就完成,接下来我们详细学习下有哪些验证约束注解吧。
7.4.2.2、内置的验证约束注解
内置的验证约束注解如下表所示(摘自hibernate validator reference):
验证注解 |
验证的数据类型 |
说明 |
@AssertFalse |
Boolean,boolean |
验证注解的元素值是false |
@AssertTrue |
Boolean,boolean |
验证注解的元素值是true |
@NotNull |
任意类型 |
验证注解的元素值不是null |
@Null |
任意类型 |
验证注解的元素值是null |
@Min(value=值) |
BigDecimal,BigInteger, byte, short, int, long,等任何Number或CharSequence(存储的是数字)子类型 |
验证注解的元素值大于等于@Min指定的value值 |
@Max(value=值) |
和@Min要求一样 |
验证注解的元素值小于等于@Max指定的value值 |
@DecimalMin(value=值) |
和@Min要求一样 |
验证注解的元素值大于等于@ DecimalMin指定的value值 |
@DecimalMax(value=值) |
和@Min要求一样 |
验证注解的元素值小于等于@ DecimalMax指定的value值 |
@Digits(integer=整数位数, fraction=小数位数) |
和@Min要求一样 |
验证注解的元素值的整数位数和小数位数上限 |
@Size(min=下限, max=上限) |
字符串、Collection、Map、数组等 |
验证注解的元素值的在min和max(包含)指定区间之内,如字符长度、集合大小 |
@Past |
java.util.Date, java.util.Calendar; Joda Time类库的日期类型 |
验证注解的元素值(日期类型)比当前时间早 |
@Future |
与@Past要求一样 |
验证注解的元素值(日期类型)比当前时间晚 |
@NotBlank |
CharSequence子类型 |
验证注解的元素值不为空(不为null、去除首位空格后长度为0),不同于@NotEmpty,@NotBlank只应用于字符串且在比较时会去除字符串的首位空格 |
@Length(min=下限, max=上限) |
CharSequence子类型 |
验证注解的元素值长度在min和max区间内 |
@NotEmpty |
CharSequence子类型、Collection、Map、数组 |
验证注解的元素值不为null且不为空(字符串长度不为0、集合大小不为0) |
@Range(min=最小值, max=最大值) |
BigDecimal,BigInteger,CharSequence, byte, short, int, long等原子类型和包装类型 |
验证注解的元素值在最小值和最大值之间 |
@Email(regexp=正则表达式, flag=标志的模式) |
CharSequence子类型(如String) |
验证注解的元素值是Email,也可以通过regexp和flag指定自定义的email格式 |
@Pattern(regexp=正则表达式, flag=标志的模式) |
String,任何CharSequence的子类型 |
验证注解的元素值与指定的正则表达式匹配 |
@Valid |
任何非原子类型 |
指定递归验证关联的对象; 如用户对象中有个地址对象属性,如果想在验证用户对象时一起验证地址对象的话,在地址对象上加@Valid注解即可级联验证 |
此处只列出Hibernate Validator提供的大部分验证约束注解,请参考hibernate validator官方文档了解其他验证约束注解和进行自定义的验证约束注解定义。
具体演示实例请参考cn.javass.chapter7.web.controller.validate.ValidatorAnnotationTestController。
7.4.2.3、错误消息
当验证出错时,我们需要给用户展示错误消息告诉用户出错的原因,因此我们要为验证约束注解指定错误消息。错误消息是通过在验证约束注解的message属性指定。验证约束注解指定错误消息有如下两种方式:
1、硬编码错误消息;
2、从资源消息文件中根据消息键读取错误消息。
一、硬编码错误消息
直接在验证约束注解上指定错误消息,如下所示:
- @NotNull(message = "用户名不能为空")
- @Length(min=5, max=20, message="用户名长度必须在5-20之间")
- @Pattern(regexp = "^[a-zA-Z_]\\w{4,19}$", message = "用户名必须以字母下划线开头,可由字母数字下划线组成")
- private String username;
如上所示,错误消息使用硬编码指定,这种方式是不推荐使用的,因为在如下场景是不适用的:
1、在国际化场景下,需要对不同的国家显示不同的错误消息;
2、需要更换错误消息时是比较麻烦的,需要找到相应的类进行更换,并重新编译发布。
二、从资源消息文件中根据消息键读取错误消息
2.1、默认的错误消息文件及默认错误消息键值
默认的错误消息文件是/org/hibernate/validator/ValidationMessages.properties,如下图所示:
默认的错误消息键值如下图所示:
消息键默认为:验证约束注解的全限定类名.message
在我们之前的测试文件中,错误消息键值是使用默认的,如何自定义错误消息文件和错误消息键值呢?
2.2、自定义的错误消息文件和错误消息键值
自定义的错误消息文件里的错误消息键值将覆盖默认的错误消息文件中的错误消息键值。我们自定义的错误消息文件是具有国际化功能的。
(1、定义错误消息文件
在类装载路径的根下创建ValidationMessages.properties文件,如在src目录下创建会自动复制到类装载路径的根下,并添加如下消息键值(需要native2ascii,可以在eclipse里装Properties Editor,自动保存为ASCII码):
- javax.validation.constraints.Pattern.message=用户名必须以字母或下划线开头,后边可以跟字母数字下划线,长度在5-20之间
需要在你的spring配置文件WEB-INF/chapter7-servlet.xml修改之前的validator Bean:
- <bean id="validator"
- class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
- <property name="providerClass"
- value="org.hibernate.validator.HibernateValidator"/>
- </bean>
此时错误消息键值的查找会先到classpath下ValidationMessages.properties中找,找不到再到默认的错误消息文件中找。
输入测试地址:http://localhost:9080/springmvc-chapter7/validate/pattern?value=zhan,将看到我们自定义的错误消息显示出来了。
(2、使用Spring的MessageSource Bean进行消息键值的查找
如果我们的环境是与spring集成,还是应该使用Spring提供的消息支持,具体配置如下:
在spring配置文件WEB-INF/chapter7-servlet.xml定义MessageSource Bean:
- <bean id="messageSource"
- class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
- <property name="basename" value="classpath:messages"/>
- <property name="fileEncodings" value="utf-8"/>
- <property name="cacheSeconds" value="120"/>
- </bean>
之前我们已经配置过了,在此就不详述了。
在spring配置文件WEB-INF/chapter7-servlet.xml定义的validator Bean,添加如下属性:
- <property name="validationMessageSource" ref="messageSource"/>
验证失败的错误消息键值的查找将使用messageSource Bean进行。
在消息文件src/messages.properties中添加如下错误消息:
- javax.validation.constraints.Pattern.message=用户名必须以字母或下划线开头,后边可以跟字母数字下划线,长度在5-20之间
输入测试地址:http://localhost:9080/springmvc-chapter7/validate/pattern?value=zhan,将看到我们自定义的错误消息显示出来了。
当我们配置了messageSource Bean时,默认将为验证的对象自动生成如下错误消息键:
验证错误注解简单类名.验证对象名.字段名
验证错误注解简单类名.字段名
验证错误注解简单类名.字段类型全限定类名
验证错误注解简单类名
使用的优先级是:从高到低,即最前边的具有最高的优先级,而且以上所有默认的错误消息键优先级高于自定义的错误消息键。
如测试用例cn.javass.chapter7.web.controller.validate.ValidatorAnnotationTestController中的public String pattern(@Valid @ModelAttribute("model") PatternModel model, Errors errors)将自动产生如下错误消息键:
Pattern.model.value=验证错误注解简单类名.验证对象名.字段名
Pattern.value=验证错误注解简单类名.字段名
Pattern.java.lang.String=验证错误注解简单类名.字段类型全限定类名
Pattern=验证错误注解简单类名
(3、自定义错误消息键值
之前我们已经学习了硬编码错误消息,及默认的错误消息,在大部分场景下,以上两种方式无法满足我们的需求,因此我们需要自定义错误消息键值。
在验证约束注解上指定错误消息键:
- package cn.javass.chapter7.web.controller.validate.model;
- public class PatternModel {
- @Pattern(regexp = "^[a-zA-Z_][\\w]{4,19}$", message="{user.name.error}")
- private String value;
- }
我们可以通过验证约束注解的message属性指定错误消息键,格式如“{消息键}”。
在消息文件src/messages.properties中添加如下错误消息:
- user.name.error=用户名格式不合法
输入测试地址:http://localhost:9080/springmvc-chapter7/validate/pattern?value=zhan,将看到我们自定义的错误消息显示出来了。
接下来我们看下如下场景
- @Length(min=5, max=20, message="{user.name.length.error}")
- user.name.error=用户名长度必须在5-20之间
错误消息中的5-20应该是从@Length验证约束注解中获取的,而不是在错误消息中硬编码,因此我们需要占位符的支持:
●如@Length(min=5, max=20, message="{user.name.length.error}"),错误消息可以这样写:用户名长度必须在{min}-{max}之间
错误消息占位符规则:
{验证注解属性名},如@Length有min和max属性,则在错误消息文件中可以通过{min}和{max}来获取;如@Max有value属性,则在错误消息文件中可以通过{value}来获取。
- user.name.length.error=用户名长度必须在{min}-{max}之间
输入测试地址:http://localhost:9080/springmvc-chapter7/validate/length?value=1,将看到我们自定义的错误消息显示出来了。
7.4.2.4、功能处理方法上多个验证参数的处理
当我们在一个功能处理方法上需要验证多个模型对象时,需要通过如下形式来获取验证结果:
- @RequestMapping("/validate/multi")
- public String multi(
- @Valid @ModelAttribute("a") A a, BindingResult aErrors,
- @Valid @ModelAttribute("b") B b, BindingResult bErrors) {
- if(aErrors.hasErrors()) { //如果a模型对象验证失败
- return "validate/error";
- }
- if(bErrors.hasErrors()) { //如果a模型对象验证失败
- return "validate/error";
- }
- return "redirect:/success";
- }
每一个模型对象后边都需要跟一个Errors或BindingResult对象来保存验证结果,其方法体内部可以使用这两个验证结果对象来选择出错时跳转的页面。详见cn.javass.chapter7.web.controller.validate.MultiModelController。
在错误页面,需要针对不同的模型来显示错误消息:
- <form:form commandName="a">
- <form:errors path="*" cssStyle="color:red"></form:errors><br/>
- </form:form>
- <form:form commandName="b">
- <form:errors path="*" cssStyle="color:red"></form:errors><br/>
- </form:form>
原文地址:http://jinnianshilongnian.iteye.com/blog/1733708
原作者:开涛
如有侵权请通知我删除!!!
JAVA技术交流群 532101200
相关推荐
总结来说,Spring MVC的注解式控制器提供了强大的数据验证、类型转换和格式化功能,简化了Web开发过程,提升了应用的安全性和用户体验。通过合理利用这些特性,开发者可以构建更加健壮、易于维护的Web应用。
PDF,源代码 开涛学SpringMVC 第一章源代码下载 第二章 Spring MVC入门 源代码下载 第四章 Controller接口控制器详解 源代码下载 第五章 处理器拦截器详解——跟着...第七章 注解式控制器的数据验证、类型转换及格式化
SpringMVC在数据类型转换、验证及格式化方面做了大量的改进和完善,为开发者提供了极为方便的工具和支持。通过对Spring 3之后的新特性进行深入理解,可以帮助开发者更好地利用这些功能,提升项目的整体质量。
在Spring MVC框架中,数据类型转换、数据格式化和数据校验是开发Web应用程序时不可或缺的部分。这些功能有助于确保从客户端接收到的数据准确无误,同时提供了一种优雅的方式来处理和展示这些数据。本篇文章将深入...
总之,"跟开涛学SpringMVC(7.2)SpringMVC数据"课程旨在通过详细讲解Spring MVC的数据处理、格式化和Java开发实践,帮助开发者掌握Web应用程序开发的关键技术,提高他们的开发效率和代码质量。通过学习和实践,学员...
第七章注解式控制器的数据验证、类型转换及格式化则专注于如何在SpringMVC中处理数据验证、类型转换和格式化。这包括了如何使用SpringMVC内建的数据绑定器,将HTTP请求参数绑定到控制器方法的参数上;如何对输入数据...
在控制器方法中,可以使用`@Valid`注解来激活验证,如: ```java @PostMapping("/register") public String register(@Valid User user, BindingResult result) { if (result.hasErrors()) { // 处理错误,如...
在进行Web应用开发时,尤其是在使用Spring MVC框架的过程中,经常需要对用户提交的数据进行处理,包括但不限于数据类型转换、数据验证以及数据格式化等操作。这些操作对于确保数据的准确性和应用程序的健壮性至关...
数据类型转换、数据格式化也是SpringMVC提供的强大功能,这部分内容将教会我们如何进行数据类型的转换和格式化操作。 最后,教程会提供每章的源代码下载链接,帮助学习者通过实践来加深对知识的理解。通过下载和...
SpringMVC 数据类型转换是Spring Web MVC框架中的一个重要部分,主要负责将HTTP请求中的字符串数据转换为控制器方法中期望的数据类型。在2021-2022年的专题资料中,这一主题聚焦于Spring 3之后引入的新特性和改进,...
在Spring MVC中,注解被广泛用于配置控制器、方法映射、数据绑定等。例如,`@Controller`用于标识一个类作为处理HTTP请求的控制器,而`@RequestMapping`注解则用于将URL路径映射到特定的方法。 2. **@Controller与...
**第七章 注解式控制器的数据验证、类型转换及格式化** 这部分内容详细讲解了Spring MVC如何处理数据验证,利用JSR-303/JSR-349标准进行Bean验证。同时,探讨了数据类型的自动转换和格式化,包括日期、数字等特殊...
为了解决这个问题,我们需要确保SpringMVC能够正确地将返回的数据转换为JSON格式,并设置合适的响应头。 首先,我们需要引入Jackson库来处理JSON序列化和反序列化。Jackson是Java中广泛使用的JSON处理库,包括三个...
开涛在其开源电子书中《跟开涛学SpringMVC》对SpringMVC进行了详细的介绍,并提供了入门Web开发的学习手册,以其简单易懂的方式阐述了相关知识点。 首先,书中提到了Web开发中的请求-响应模型。在Web世界中,Web...
1. **@Controller**:这个注解用于标记一个类作为SpringMVC的控制器。控制器类将处理HTTP请求,并调用业务逻辑方法。 2. **@RequestMapping**:此注解用于映射HTTP请求到特定的方法。可以放在类级别或方法级别,...
当你在控制器方法的参数中使用 `@RequestParam` 或 `@PathVariable` 注解时,Spring MVC 将自动使用已注册的 `Formatter` 进行解析和格式化。 除了手动实现 `Formatter`,Spring MVC还提供了 `...
在SpringMVC中,数据格式化是将用户输入的数据转换为业务对象的过程。这通常涉及到日期、货币和其他复杂类型的输入。Spring提供了`@DateTimeFormat`和`@NumberFormat`注解来帮助自动解析和格式化日期和数字。另外,...