`

SpringMVC数据验证——第七章 注解式控制器的数据验证、类型转换及格式化——跟着开涛学SpringMVC

阅读更多

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、控制器实现

Java代码  收藏代码
  1. @Controller  
  2. public class RegisterSimpleFormController {  
  3.     private UserModelValidator validator = new UserModelValidator();  
  4.   
  5.     @ModelAttribute("user")        //① 暴露表单引用对象为模型数据  
  6.     public UserModel getUser() {  
  7.         return new UserModel();  
  8.     }  
  9.     @RequestMapping(value = "/validator", method = RequestMethod.GET)  
  10.     public String showRegisterForm() {   //② 表单展示  
  11.         return "validate/registerAndValidator";  
  12.     }  
  13.     @RequestMapping(value = "/validator", method = RequestMethod.POST)  
  14.     public String submitForm(  
  15.             @ModelAttribute("user") UserModel user,  
  16.             Errors errors) {           //③ 表单提交  
  17.         validator.validate(user, errors);  //1 调用UserModelValidator的validate方法进行验证  
  18.         if(errors.hasErrors()) { //2如果有错误再回到表单展示页面  
  19.             return showRegisterForm();  
  20.         }  
  21.         return "redirect:/success";  
  22.     }  
  23. }   

在submitForm方法中,我们首先调用之前写的UserModelValidator的validate方法进行验证,当然此处可以直接验证并通过Errors接口来保留错误;此处还通过 Errors接口的hasErrors方法来决定当验证失败时显示的错误页面。

 

(3、spring配置文件chapter7-servlet.xml

Java代码  收藏代码
  1. <bean class="cn.javass.chapter7.web.controller.RegisterSimpleFormController"/>   

(4、错误码配置(messages.properties),需要执行NativeToAscii

直接将【springmvc-chapter4】项目中src下的messages.properties复制到src目录下。

 

在spring配置文件chapter7-servlet.xml中添加messageSource

Java代码  收藏代码
  1. <bean id="messageSource"   
  2. class="org.springframework.context.support.ReloadableResourceBundleMessageSource">  
  3.         <property name="basename" value="classpath:messages"/>  
  4.         <property name="fileEncodings" value="utf-8"/>  
  5.         <property name="cacheSeconds" value="120"/>  
  6. </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/lib/required/validation-api-1.0.0.GA.jar JSR-303规范API包
dist/hibernate-validator-4.3.0.Final.jar Hibernate 参考实现

(2、在Spring配置总添加对JSR-303验证框架的支持   

 

Java代码  收藏代码
  1. <!-- 以下 validator  ConversionService 在使用 mvc:annotation-driven 会 自动注册-->  
  2. <bean id="validator"   
  3. class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">  
  4.         <property name="providerClass"  value="org.hibernate.validator.HibernateValidator"/>  
  5.         <!-- 如果不加默认到 使用classpath下的 ValidationMessages.properties -->  
  6.         <property name="validationMessageSource" ref="messageSource"/>  
  7. </bean>   

此处使用Hibernate validator实现:

validationMessageSource属性:指定国际化错误消息从哪里取,此处使用之前定义的messageSource来获取国际化消息;如果此处不指定该属性,则默认到classpath下的ValidationMessages.properties取国际化错误消息。

 

通过ConfigurableWebBindingInitializer注册validator:

Java代码  收藏代码
  1. <bean id="webBindingInitializer"   
  2. class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">  
  3.         <property name="conversionService" ref="conversionService"/>  
  4.         <property name="validator" ref="validator"/>  
  5. </bean>   

其他配置和之前学习7.2.2.4一节一样。

 

如上集成过程看起来比较麻烦,后边我们会介绍<mvc:annotation-driven>和@EnableWebMvc,ConversionService会自动注册,后续章节再详细介绍。

 

(3、使用JSR-303验证框架注解为模型对象指定验证信息

Java代码  收藏代码
  1. package cn.javass.chapter7.model;  
  2. import javax.validation.constraints.NotNull;  
  3. public class UserModel {  
  4.     @NotNull(message="{username.not.empty}")  
  5.     private String username;  
  6. }   

通过@NotNull指定此username字段不允许为空,当验证失败时将从之前指定的messageSource中获取“username.not.empty”对于的错误信息,此处只有通过“{错误消息键值}”格式指定的才能从messageSource获取。

 

(4、控制器

Java代码  收藏代码
  1. package cn.javass.chapter7.web.controller.validate;  
  2. //省略import  
  3. @Controller  
  4. public class HelloWorldController {  
  5.     @RequestMapping("/validate/hello")  
  6.     public String validate(@Valid @ModelAttribute("user") UserModel user, Errors errors) {  
  7.           
  8.         if(errors.hasErrors()) {  
  9.             return "validate/error";  
  10.         }  
  11.         return "redirect:/success";  
  12.     }  
  13. }   

通过在命令对象上注解@Valid来告诉Spring MVC此命令对象在绑定完毕后需要进行JSR-303验证,如果验证失败会将错误信息添加到errors错误对象中。

 

(5、验证失败后需要展示的页面(/WEB-INF/jsp/validate/error.jsp)

Java代码  收藏代码
  1. <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>  
  2. <%@taglib prefix="form" uri="http://www.springframework.org/tags/form" %>  
  3.   
  4. <form:form commandName="user">  
  5.     <form:errors path="*" cssStyle="color:red"></form:errors><br/>  
  6. </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、从资源消息文件中根据消息键读取错误消息。

 

一、硬编码错误消息

直接在验证约束注解上指定错误消息,如下所示:

Java代码  收藏代码
  1. @NotNull(message = "用户名不能为空")  
  2. @Length(min=5, max=20, message="用户名长度必须在5-20之间")  
  3. @Pattern(regexp = "^[a-zA-Z_]\\w{4,19}$", message = "用户名必须以字母下划线开头,可由字母数字下划线组成")  
  4. private String username;   

如上所示,错误消息使用硬编码指定,这种方式是不推荐使用的,因为在如下场景是不适用的:

1、在国际化场景下,需要对不同的国家显示不同的错误消息;

2、需要更换错误消息时是比较麻烦的,需要找到相应的类进行更换,并重新编译发布。

 

二、从资源消息文件中根据消息键读取错误消息

 

2.1、默认的错误消息文件及默认错误消息键值

默认的错误消息文件是/org/hibernate/validator/ValidationMessages.properties,如下图所示:



 默认的错误消息键值如下图所示:



 消息键默认为:验证约束注解的全限定类名.message

 

在我们之前的测试文件中,错误消息键值是使用默认的,如何自定义错误消息文件和错误消息键值呢?

 

2.2、自定义的错误消息文件和错误消息键值

自定义的错误消息文件里的错误消息键值将覆盖默认的错误消息文件中的错误消息键值。我们自定义的错误消息文件是具有国际化功能的。

 

(1、定义错误消息文件

在类装载路径的根下创建ValidationMessages.properties文件,如在src目录下创建会自动复制到类装载路径的根下,并添加如下消息键值(需要native2ascii,可以在eclipse里装Properties Editor,自动保存为ASCII码):

 

Java代码  收藏代码
  1. javax.validation.constraints.Pattern.message=用户名必须以字母或下划线开头,后边可以跟字母数字下划线,长度在5-20之间  

需要在你的spring配置文件WEB-INF/chapter7-servlet.xml修改之前的validator Bean:

 

Java代码  收藏代码
  1. <bean id="validator"   
  2. class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">  
  3.         <property name="providerClass"   
  4. value="org.hibernate.validator.HibernateValidator"/>  
  5. </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:

Java代码  收藏代码
  1. <bean id="messageSource"   
  2. class="org.springframework.context.support.ReloadableResourceBundleMessageSource">  
  3.         <property name="basename" value="classpath:messages"/>  
  4.         <property name="fileEncodings" value="utf-8"/>  
  5.         <property name="cacheSeconds" value="120"/>  
  6. </bean>   

之前我们已经配置过了,在此就不详述了。

 

在spring配置文件WEB-INF/chapter7-servlet.xml定义的validator Bean,添加如下属性:

Java代码  收藏代码
  1. <property name="validationMessageSource" ref="messageSource"/>  

 验证失败的错误消息键值的查找将使用messageSource Bean进行。

 

在消息文件src/messages.properties中添加如下错误消息:

Java代码  收藏代码
  1. 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、自定义错误消息键值

之前我们已经学习了硬编码错误消息,及默认的错误消息,在大部分场景下,以上两种方式无法满足我们的需求,因此我们需要自定义错误消息键值。

 

在验证约束注解上指定错误消息键:

Java代码  收藏代码
  1. package cn.javass.chapter7.web.controller.validate.model;  
  2. public class PatternModel {   
  3.     @Pattern(regexp = "^[a-zA-Z_][\\w]{4,19}$", message="{user.name.error}")  
  4.     private String value;  
  5. }   

我们可以通过验证约束注解的message属性指定错误消息键,格式如“{消息键}”。

 

在消息文件src/messages.properties中添加如下错误消息:

Java代码  收藏代码
  1. user.name.error=用户名格式不合法  

输入测试地址:http://localhost:9080/springmvc-chapter7/validate/pattern?value=zhan,将看到我们自定义的错误消息显示出来了。

 

接下来我们看下如下场景

Java代码  收藏代码
  1. @Length(min=5, max=20, message="{user.name.length.error}")  
Java代码  收藏代码
  1. 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}来获取。

Java代码  收藏代码
  1. user.name.length.error=用户名长度必须在{min}-{max}之间  

输入测试地址:http://localhost:9080/springmvc-chapter7/validate/length?value=1,将看到我们自定义的错误消息显示出来了。

7.4.2.4、功能处理方法上多个验证参数的处理

当我们在一个功能处理方法上需要验证多个模型对象时,需要通过如下形式来获取验证结果:

Java代码  收藏代码
  1. @RequestMapping("/validate/multi")  
  2. public String multi(  
  3.             @Valid @ModelAttribute("a") A a, BindingResult aErrors,  
  4.             @Valid @ModelAttribute("b") B b, BindingResult bErrors) {  
  5.           
  6.         if(aErrors.hasErrors()) { //如果a模型对象验证失败  
  7.             return "validate/error";  
  8.         }  
  9.         if(bErrors.hasErrors()) { //如果a模型对象验证失败  
  10.             return "validate/error";  
  11.         }  
  12.         return "redirect:/success";  
  13. }   

每一个模型对象后边都需要跟一个Errors或BindingResult对象来保存验证结果,其方法体内部可以使用这两个验证结果对象来选择出错时跳转的页面。详见cn.javass.chapter7.web.controller.validate.MultiModelController。

 

在错误页面,需要针对不同的模型来显示错误消息:

Java代码  收藏代码
  1. <form:form commandName="a">  
  2.     <form:errors path="*" cssStyle="color:red"></form:errors><br/>  
  3. </form:form>  
  4. <form:form commandName="b">  
  5.     <form:errors path="*" cssStyle="color:red"></form:errors><br/>  
  6. </form:form>   

 

原文地址:http://jinnianshilongnian.iteye.com/blog/1733708

原作者:开涛

如有侵权请通知我删除!!!

JAVA技术交流群 532101200

分享到:
评论

相关推荐

    springmvc注解式控制器的数据验证、类型转换及格式化 SpringMVC数据验证

    springmvc注解式控制器的数据验证、类型转换及格式化 SpringMVC数据验证 参数传递

    跟我学SpringMVC 教程

    第七章 注解式控制器的数据验证、类型转换及格式化 SpringMVC数据类型转换 第七章 注解式控制器的数据验证、类型转换及格式化 SpringMVC数据格式化 第七章 注解式控制器的数据验证、类型转换及格式化 SpringMVC...

    跟我学SpringMVC

    第七章 注解式控制器的数据验证、类型转换及格式化 SpringMVC数据类型转换 第七章 注解式控制器的数据验证、类型转换及格式化 SpringMVC数据格式化 第七章 注解式控制器的数据验证、类型转换及格式化 SpringMVC数据...

    SpringMvc开涛.rar

    PDF,源代码 开涛学SpringMVC 第一章源代码下载 第二章 Spring MVC入门 源代码下载 第四章 Controller接口控制器详解 源代码下载 第五章 处理器拦截器详解——跟着...第七章 注解式控制器的数据验证、类型转换及格式化

    SpringMVC数据类型转换超详细介绍

    SpringMVC数据类型转换超详细介绍,注解式控制器的数据验证、类型转换及格式化

    SpringMVC学习文档

    SpringMVC入门、Controller接口详解、注解详解、数据验证、类型转换及格式化等等

    SpringMVC示例

    员工信息、RESTRUL_CRUD_添加操作&表单标签、RESTRUL_CRUD_删除操作&处理静态资源、RESTRUL_CRUD_修改操作、自定义类型转换器、annotation-driven配置、InitBinder注解、数据的格式化、JSR 303数据校验、错误消息的...

    Spring MVC通过添加自定义注解格式化数据的方法

    主要给大家介绍了关于Spring MVC通过添加自定义注解格式化数据的方法,文中先对springmvc 自定义注解 以及自定义注解的解析进行了详细的介绍,相信会对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面...

    SpringMVC Employee Demo

    driven配置、InitBinder注解、数据的格式化、JSR303数据校验、错误消息的显示及国际化、Ajax返回JSON、使用HttpMessageConverter、国际化_通过超链接切换中英文、文件上传、自定义的拦截器、拦截器的零Xml配置、异常...

    Spring、SpringMVC和Mybatis框架整合包

    手把手教你整合最优雅SSM框架:SpringMVC + Spring + MyBatis 博客地址:http://blog.csdn.net/qq598535550/article/details/51703190 我们看招聘信息的时候,经常会看到这一点,需要具备SSH框架的技能;而且在大...

    SpringMVC大威天龙.docx

    SpringMVC是Spring提供的一个强大而灵活的Web框架 借助于注解 SpringMVC提供了几乎是POJO的开发模式 使得控制器的开发和测试更加简单 二 SpringMVC优点 1. 角色划分清晰 2. 分工明确 而且扩展相当灵活 3. 和Spring...

    spring杂谈 作者zhang KaiTao

    1. spring杂谈[原创] 1.1 Spring事务处理时自我调用的解决方案及一些实现方式的风险 ...1.32 Spring3 Web MVC下的数据类型转换(第一篇)——《跟我学Spring3 Web MVC》抢先看 1.33 Spring 注入集合类型

    Spring3_MVC注解教程.ppt

    支持REST风格的URL 添加更多注解,可完全注解驱动 引入HTTP输入输出转换器...和数据转换、格式化、验证框架无缝集成 对静态资源处理提供特殊支持 更加灵活的控制器方法签名,可完全独立于Servlet API

    Spring MVC 3.0实战指南.ppt

    4、数据转换、格式化、校验 5、数据模型控制 6、视图及解析器 7、其它 目录: Spring MVC 3.0新特性 Spring MVC框架结构 Spring MVC框架结构 框架的实现者 目录 HTTP请求映射原理 Spring MVC进行映射的依据 通过URL...

    spring-mvc-learn:spring-mvc学习代码源码-mvc source code

    转换器(转换器)和格式化(Formatter) 转炉 实现转换器接口 在spring-mvc的配置文件中添加bean:org.springframework.context.support.ConversionServiceFactoryBean,注册转换器,添加注释驱动的转换服务属性 ...

    spring mvc 3.2 参考文档

    Spring的视图解析也非常灵活,控制器通常负责准备含有数据的model Map并选择一种视图名称,当然,它也可以直接直接写响应流,并完成该请求。视图名称解析可以根据文件扩展名或者Accept头内容类型协商,通过bean的...

    server-api:SERVER-API 是一个gui的web接口管理工具,基于 swagger-ui 的后台API开源项目,采用SpringMvc+Maven3+Jdk1.7+Tomcat7

    api 是一个GUI的WEB接口管理工具,基于 的后台API开源项目,采用SpringMvc+Maven3+Jdk1.7+Tomcat7,该项目的初衷是为了更好的去发展Swagger-ui与SpringMvc的结合,希望能够更加灵活,轻量化的根据后台不同的数据源...

    report 开源的访问层中间件,基于java平台

    可用于接口的调试及性能的展示,以及访问控制层的使用,简化控制层的繁琐代码,简化spring mvc的配置,剥离的请求前的一系列操作,耦合性低,report是请求通道采用责任链模式设计,轻便可控、扩展性强。report的测试...

    java猜数字源码-eweb4j-framework:简单的Java网络框架

    声明式事务、事务模板、事务嵌套 丰富的DAO封装类 多数据源、表关联 简单的 IOC 容器 MVC、ORM、IOC 可控开关 键值对配置文件支持 国际化支持 让我们看看它是如何做到的。 == 1. 独具特色的 RESTful 路由 == 讨厌 _...

    SSM入门到精通项目实战(附源码)

    掌握SpringMVC的项目整合配置,@Controller,@RequestMapping,@Resource,@PathVariable,@ResponseBody,@ModelAttribute,@CookieValue,@Transactional等注解的使用,json数据传值,国际化,拦截器,权限控制,...

Global site tag (gtag.js) - Google Analytics