声明式数据验证

声明式数据验证

nSpring3开始支持JSR-303验证框架,JSR-303支持XML风格的和注解风格的验证,接下来咱们首先看一下如何和Spring集成。css

1、添加jar包:html

此处使用Hibernate-validator实现(版本:hibernate-validator-4.3.0.Final-dist.zip),将以下jar包添加到classpath(WEB-INF/lib下便可):java

dist/lib/required/validation-api-1.0.0.GA.jar     JSR-303规范API包git

dist/hibernate-validator-4.3.0.Final.jar          Hibernate 参考实现web

还须要加入jboss-logging-3.1.0.CR2.jar正则表达式

 

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

<!-- 如下 validator  ConversionService 在使用 mvc:annotation-driven 会 自动注册-->api

<bean id= "validator"数组

class= "org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">mvc

        <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>

 

 

3、在Spring配置  添加message配置

<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>

在src下放一个messages.properties,里面的内容是:

username.not.empty=\u7528\u6237\u59D3\u540D\u4E0D\u80FD\u4E3A\u7A7A

这是已经转义的,原始的信息是:用户姓名不能为空

nHelloWorld的Model,使用JSR-303验证框架注解为模型对象指定验证信息

public class UserModel {

@NotNull(message="{username.not.empty}")

private String username;

}

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

nHelloWorld的Controller

@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错误对象中

说明:错误对象的表明者是Errors接口,而且提供了几个实现者,在Spring Web MVC中咱们使用的是以下实现:Errors、BindingResult、BindException等

 

nHelloWorld的验证失败后须要展现的页面

<%@ 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>

 

 

能够去测试啦,不给UserModel传递 name值看看效果。

 

n@AssertFalse

验证的数据类型 :Boolean,boolean

说明 :验证注解的元素值是false

n@AssertTrue

验证的数据类型 :Boolean,boolean

说明 :验证注解的元素值是true

n@NotNull

验证的数据类型 :任意类型 

说明 :验证注解的元素值不是null

n@Null

验证的数据类型 :任意类型 

说明 :验证注解的元素值是null

n@Min(value=值)

验证的数据类型 :BigDecimal,BigInteger, byte,short, int, long,等任何Number或CharSequence(存储的是数字)子类型 

说明 :验证注解的元素值大于等于@Min指定的value值

 

n@Max(value=值)

验证的数据类型 :和@Min要求同样 

说明 :验证注解的元素值小于等于@Max指定的value值

n@DecimalMin(value=值)

验证的数据类型 :和@Min要求同样

说明 :验证注解的元素值大于等于@ DecimalMin指定的value值

n@DecimalMax(value=值)

验证的数据类型 :和@Min要求同样

说明 :验证注解的元素值小于等于@ DecimalMax指定的value值

n@Digits(integer=整数位数, fraction=小数位数)

验证的数据类型 :和@Min要求同样

说明 :验证注解的元素值的整数位数和小数位数上限

n@Size(min=下限, max=上限)

验证的数据类型 :字符串、Collection、Map、数组等

说明 :验证注解的元素值的在min和max(包含)指定区间以内,如字符长度、集合大小

n@Past

验证的数据类型 :java.util.Date,java.util.Calendar,Joda Time类库的日期类型

说明 :验证注解的元素值(日期类型)比当前时间早

 

n@Future

验证的数据类型 :与@Past要求同样

说明 :验证注解的元素值(日期类型)比当前时间晚

n@NotBlank

验证的数据类型 :CharSequence子类型

说明 :验证注解的元素值不为空(不为null、去除首位空格后长度为0),不一样于@NotEmpty,@NotBlank只应用于字符串且在比较时会去除字符串的首位空格

n@Length(min=下限, max=上限) 

验证的数据类型 : CharSequence子类型

说明 :验证注解的元素值长度在min和max区间内

n@NotEmpty

验证的数据类型 :CharSequence子类型、Collection、Map、数组

说明 :验证注解的元素值不为null且不为空(字符串长度不为0、集合大小不为0)

n@Range(min=最小值, max=最大值)

验证的数据类型 :BigDecimal,BigInteger,CharSequence, byte, short, int, long等原子类型和包装类型

说明 :验证注解的元素值在最小值和最大值之间

 

n@Email(regexp=正则表达式,flag=标志的模式)

验证的数据类型 :CharSequence子类型(如String)

说明 :验证注解的元素值是Email,也能够经过regexp和flag指定自定义的email格式

n@Pattern(regexp=正则表达式,flag=标志的模式)

验证的数据类型 :String,任何CharSequence的子类型

说明 :验证注解的元素值与指定的正则表达式匹配

n@Valid

验证的数据类型 :任何非原子类型

说明 :指定递归验证关联的对象;如用户对象中有个地址对象属性,若是想在验证用户对象时一块儿验证地址对象的话,在地址对象上加@Valid注解便可级联验证

 

注意:此处只列出Hibernate Validator提供的大部分验证约束注解,请参考hibernate validator官方文档了解其余验证约束注解和进行自定义的验证约束注解定义

 

错误消息

n概述

当验证出错时,咱们须要给用户展现错误消息告诉用户出错的缘由,所以咱们要为验证约束注解指定错误消息。错误消息是经过在验证约束注解的message属性指定。验证约束注解指定错误消息有以下两种方式:

一、硬编码错误消息;

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

n硬编码错误消息

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

@NotNull(message = "用户名不能为空")

@Length(min=5, max=20, message="用户名长度必须在5-20之间")

@Pattern(regexp = "^[a-zA-Z_]\\w{4,19}$", message = "用户名必须以字母下划线开头,可由字母数字下划线组成")

private String username;

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

一、在国际化场景下,须要对不一样的国家显示不一样的错误消息;

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

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

这个最为推荐的方式就是直接使用Spring的MessageSource Bean进行消息的匹配和管理,前面HelloWorld就是使用的这个方式,这儿就不赘述了。

 

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

n当咱们在一个功能处理方法上须要验证多个模型对象时,须要经过以下形式来获取验证结果:

@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对象来保存验证结果,其方法体内部可使用这两个验证结果对象来选择出错时跳转的页面。

 

n在错误页面,须要针对不一样的模型来显示错误消息 :

<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>

 

而后就能够测试了。

 

异常处理的支持

nSpring Web MVC对异常处理的支持有两种方式

1:一种是直接实现本身的HandlerExceptionResolver ,一般用来实现全局异常控制, Spring Web MVC已经有了一个缺省的实现:SimpleMappingExceptionResolver,

2:用注解的方式实现一个专门用于处理异常的Controller——ExceptionHandler,一般用来在Controller内部实现更个性化点异常处理方式,灵活性更高。

n自定义实现的方式,只须要实现HandlerExceptionResolver接口便可,示例以下:

public class MyExceptionHandler implements HandlerExceptionResolver{

public ModelAndView resolveException(HttpServletRequest request,

HttpServletResponse response, Object handler, Exception ex) {

if(ex instanceof NullPointerException){

//这里就写如何处理,好比:记日志

System.out.println("now is NullPointer");

}else if(ex instanceof ArrayIndexOutOfBoundsException){

//这里就写如何处理,好比:记日志

}

return new ModelAndView("exception");

}

}

 

n上述类须要在spring的配置文件中配置,示例以下:

<bean id= "myExceptionHandler" class= "cn.javass.springmvc.exception.MyExceptionHandler"/>

n说明:

1:上述示例的resolveException方法的第四个参数,就是具体的例外类型

2:若是该方法返回了null,则Spring会继续寻找其余的实现了HandlerExceptionResolver 接口的Bean。也就是说,Spring会搜索全部注册在其环境中的实现了HandlerExceptionResolver接口的Bean,逐个执行,直到返回了一个ModelAndView对象。

 

 

n固然咱们也能够直接使用Spring提供的SimpleMappingExceptionResolver类,示例以下:

<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> 

    <!-- 定义默认的异常处理页面,当该异常类型的注册时使用 --> 

    <property name="defaultErrorView" value="exception"></property> 

    <!-- 定义异常处理页面用来获取异常信息的变量名,默认名为exception --> 

    <property name="exceptionAttribute" value="ex"></property> 

<!-- 定义须要特殊处理的异常,用类名或彻底路径名做为key,异常显示的页面名做为值 --> 

    <property name="exceptionMappings"> 

        <props> 

            <prop key="NullPointerException">error/nullPage</prop> 

            <prop key="ArrayIndexOutOfBoundsException">error/ArrayIndexOutOfBoundsPage</prop> 

        </props> 

    </property> 

</bean>

 

n说明:出了错事后,例外信息会以ex为key存放在request属性里面,所以在错误页面就能够经过request的属性取到例外对象了

 

n典型的异常显示页面示例以下:

<%@ page language= "java" contentType= "text/html; charset=UTF-8" pageEncoding= "UTF-8"%>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

 

<% Exception ex = (Exception)request.getAttribute("ex"); %>

<H2>Exception: <%= ex.getMessage()%></H2>

 

n基于@ExceptionHandler的异常处理

该方法须要定义在Controller内部,而后建立一个方法并用@ExceptionHandler注解来修饰用来处理异常,这个方法基本和 @RequestMapping修饰的方法差很少,只是能够多一个类型为Exception的参数,@ExceptionHandler中能够添加一个或多个异常的类型,若是为空的话则认为能够触发全部的异常类型错误。

nController中示例以下:

@ExceptionHandler(value={NullPointerException.class,ArrayIndexOutOfBoundsException.class})

public String exceptionExecute(Exception ex,HttpServletRequest request){

request.setAttribute("ex", ex);

if(ex instanceof NullPointerException){

//这里就写如何处理,好比:记日志

System.out.println("now is NullPointer2");

return "error/nullPage2";

}else if(ex instanceof ArrayIndexOutOfBoundsException){

//这里就写如何处理,好比:记日志

}

return "error/nullPage2";

}

 

n三种处理方式都有的运行顺序

1:优先在本身Controller里面寻找@ExceptionHandler,看能不能处理

2:若是不能,而后在Spring中,寻找实现HandlerExceptionResolver 的Bean

3:对于多个都能处理的Bean,则按照配置的前后顺序进行处理

4:只要有一个能处理,不返回null,那么就结束

相关文章
相关标签/搜索