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,那麼就結束