SpringMVC驗證框架Validation特殊用法

基本用法不說了,網上例子不少,這裏主要介紹下比較特殊狀況下使用的方法。java

1. 分組web

有的時候,咱們對一個實體類須要有多中驗證方式,在不一樣的狀況下使用不一樣驗證方式,好比說對於一個實體類來的id來講,保存的時候是不須要的,對於更新時是必須的,能夠以下配置:spring

public class UserModel {

    @NotNull(message = "{id.empty}", groups = {First.class})
    private int id;
    @NotNull(message = "{username.empty}", groups = {First.class, Second.class})
    private String username;
    @NotNull(message = "{content.empty}", groups = {First.class, Second.class})
    private String content;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }
}

public interface First {}
public interface Second {}

經過 groups 對驗證進行分組spring-mvc

在controler中的代碼以下:mvc

@RequestMapping(value = "/save.action", method = RequestMethod.POST)
public String save(@Validated({Second.class}) UserModel userModel, BindingResult result) {
    if (result.hasErrors()) {
        return "validate/error";
    }
    return "redirect:/success";
}

@RequestMapping(value = "/update.action", method = RequestMethod.POST)
public String update(@Validated({First.class, Second.class}) UserModel user, BindingResult result) {
    if (result.hasErrors()) {
        return "validate/error";
    }
    return "redirect:/success";
}

2. 組序列app

默認狀況下,不一樣組別的約束驗證是無序的,然而在某些狀況下,約束驗證的順序卻很重要,以下面兩個例子:(1)第二個組中的約束驗證依賴於一個穩定狀態來運行,而這個穩定狀態是由第一個組來進行驗證的。(2)某個組的驗證比較耗時,CPU 和內存的使用率相對比較大,最優的選擇是將其放在最後進行驗證。所以,在進行組驗證的時候尚需提供一種有序的驗證方式,這就提出了組序列的概念。ide

一個組能夠定義爲其餘組的序列,使用它進行驗證的時候必須符合該序列規定的順序。在使用組序列驗證的時候,若是序列前邊的組驗證失敗,則後面的組將再也不給予驗證。測試

下例中聲明瞭組 GroupA.class,GroupB.class 和 Group.class,其中 default,GroupA,GroupB 均爲 Group 的序列。this

public interface GroupA {}
public interface GroupB {}

@GroupSequence({Default.class, GroupA.class, GroupB.class})
public interface Group {}

public class User {

    @NotEmpty(message = "firstname may be empty")
    private String firstname;
    @NotEmpty(message = "middlename may be empty", groups = Default.class)
    private String middlename;
    @NotEmpty(message = "lastname may be empty", groups = GroupA.class)
    private String lastname;
    @NotEmpty(message = "country may be empty", groups = GroupB.class)
    private String country;
}

3. 驗證多個對象spa

當咱們在一個功能處理方法上須要驗證多個模型對象時,須要經過以下形式來獲取驗證結果:

@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對象來保存驗證結果,其方法體內部可使用這兩個驗證結果對象來選擇出錯時跳轉的頁面或處理的邏輯。

4. Junit測試

當自定義拓展Validation時,可使用以下方法進行測試:

@Test
public void testValidate() {
    AnnotationDescriptor<EqualsAny> descriptor = new AnnotationDescriptor<EqualsAny>(EqualsAny.class);
    EqualsAny equalsAny = AnnotationFactory.create(descriptor);
    EqualsAnyValidator equalsAnyValidator = new EqualsAnyValidator();
    equalsAnyValidator.initialize(equalsAny);
    Assert.assertTrue(equalsAnyValidator.isValid("123", null));
}

另外再講一點Spring對自定義JSR-303限制類型支持的新特性,那就是Spring支持往ConstraintValidator裏面注入bean對象。例如在EqualsAnyValidator中利用@Resource註解注入其餘Bean對象。

補充:

Spring MVC配置文件(spring-mvc.xml)

<!-- 指定本身定義的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>  

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

錯誤消息文件messages.properties:

user.id.null=用戶編號不能爲空  
user.name.null=用戶名不能爲空  
user.name.length.illegal=用戶名長度必須在5到20之間  
user.name.illegal=用戶名必須是字母  
user.password.null=密碼不能爲空  

消息中使用EL表達式

假設咱們須要顯示如:用戶名[NAME]長度必須在[MIN]到[MAX]之間,此處你們能夠看到,咱們不想把一些數據寫死,如NAME、MIN、MAX;此時咱們可使用EL表達式。

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

錯誤消息:

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

使用如EL表達式:${validatedValue}獲得輸入的值 :

user.name.length.illegal=用戶名[${validatedValue}]長度必須在{min}到{max}之間

另外咱們還能夠拿到一個java.util.Formatter類型的formatter變量進行格式化:

${formatter.format("%04d", min)}
相關文章
相關標籤/搜索