數據驗證框架 Apache BVal 簡介

hvkt5303 8年前發布 | 21K 次閱讀 Java開發

來自: http://blog.csdn.net/zhangxin09/article/details/50600575


Apache BVal源碼)是實體數據驗證 Java Bean Validation 的參考實現。Apache BVal 提供了 JSR 303 規范中所有內置 constraint 的實現,用于對 Bean 中的字段的值進行約束定義、描述和驗證。若單單說 JSR 規范大渣可能還不清楚,但做過 POJO 的 Hibernate Validator 注解的朋友就知道是啥,——那為什么不使用主流的 Hibernate Validator 呢?因為這貨凈是個壓縮包都已經 13mb 了(盡管可以有文檔、源碼其他在內),BVal 才只有 400 多 kb,而我只需要服務端驗證而已,——天真的孩紙傷不起啊。俺的 ORM 也是 Mybatis 的,務求盡可能地輕量級。

Spring MVC 3.x 雖然自帶了驗證器 Validatior,可以在控制器中對表單提交的數據進行驗證,但這個驗證器是極其弱,因為你需要完全手工編碼 if (null) else warn("不能空數據"),——太變態了(入下面的例子)——我們需要框架來減輕費時耗力的勞動,于是這類驗證框架出現了。

import org.springframework.validation.Errors;  
    import org.springframework.validation.ValidationUtils;  
    import org.springframework.validation.Validator;  

    public class UserValidator implements Validator {  

        public boolean supports(Class<?> clazz) {  
           // TODO Auto-generated method stub  
           return User.class.equals(clazz);  
        }  

        public void validate(Object obj, Errors errors) {  
           // TODO Auto-generated method stub  
           ValidationUtils.rejectIfEmpty(errors, "username", null, "Username is empty.");  
           User user = (User) obj;  
           if (null == user.getPassword() || "".equals(user.getPassword()))  
               errors.rejectValue("password", null, "Password is empty.");  
        }  

    }

而我們理想的是這樣的,在 POJO 身上聲明驗證條件的注解:

import javax.validation.constraints.Min;  
import javax.validation.constraints.NotNull;  
import org.hibernate.validator.constraints.NotBlank;  

public class User {  
    private String username;    
    private String password;  
    private int age;  

    @NotBlank(message="用戶名不能為空")  
    public String getUsername() {  
       return username;  
    }  
    public void setUsername(String username) {  
       this.username = username;  
    }  

    @NotNull(message="密碼不能為null")  
    public String getPassword() {  
       return password;  
    }  
    public void setPassword(String password) {  
       this.password = password;  
    }  

    @Min(value=10, message="年齡的最小值為10")  
    public int getAge() {  
       return age;  
    }  
    public void setAge(int age) {  
       this.age = age;  
    }  
}

如果用 Apache BVal 是怎么做的呢?首先準備一下 jar 包:

接著,我們仍舊離不開 Spring,在 MVC 的 xml 配置文件中加入以下:

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

<!-- 數據驗證 Validator bean -->
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
    <property name="providerClass" value="org.apache.bval.jsr.ApacheValidationProvider" />
</bean>
<!-- // -->

這是一種全局的配置方式,我們注入 Bval 的驗證器,另外,還要讓 MVC 打開注解驅動。加上了 <mvn:annotation-driven/> 之后 Spring 會自動檢測 classpath 下的 JSR-303 提供者并自動啟用對 JSR-303 的支持。然后就可以在 POJO 中添加注解,而且要在控制器中聲明 bean 的驗證,如下例的 @Valid T news,否則 Bval 不會起作用。

/**
 * 新建 
 * @return
 */
@RequestMapping(method = RequestMethod.POST)
public String create(@Valid T news,  BindingResult result,Model model) {
    System.out.println("新建");
    if (result.hasErrors()) {
        LOGGER.info("create error!");
    }else{
        LOGGER.info("create ok!");
    }
    news.setService(getService());
    try {
        getService().create(news);
        model.addAttribute("newlyId", news.getId());
    } catch (ServiceException e) {
        model.addAttribute("errMsg", e.toString());
    }

    return "common/entity/json_cud";
}

一定要注意的是,控制器方法的參數順序。Binding Result 必須在 Bean 后面。這是 Spring MVC 的約定。MVC 對控制器其他參數的順序沒什么規定,唯獨這個 BindingResult 作了如此規定。目的是為了可以允許有多個 bean,于是也就有多個 BindingResult。

怎么處理錯誤就不詳細說了,不同場景下要求不同。

可否自定義驗證條件?我還沒試,應該可以參考 Hibernate Validator 的做法。下面這篇文章說得很詳細。

《Springmvc validator 驗證的使用》

 本文由用戶 hvkt5303 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!