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,那么就结束