聲明式數據驗證

聲明式數據驗證

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

相關文章
相關標籤/搜索