Hibernate Validator深入剖析
在向大家詳細(xì)介紹Hibernate Validator之前,首先讓大家了解下Commons Validator 也有自己的缺陷,然后全面介紹Hibernate Validator。
更好的方法Hibernate Validator
進(jìn)行驗(yàn)證的一種典型方法是對(duì)簡(jiǎn)單的驗(yàn)證使用 Commons Validator,并在控制器中編寫其他一些驗(yàn)證邏輯。Commons Validator 可以生成 JavaScript 來對(duì)視圖中的驗(yàn)證進(jìn)行處理。但是 Commons Validator 也有自己的缺陷:它只能處理簡(jiǎn)單的驗(yàn)證問題,并且將驗(yàn)證的信息都保存到了 XML 文件中。Commons Validator 被設(shè)計(jì)用來與 Struts 一起使用,而且沒有提供一種簡(jiǎn)單的方法在應(yīng)用程序?qū)娱g重用驗(yàn)證的聲明。
在規(guī)劃有效性驗(yàn)證策略時(shí),選擇在錯(cuò)誤發(fā)生時(shí)簡(jiǎn)單地處理這些錯(cuò)誤是遠(yuǎn)遠(yuǎn)不夠的。一種良好的設(shè)計(jì)同時(shí)還要通過生成一個(gè)友好的用戶界面來防止出現(xiàn)錯(cuò)誤。采用預(yù)先進(jìn)行的方法進(jìn)行驗(yàn)證可以極大地增強(qiáng)用戶對(duì)于應(yīng)用程序的理解。不幸的是,Commons Validator 并沒有對(duì)此提供支持。假設(shè)希望 HTML 文件設(shè)置文本域的 maxlength 屬性來與驗(yàn)證匹配,或者在文本域之后放上一個(gè)百分號(hào)(%)來表示要輸入百分比的值。通常,這些信息都被硬編寫到 HTML 文檔中了。如果決定修改 name 屬性來支持 75 個(gè)字符,而不是 60 個(gè)字符,那么需要改動(dòng)多少地方呢?在很多應(yīng)用程序中,通常都需要:
◆更新 DDL 來增大數(shù)據(jù)庫(kù)列的長(zhǎng)度(通過 HibernateDoclet、 hbm.xml 或 Hibernate Annotations)。
◆更新 Commons Validator XML 文件將***值增加到 75。
◆更新所有與這個(gè)域有關(guān)的 HTML 表單,以修改 maxlength 屬性。
更好的方法是使用 Hibernate Validator。驗(yàn)證的定義都被通過注釋 添加到了模型層中,同時(shí)還有對(duì)所包含的驗(yàn)證處理的支持。如果選擇充分利用所有的 Hibernate,這個(gè) Validator 就可以在 DAO 和 DBMS 層也提供驗(yàn)證。在下面給出的樣例代碼中,將使用 reflection 和 JSP 2.0 標(biāo)簽文件多執(zhí)行一個(gè)步驟,從而充分利用注釋 為視圖層動(dòng)態(tài)生成代碼。這可以清除在視圖中使用的硬編寫的業(yè)務(wù)邏輯。
dateOfBirth 被注釋為 NotNull 和過去的日期。 Hibernate 的 DDL 生成代碼對(duì)這個(gè)列添加了一個(gè)非空約束,以及一個(gè)要求日期必須是之前日期的檢查約束。e-mail 地址也是非空的,必須匹配 e-mail 地址的格式。這會(huì)生成一個(gè)非空約束,但是不會(huì)生成匹配這種格式的檢查約束。
- public class Contact implements Serializable {
- public static final int MAX_FIRST_NAME = 30;
- public static final int MAX_MIDDLE_NAME = 1;
- public static final int MAX_LAST_NAME = 30;
- private String fname;
- private String mi;
- private String lname;
- private Date dateOfBirth;
- private String emailAddress;
- private Address address;
- public Contact() {
- this.address = new Address();
- }
- @Valid
- @Embedded
- public Address getAddress() {
- return address;
- }
- public void setAddress(Address a) {
- if (a == null) {
- address = new Address();
- } else {
- aaddress = a;
- }
- }
- @NotNull
- @Length(min = 1, max = MAX_FIRST_NAME)
- @Column(name = "fname")
- public String getFirstname() {
- return fname;
- }
- public void setFirstname(String fname) {
- this.fname = fname;
- }
- @Length(min = 1, max = MAX_MIDDLE_NAME)
- @Column(name = "mi")
- public String getMi() {
- return mi;
- }
- public void setMi(String mi) {
- this.mi = mi;
- }
- @NotNull
- @Length(min = 1, max = MAX_LAST_NAME)
- @Column(name = "lname")
- public String getLastname() {
- return lname;
- }
如果需要,Hibernate DAO 實(shí)現(xiàn)也可以使用 Validation Annotations。所需做的是在 hibernate.cfg.xml 文件中指定基于 Hibernate 事件的驗(yàn)證規(guī)則。(更多信息請(qǐng)參考 Hibernate Validator 的文檔;可以在 參考資料 一節(jié)中找到相關(guān)的鏈接)。如果真地希望抄近路,您可以只捕獲服務(wù)或控制器中的 InvalidStateException 異常,并循環(huán)遍歷 InvalidValue 數(shù)組。
【編輯推薦】