【補充】Hibernate validator使用和自定義validator及整合Spring MVC

Hibernate validator使用

導入validation-api-xxx.jar 以及  hibernate-validator-xxx.Final.jar

須要檢查的java bean html

Entity.javajava

import javax.validation.constraints.Max;  
import org.hibernate.validator.constraints.Length;  
public class Entity {  
    @Max(value=3)//最大值爲3  
    private int age;  
    @Length(max=1) //字符串長度最大爲1,hibernate 擴展的  
    private String name;  
    public int getAge() {  
        return age;  
    }  
    public void setAge(int age) {  
        this.age = age;  
    }  
    public String getName() {  
        return name;  
    }  
    public void setName(String name) {  
        this.name = name;  
    }  
}

值校驗的測試類git

import java.util.Set;  
import javax.validation.ConstraintViolation;  
import javax.validation.Validation;  
import javax.validation.Validator;  
import javax.validation.ValidatorFactory;  
public class Tv {  
    public static void main(String[] args) {  
        ValidatorFactory factory = Validation.buildDefaultValidatorFactory();  
        Validator validator = factory.getValidator();  
  
        Entity entity = new Entity();  
        entity.setAge(12);  
        entity.setName("admin");  
        Set<ConstraintViolation<Entity>> constraintViolations = validator.validate(entity);  
        for (ConstraintViolation<Entity> constraintViolation : constraintViolations) {  
            System.out.println("對象屬性:"+constraintViolation.getPropertyPath());  
            System.out.println("國際化key:"+constraintViolation.getMessageTemplate());  
            System.out.println("錯誤信息:"+constraintViolation.getMessage());  
        }  
  
    }  
}

輸出結果web


這裏有一個國際化的key值,國際化文件在org.hibernate.validator下面的一系列的properites文件裏面,若是須要自定義那麼能夠拷貝出來放在src目錄下正則表達式

 

這裏咱們拷貝一個出來,新增一個key爲maxlength=字符串長度最大不能超過{max} ,可使用動態參數,這裏的max值就是註解裏面設定的值spring

而後修改Entity.java,name屬性的message="{maxlength}"api

@Length(max=1,message="{maxlength}") //{maxlength}對應配置文件中的key. 必須有{}  
    private String name;

再次運行結果以下mvc

自定義validator

首先自定義一個註解CannotContainSpaces (不能包含空格)app

import java.lang.annotation.Documented;  
import java.lang.annotation.Retention;  
import java.lang.annotation.Target;  
import javax.validation.Constraint;  
import javax.validation.Payload;  
  
@Constraint(validatedBy = CannotContainSpacesValidator.class) //具體的實現  
@Target( { java.lang.annotation.ElementType.METHOD,  
    java.lang.annotation.ElementType.FIELD })  
@Retention(java.lang.annotation.RetentionPolicy.RUNTIME)  
@Documented  
public @interface CannotContainSpaces {  
    String message() default "{Cannot.contain.Spaces}"; //提示信息,能夠寫死,能夠填寫國際化的key  
      
    int length() default 5;  
      
    //下面這兩個屬性必須添加  
    Class<?>[] groups() default {};  
    Class<? extends Payload>[] payload() default {};  
      
}

具體實現類CannotContainSpacesValidator.javajsp

import javax.validation.ConstraintValidator;  
import javax.validation.ConstraintValidatorContext;  
  
public class CannotContainSpacesValidator implements ConstraintValidator<CannotContainSpaces, String> {  
    private int len;  
    /** 
     * 初始參數,獲取註解中length的值 
     */  
    @Override  
    public void initialize(CannotContainSpaces arg0) {  
        this.len = arg0.length();  
    }  
  
    @Override  
    public boolean isValid(String str, ConstraintValidatorContext constraintValidatorContext) {  
        if(str != null){  
            if(str.indexOf(" ") < 0){  
                return true;  
            }  
        }else{  
            constraintValidatorContext.disableDefaultConstraintViolation();//禁用默認的message的值  
            //從新添加錯誤提示語句  
            constraintValidatorContext  
            .buildConstraintViolationWithTemplate("字符串不能爲空").addConstraintViolation();  
        }  
        return false;  
    }  
  
}

使用的時候直接註解到對象的屬性上面就能夠了

@CannotContainSpaces  
    private String name;

測試當name包含空格的時候 entity.setName("xx xx");

 

 

當name爲null的時候

 

 

整合Spring MVC

首先新增配置文件內容(實體類裏面的註解與上面徹底相同)

<!-- 國際化配置 -->  
<bean id="localeResolver"  
    class="org.springframework.web.servlet.i18n.CookieLocaleResolver" />  
<bean id="messageSource"  
    class="org.springframework.context.support.ReloadableResourceBundleMessageSource">  
    <property name="basenames">  
        <list>  
            <value>classpath:messages/messages</value>  
            <value>classpath:messages/Validation</value>  
        </list>  
    </property>  
    <property name="useCodeAsDefaultMessage" value="true" />  
</bean>  
<!-- 註冊驗證器 -->  
<mvc:annotation-driven validator="validator" />   
 
<!-- 註冊驗證器 補充方式二-->
<!--
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
    <property name="webBindingInitializer">
        <ref bean="webBindingInitializer" />
    </property>
</bean>

<bean id="webBindingInitializer" class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
    <property name="validator" ref="validator" />
</bean>
-->  

<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">    
      <property name="providerClass" value="org.hibernate.validator.HibernateValidator"/>    
      <!-- 這裏配置將使用上面國際化配置的messageSource -->  
      <property name="validationMessageSource" ref="messageSource"/>    
  </bean>

在Spring MVC 控制器中方法屬性以下

/** 
         * 這裏的@Valid必須書寫, bindingResult參數也必須書寫在後面,不然驗證不經過就會返回400 
         * @param entity 
         * @param result 
         * @return 
         */  
        @RequestMapping(value="/valid")  
        public String validator(@Valid Entity entity,BindingResult result){  
            if(result.hasErrors()){  
                //若是嚴重沒有經過,跳轉提示  
                return "error";  
            }else{  
                //繼續業務邏輯  
            }  
            return "success";  
        }

error.jsp中以下

導入spring標籤庫

<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<!-- commandName 控制器參數中對象名稱 -->  
<form:form commandName="entity">  
    <!-- 顯示所有錯誤信息用* -->  
    <form:errors path="*"/>  
</form:form>  
<hr/>  
<!-- 對象名稱.屬性名稱    若是該對象的指定屬性沒有經過校驗那麼顯示錯誤信息(根據當前語言顯示不一樣國家的文字) -->  
<form:errors path="entity.name"/>

校驗註解說明

Bean Validation 中內置的 constraint     
@Null   被註釋的元素必須爲 null     
@NotNull    被註釋的元素必須不爲 null     
@AssertTrue     被註釋的元素必須爲 true     
@AssertFalse    被註釋的元素必須爲 false     
@Min(value)     被註釋的元素必須是一個數字,其值必須大於等於指定的最小值     
@Max(value)     被註釋的元素必須是一個數字,其值必須小於等於指定的最大值     
@DecimalMin(value)  被註釋的元素必須是一個數字,其值必須大於等於指定的最小值     
@DecimalMax(value)  被註釋的元素必須是一個數字,其值必須小於等於指定的最大值     
@Size(max=, min=)   被註釋的元素的大小必須在指定的範圍內     
@Digits (integer, fraction)     被註釋的元素必須是一個數字,其值必須在可接受的範圍內     
@Past   被註釋的元素必須是一個過去的日期     
@Future     被註釋的元素必須是一個未來的日期     
@Pattern(regex=,flag=)  被註釋的元素必須符合指定的正則表達式     
Hibernate Validator 附加的 constraint     
@NotBlank(message =)   驗證字符串非null,且長度必須大於0     
@Email  被註釋的元素必須是電子郵箱地址     
@Length(min=,max=)  被註釋的字符串的大小必須在指定的範圍內     
@NotEmpty   被註釋的字符串的必須非空     
@Range(min=,max=,message=)  被註釋的元素必須在合適的範圍內

注意
①:在整合Spring MVC的時候,ValidationMessages_zh_CN.properties文件若是不是放在src目錄下(如上面放在src/messages/下面) 那麼在屬性文件裏面不能使用動態參數獲取了(如${length} ${max}這些). 必須將hibernate validation的國際化屬性所有放到src目錄下面才能夠(不曉得爲何,若是你能解決順便留個言)

②:我這裏使用的是spring 4.1 + hibernate validation 5.1 ,若是你使用的是spring 3.2 須要對於的hibernate validation版本是 4.x的 否則在配置

org.springframework.validation.beanvalidation.LocalValidatorFactoryBean

這個的是會報錯,

 

【補充】

        當SpringMVC將接收到的參數映射成modelAttribute時,可能會出現異常,好比參數是字符型,接收對象的屬性是數值型,則轉換異常。此時SpringMVC也會把異常信息放到BindingResult中。可是異常信息沒有通過國際化處理,若是要轉換爲國際化的信息,則要本身處理,方式以下:

        經過BindingResult獲取到FieldError對象error,在經過messageSource.getMessage()方法獲取到國際化後的異常信息

@Autowired
private MessageSource messageSource;
...

FieldError error = bindingResult.getFieldError("fieldName");
String errorMessage = messageSource.getMessage(error, Locale.getDefault());
相關文章
相關標籤/搜索