天天看點

Spring4新特性——內建Bean Validation 1.1(JSR-349)到SpringMVC

bean validation 1.1目前實作是hibernate validator 5,且spring4才支援。接下來我們從以下幾個方法講解bean validation 1.1,當然不一定是新特性:

 內建bean validation 1.1到springmvc

 分組驗證、分組順序及級聯驗證

 消息中使用el表達式

 方法參數/傳回值驗證

 自定義驗證規則

 類級别驗證器

 腳本驗證器

 cross-parameter,跨參數驗證

混合類級别驗證器和跨參數驗證器

組合多個驗證注解

本地化

因為大多數時候驗證都配合web架構使用,而且很多朋友都咨詢過如分組/跨參數驗證,是以本文介紹下這些,且是和springmvc架構內建的例子,其他使用方式(比如內建到jpa中)可以參考其官方文檔:

1.1、項目搭建

首先添加hibernate validator 5依賴:

Spring4新特性——內建Bean Validation 1.1(JSR-349)到SpringMVC

<dependency>  

    <groupid>org.hibernate</groupid>  

    <artifactid>hibernate-validator</artifactid>  

    <version>5.0.2.final</version>  

</dependency>  

如果想在消息中使用el表達式,請確定el表達式版本是 2.2或以上,如使用tomcat6,請到tomcat7中拷貝相應的el jar包到tomcat6中。

Spring4新特性——內建Bean Validation 1.1(JSR-349)到SpringMVC

    <groupid>javax.el</groupid>  

    <artifactid>javax.el-api</artifactid>  

    <version>2.2.4</version>  

    <scope>provided</scope>  

請確定您使用的web容器有相應版本的el jar包。

對于其他pom依賴請下載下傳附件中的項目參考。

1.2、spring mvc配置檔案(spring-mvc.xml):

Spring4新特性——內建Bean Validation 1.1(JSR-349)到SpringMVC

<!-- 指定自己定義的validator -->  

<mvc:annotation-driven validator="validator"/>  

<!-- 以下 validator  conversionservice 在使用 mvc:annotation-driven 會 自動注冊-->  

<bean id="validator" class="org.springframework.validation.beanvalidation.localvalidatorfactorybean">  

    <property name="providerclass" value="org.hibernate.validator.hibernatevalidator"/>  

    <!-- 如果不加預設到 使用classpath下的 validationmessages.properties -->  

    <property name="validationmessagesource" ref="messagesource"/>  

</bean>  

<!-- 國際化的消息資源檔案(本系統中主要用于顯示/錯誤消息定制) -->  

<bean id="messagesource" class="org.springframework.context.support.reloadableresourcebundlemessagesource">  

    <property name="basenames">  

        <list>  

            <!-- 在web環境中一定要定位到classpath 否則預設到目前web應用下找  -->  

            <value>classpath:messages</value>  

            <value>classpath:org/hibernate/validator/validationmessages</value>  

        </list>  

    </property>  

    <property name="usecodeasdefaultmessage" value="false"/>  

    <property name="defaultencoding" value="utf-8"/>  

    <property name="cacheseconds" value="60"/>  

此處主要把bean validation的消息查找委托給spring的messagesource。

1.3、實體驗證注解:

Spring4新特性——內建Bean Validation 1.1(JSR-349)到SpringMVC

public class user implements serializable {  

    @notnull(message = "{user.id.null}")  

    private long id;  

    @notempty(message = "{user.name.null}")  

    @length(min = 5, max = 20, message = "{user.name.length.illegal}")  

    @pattern(regexp = "[a-za-z]{5,20}", message = "{user.name.illegal}")  

    private string name;  

    @notnull(message = "{user.password.null}")  

    private string password;  

}  

1.4、錯誤消息檔案messages.properties:

Spring4新特性——內建Bean Validation 1.1(JSR-349)到SpringMVC

user.id.null=使用者編号不能為空  

user.name.null=使用者名不能為空  

user.name.length.illegal=使用者名長度必須在5到20之間  

user.name.illegal=使用者名必須是字母  

user.password.null=密碼不能為空  

1.5、控制器

Spring4新特性——內建Bean Validation 1.1(JSR-349)到SpringMVC

@controller  

public class usercontroller {  

    @requestmapping("/save")  

    public string save(@valid user user, bindingresult result) {  

        if(result.haserrors()) {  

            return "error";  

        }  

        return "success";  

    }  

1.6、錯誤頁面:

Spring4新特性——內建Bean Validation 1.1(JSR-349)到SpringMVC

<spring:hasbinderrors name="user">  

    <c:if test="${errors.fielderrorcount > 0}">  

        字段錯誤:<br/>  

        <c:foreach items="${errors.fielderrors}" var="error">  

            <spring:message var="message" code="${error.code}" arguments="${error.arguments}" text="${error.defaultmessage}"/>  

            ${error.field}------${message}<br/>  

        </c:foreach>  

    </c:if>  

    <c:if test="${errors.globalerrorcount > 0}">  

        全局錯誤:<br/>  

        <c:foreach items="${errors.globalerrors}" var="error">  

            <c:if test="${not empty message}">  

                ${message}<br/>  

            </c:if>  

</spring:hasbinderrors>  

1.7、測試

Spring4新特性——內建Bean Validation 1.1(JSR-349)到SpringMVC

name------使用者名必須是字母  

name------使用者名長度必須在5到20之間  

password------密碼不能為空  

id------使用者編号不能為空  

基本的內建就完成了。

如上測試有幾個小問題:

1、錯誤消息順序,大家可以看到name的錯誤消息順序不是按照書寫順序的,即不确定;

2、我想顯示如:使用者名【zhangsan】必須在5到20之間;其中我們想動态顯示:使用者名、min,max;而不是寫死了;

3、我想在修改的時候隻驗證使用者名,其他的不驗證怎麼辦。

接下來我們挨着試試吧。

如果我們想在新增的情況驗證id和name,而修改的情況驗證name和password,怎麼辦? 那麼就需要分組了。

首先定義分組接口:

Spring4新特性——內建Bean Validation 1.1(JSR-349)到SpringMVC

public interface first {  

public interface second {  

分組接口就是兩個普通的接口,用于辨別,類似于java.io.serializable。

接着我們使用分組接口辨別實體:

Spring4新特性——內建Bean Validation 1.1(JSR-349)到SpringMVC

    @notnull(message = "{user.id.null}", groups = {first.class})  

    @length(min = 5, max = 20, message = "{user.name.length.illegal}", groups = {second.class})  

    @pattern(regexp = "[a-za-z]{5,20}", message = "{user.name.illegal}", groups = {second.class})  

    @notnull(message = "{user.password.null}", groups = {first.class, second.class})  

驗證時使用如:

Spring4新特性——內建Bean Validation 1.1(JSR-349)到SpringMVC

@requestmapping("/save")  

public string save(@validated({second.class}) user user, bindingresult result) {  

    if(result.haserrors()) {  

        return "error";  

    return "success";  

即通過@validate注解辨別要驗證的分組;如果要驗證兩個的話,可以這樣@validated({first.class, second.class})。

接下來我們來看看通過分組來指定順序;還記得之前的錯誤消息嗎? user.name會顯示兩個錯誤消息,而且順序不确定;如果我們先驗證一個消息;如果不通過再驗證另一個怎麼辦?可以通過@groupsequence指定分組驗證順序:

Spring4新特性——內建Bean Validation 1.1(JSR-349)到SpringMVC

@groupsequence({first.class, second.class, user.class})  

    @length(min = 5, max = 20, message = "{user.name.length.illegal}", groups = {first.class})  

通過@groupsequence指定驗證順序:先驗證first分組,如果有錯誤立即傳回而不會驗證second分組,接着如果first分組驗證通過了,那麼才去驗證second分組,最後指定user.class表示那些沒有分組的在最後。這樣我們就可以實作按順序驗證分組了。

另一個比較常見的就是級聯驗證:

如:

Spring4新特性——內建Bean Validation 1.1(JSR-349)到SpringMVC

public class user {  

    @valid   

    @convertgroup(from=first.class, to=second.class)  

    private organization o;  

 1、級聯驗證隻要在相應的字段上加@valid即可,會進行級聯驗證;@convertgroup的作用是當驗證o的分組是first時,那麼驗證o的分組是second,即分組驗證的轉換。

假設我們需要顯示如:使用者名[name]長度必須在[min]到[max]之間,此處大家可以看到,我們不想把一些資料寫死,如name、min、max;此時我們可以使用el表達式。

Spring4新特性——內建Bean Validation 1.1(JSR-349)到SpringMVC

@length(min = 5, max = 20, message = "{user.name.length.illegal}", groups = {first.class})  

錯誤消息:

Spring4新特性——內建Bean Validation 1.1(JSR-349)到SpringMVC

user.name.length.illegal=使用者名長度必須在{min}到{max}之間  

其中我們可以使用{驗證注解的屬性}得到這些值;如{min}得到@length中的min值;其他的也是類似的。

到此,我們還是無法得到出錯的那個輸入值,如name=zhangsan。此時就需要el表達式的支援,首先确定引入el jar包且版本正确。然後使用如:

Spring4新特性——內建Bean Validation 1.1(JSR-349)到SpringMVC

user.name.length.illegal=使用者名[${validatedvalue}]長度必須在5到20之間  

使用如el表達式:${validatedvalue}得到輸入的值,如zhangsan。當然我們還可以使用如${min > 1 ? '大于1' : '小于等于1'},及在el表達式中也能拿到如@length的min等資料。

另外我們還可以拿到一個java.util.formatter類型的formatter變量進行格式化:

Spring4新特性——內建Bean Validation 1.1(JSR-349)到SpringMVC

${formatter.format("%04d", min)}  

有時候預設的規則可能還不夠,有時候還需要自定義規則,比如屏蔽關鍵詞驗證是非常常見的一個功能,比如在發帖時文章中不允許出現admin等關鍵詞。

1、定義驗證注解

Spring4新特性——內建Bean Validation 1.1(JSR-349)到SpringMVC

package com.sishuok.spring4.validator;  

import javax.validation.constraint;  

import javax.validation.payload;  

import java.lang.annotation.documented;  

import java.lang.annotation.retention;  

import java.lang.annotation.target;  

import static java.lang.annotation.elementtype.*;  

import static java.lang.annotation.retentionpolicy.*;  

/** 

 * <p>user: zhang kaitao 

 * <p>date: 13-12-15 

 * <p>version: 1.0 

 */  

@target({ field, method, parameter, annotation_type })  

@retention(runtime)  

//指定驗證器  

@constraint(validatedby = forbiddenvalidator.class)  

@documented  

public @interface forbidden {  

    //預設錯誤消息  

    string message() default "{forbidden.word}";  

    //分組  

    class<?>[] groups() default { };  

    //負載  

    class<? extends payload>[] payload() default { };  

    //指定多個時使用  

    @target({ field, method, parameter, annotation_type })  

    @retention(runtime)  

    @documented  

    @interface list {  

        forbidden[] value();  

2、 定義驗證器

Spring4新特性——內建Bean Validation 1.1(JSR-349)到SpringMVC

import org.hibernate.validator.internal.engine.constraintvalidation.constraintvalidatorcontextimpl;  

import org.springframework.beans.factory.annotation.autowired;  

import org.springframework.context.applicationcontext;  

import org.springframework.util.stringutils;  

import javax.validation.constraintvalidator;  

import javax.validation.constraintvalidatorcontext;  

import java.io.serializable;  

public class forbiddenvalidator implements constraintvalidator<forbidden, string> {  

    private string[] forbiddenwords = {"admin"};  

    @override  

    public void initialize(forbidden constraintannotation) {  

        //初始化,得到注解資料  

    public boolean isvalid(string value, constraintvalidatorcontext context) {  

        if(stringutils.isempty(value)) {  

            return true;  

        for(string word : forbiddenwords) {  

            if(value.contains(word)) {  

                return false;//驗證失敗  

            }  

        return true;  

 驗證器中可以使用spring的依賴注入,如注入:@autowired  private applicationcontext ctx; 

3、使用

Spring4新特性——內建Bean Validation 1.1(JSR-349)到SpringMVC

    @forbidden()  

4、當我們在送出name中含有admin的時候會輸出錯誤消息:

Spring4新特性——內建Bean Validation 1.1(JSR-349)到SpringMVC

forbidden.word=您輸入的資料中有非法關鍵詞  

問題來了,哪個詞是非法的呢?bean validation 和 hibernate validator都沒有提供相應的api提供這個資料,怎麼辦呢?通過跟蹤代碼,發現一種不是特别好的方法:我們可以覆寫org.hibernate.validator.internal.metadata.descriptor.constraintdescriptorimpl實作(即複制一份代碼放到我們的src中),然後覆寫buildannotationparametermap方法;

Spring4新特性——內建Bean Validation 1.1(JSR-349)到SpringMVC

private map<string, object> buildannotationparametermap(annotation annotation) {  

    ……  

    //将collections.unmodifiablemap( parameters );替換為如下語句  

    return parameters;  

 即允許這個資料可以修改;然後在forbiddenvalidator中:

Spring4新特性——內建Bean Validation 1.1(JSR-349)到SpringMVC

for(string word : forbiddenwords) {  

    if(value.contains(word)) {  

        ((constraintvalidatorcontextimpl)context).getconstraintdescriptor().getattributes().put("word", word);  

        return false;//驗證失敗  

通過((constraintvalidatorcontextimpl)context).getconstraintdescriptor().getattributes().put("word", word);添加自己的屬性;放到attributes中的資料可以通過${} 擷取。然後消息就可以變成:

Spring4新特性——內建Bean Validation 1.1(JSR-349)到SpringMVC

forbidden.word=您輸入的資料中有非法關鍵詞【{word}】  

這種方式不是很友好,但是可以解決我們的問題。

典型的如密碼、确認密碼的場景,非常常用;如果沒有這個功能我們需要自己寫代碼來完成;而且經常重複自己。接下來看看bean validation 1.1如何實作的。

6.1、定義驗證注解

Spring4新特性——內建Bean Validation 1.1(JSR-349)到SpringMVC

import javax.validation.constraints.notnull;  

@target({ type, annotation_type})  

@constraint(validatedby = checkpasswordvalidator.class)  

public @interface checkpassword {  

    string message() default "";  

        checkpassword[] value();  

6.2、 定義驗證器

Spring4新特性——內建Bean Validation 1.1(JSR-349)到SpringMVC

import com.sishuok.spring4.entity.user;  

public class checkpasswordvalidator implements constraintvalidator<checkpassword, user> {  

    public void initialize(checkpassword constraintannotation) {  

    public boolean isvalid(user user, constraintvalidatorcontext context) {  

        if(user == null) {  

        //沒有填密碼  

        if(!stringutils.hastext(user.getpassword())) {  

            context.disabledefaultconstraintviolation();  

            context.buildconstraintviolationwithtemplate("{password.null}")  

                    .addpropertynode("password")  

                    .addconstraintviolation();  

            return false;  

        if(!stringutils.hastext(user.getconfirmation())) {  

            context.buildconstraintviolationwithtemplate("{password.confirmation.null}")  

                    .addpropertynode("confirmation")  

        //兩次密碼不一樣  

        if (!user.getpassword().trim().equals(user.getconfirmation().trim())) {  

            context.buildconstraintviolationwithtemplate("{password.confirmation.error}")  

其中我們通過disabledefaultconstraintviolation禁用預設的限制;然後通過buildconstraintviolationwithtemplate(消息模闆)/addpropertynode(所屬屬性)/addconstraintviolation定義我們自己的限制。

6.3、使用

Spring4新特性——內建Bean Validation 1.1(JSR-349)到SpringMVC

@checkpassword()  

 放到類頭上即可。

Spring4新特性——內建Bean Validation 1.1(JSR-349)到SpringMVC

@scriptassert(script = "_this.password==_this.confirmation", lang = "javascript", alias = "_this", message = "{password.confirmation.error}")  

通過腳本驗證是非常簡單而且強大的,lang指定腳本語言(請參考javax.script.scriptenginemanager jsr-223),alias是在腳本驗證中user對象的名字,但是大家會發現一個問題:錯誤消息怎麼顯示呢? 在springmvc 中會添加到全局錯誤消息中,這肯定不是我們想要的,我們改造下吧。

7.1、定義驗證注解

Spring4新特性——內建Bean Validation 1.1(JSR-349)到SpringMVC

import org.hibernate.validator.internal.constraintvalidators.scriptassertvalidator;  

import static java.lang.annotation.elementtype.type;  

import static java.lang.annotation.retentionpolicy.runtime;  

@target({ type })  

@constraint(validatedby = {propertyscriptassertvalidator.class})  

public @interface propertyscriptassert {  

    string message() default "{org.hibernate.validator.constraints.scriptassert.message}";  

    string lang();  

    string script();  

    string alias() default "_this";  

    string property();  

    @target({ type })  

    public @interface list {  

        propertyscriptassert[] value();  

和scriptassert沒什麼差別,隻是多了個property用來指定出錯後給實體的哪個屬性。

7.2、驗證器

Spring4新特性——內建Bean Validation 1.1(JSR-349)到SpringMVC

import javax.script.scriptexception;  

import javax.validation.constraintdeclarationexception;  

import com.sishuok.spring4.validator.propertyscriptassert;  

import org.hibernate.validator.constraints.scriptassert;  

import org.hibernate.validator.internal.util.contracts;  

import org.hibernate.validator.internal.util.logging.log;  

import org.hibernate.validator.internal.util.logging.loggerfactory;  

import org.hibernate.validator.internal.util.scriptengine.scriptevaluator;  

import org.hibernate.validator.internal.util.scriptengine.scriptevaluatorfactory;  

import static org.hibernate.validator.internal.util.logging.messages.messages;  

public class propertyscriptassertvalidator implements constraintvalidator<propertyscriptassert, object> {  

    private static final log log = loggerfactory.make();  

    private string script;  

    private string languagename;  

    private string alias;  

    private string property;  

    private string message;  

    public void initialize(propertyscriptassert constraintannotation) {  

        validateparameters( constraintannotation );  

        this.script = constraintannotation.script();  

        this.languagename = constraintannotation.lang();  

        this.alias = constraintannotation.alias();  

        this.property = constraintannotation.property();  

        this.message = constraintannotation.message();  

    public boolean isvalid(object value, constraintvalidatorcontext constraintvalidatorcontext) {  

        object evaluationresult;  

        scriptevaluator scriptevaluator;  

        try {  

            scriptevaluatorfactory evaluatorfactory = scriptevaluatorfactory.getinstance();  

            scriptevaluator = evaluatorfactory.getscriptevaluatorbylanguagename( languagename );  

        catch ( scriptexception e ) {  

            throw new constraintdeclarationexception( e );  

            evaluationresult = scriptevaluator.evaluate( script, value, alias );  

            throw log.geterrorduringscriptexecutionexception( script, e );  

        if ( evaluationresult == null ) {  

            throw log.getscriptmustreturntrueorfalseexception( script );  

        if ( !( evaluationresult instanceof boolean ) ) {  

            throw log.getscriptmustreturntrueorfalseexception(  

                    script,  

                    evaluationresult,  

                    evaluationresult.getclass().getcanonicalname()  

            );  

        if(boolean.false.equals(evaluationresult)) {  

            constraintvalidatorcontext.disabledefaultconstraintviolation();  

            constraintvalidatorcontext  

                    .buildconstraintviolationwithtemplate(message)  

                    .addpropertynode(property)  

        return boolean.true.equals( evaluationresult );  

    private void validateparameters(propertyscriptassert constraintannotation) {  

        contracts.assertnotempty( constraintannotation.script(), messages.parametermustnotbeempty( "script" ) );  

        contracts.assertnotempty( constraintannotation.lang(), messages.parametermustnotbeempty( "lang" ) );  

        contracts.assertnotempty( constraintannotation.alias(), messages.parametermustnotbeempty( "alias" ) );  

        contracts.assertnotempty( constraintannotation.property(), messages.parametermustnotbeempty( "property" ) );  

        contracts.assertnotempty( constraintannotation.message(), messages.parametermustnotbeempty( "message" ) );  

和之前的類級别驗證器類似,就不多解釋了,其他代碼全部拷貝自org.hibernate.validator.internal.constraintvalidators.scriptassertvalidator。

7.3、使用

Spring4新特性——內建Bean Validation 1.1(JSR-349)到SpringMVC

@propertyscriptassert(property = "confirmation", script = "_this.password==_this.confirmation", lang = "javascript", alias = "_this", message = "{password.confirmation.error}")  

和之前的差別就是多了個property,用來指定出錯時給哪個字段。 這個相對之前的類級别驗證器更通用一點。

直接看示例;

Spring4新特性——內建Bean Validation 1.1(JSR-349)到SpringMVC

<bean class="org.springframework.validation.beanvalidation.methodvalidationpostprocessor">  

    <property name="validator" ref="validator"/>  

8.2、service 

Spring4新特性——內建Bean Validation 1.1(JSR-349)到SpringMVC

@validated  

@service  

public class userservice {  

    @crossparameter  

    public void changepassword(string password, string confirmation) {  

通過@validated注解userservice表示該類中有需要進行方法參數/傳回值驗證;   @crossparameter注解方法表示要進行跨參數驗證;即驗證password和confirmation是否相等。

8.3、驗證注解 

Spring4新特性——內建Bean Validation 1.1(JSR-349)到SpringMVC

//省略import  

@constraint(validatedby = crossparametervalidator.class)  

@target({ method, constructor, annotation_type })  

public @interface crossparameter {  

    string message() default "{password.confirmation.error}";  

8.4、驗證器 

Spring4新特性——內建Bean Validation 1.1(JSR-349)到SpringMVC

@supportedvalidationtarget(validationtarget.parameters)  

public class crossparametervalidator implements constraintvalidator<crossparameter, object[]> {  

    public void initialize(crossparameter constraintannotation) {  

    public boolean isvalid(object[] value, constraintvalidatorcontext context) {  

        if(value == null || value.length != 2) {  

            throw new illegalargumentexception("must have two args");  

        if(value[0] == null || value[1] == null) {  

        if(value[0].equals(value[1])) {  

        return false;  

其中@supportedvalidationtarget(validationtarget.parameters)表示驗證參數; value将是參數清單。 

8.5、使用

Spring4新特性——內建Bean Validation 1.1(JSR-349)到SpringMVC

@requestmapping("/changepassword")  

public string changepassword(  

        @requestparam("password") string password,  

        @requestparam("confirmation") string confirmation, model model) {  

    try {  

        userservice.changepassword(password, confirmation);  

    } catch (constraintviolationexception e) {  

        for(constraintviolation violation : e.getconstraintviolations()) {  

            system.out.println(violation.getmessage());  

調用userservice.changepassword方法,如果驗證失敗将抛出constraintviolationexception異常,然後得到constraintviolation,調用getmessage即可得到錯誤消息;然後到前台顯示即可。

從以上來看,不如之前的使用友善,需要自己對錯誤消息進行處理。 下一節我們也寫個腳本方式的跨參數驗證器。

9.1、驗證注解

Spring4新特性——內建Bean Validation 1.1(JSR-349)到SpringMVC

@constraint(validatedby = {  

        crossparameterscriptassertclassvalidator.class,  

        crossparameterscriptassertparametervalidator.class  

})  

@target({ type, field, parameter, method, constructor, annotation_type })  

public @interface crossparameterscriptassert {  

    string message() default "error";  

    string property() default "";  

    constrainttarget validationappliesto() default constrainttarget.implicit;  

}   

此處我們通過@constraint指定了兩個驗證器,一個類級别的,一個跨參數的。validationappliesto指定為constrainttarget.implicit,表示隐式自動判斷。

9.2、驗證器

請下載下傳源碼檢視

9.3、使用

9.3.1、類級别使用

Spring4新特性——內建Bean Validation 1.1(JSR-349)到SpringMVC

@crossparameterscriptassert(property = "confirmation", script = "_this.password==_this.confirmation", lang = "javascript", alias = "_this", message = "{password.confirmation.error}")  

指定property即可,其他和之前的一樣。

9.3.2、跨參數驗證

Spring4新特性——內建Bean Validation 1.1(JSR-349)到SpringMVC

@crossparameterscriptassert(script = "args[0] == args[1]", lang = "javascript", alias = "args", message = "{password.confirmation.error}")  

public void changepassword(string password, string confirmation) {  

通過args[0]==args[1] 來判斷是否相等。

這樣,我們的驗證注解就自動适應兩種驗證規則了。  

有時候,可能有好幾個注解需要一起使用,此時就可以使用組合驗證注解

Spring4新特性——內建Bean Validation 1.1(JSR-349)到SpringMVC

@target({ field})  

@notnull(message = "{user.name.null}")  

@length(min = 5, max = 20, message = "{user.name.length.illegal}")  

@pattern(regexp = "[a-za-z]{5,20}", message = "{user.name.length.illegal}")  

@constraint(validatedby = { })  

public @interface composition {  

這樣我們驗證時隻需要:

Spring4新特性——內建Bean Validation 1.1(JSR-349)到SpringMVC

@composition()  

private string name;  

簡潔多了。 

即根據不同的語言選擇不同的錯誤消息顯示。

1、本地化解析器

Spring4新特性——內建Bean Validation 1.1(JSR-349)到SpringMVC

<bean id="localeresolver" class="org.springframework.web.servlet.i18n.cookielocaleresolver">  

    <property name="cookiename" value="locale"/>  

    <property name="cookiemaxage" value="-1"/>  

    <property name="defaultlocale" value="zh_cn"/>  

此處使用cookie存儲本地化資訊,當然也可以選擇其他的,如session存儲。

2、設定本地化資訊的攔截器

Spring4新特性——內建Bean Validation 1.1(JSR-349)到SpringMVC

<mvc:interceptors>  

    <bean class="org.springframework.web.servlet.i18n.localechangeinterceptor">  

        <property name="paramname" value="language"/>  

    </bean>  

</mvc:interceptors>  

即請求參數中通過language設定語言。

3、消息檔案

Spring4新特性——內建Bean Validation 1.1(JSR-349)到SpringMVC

4、 浏覽器輸入

http://localhost:9080/spring4/changepassword?password=1&confirmation=2&language=en_us

轉自:http://jinnianshilongnian.iteye.com/blog/1990081