<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Vincent

    Vicent's blog
    隨筆 - 74, 文章 - 0, 評論 - 5, 引用 - 0
    數據加載中……

    Hibernate Validator 簡介

    在項目的業務屬性中,你是不是要經常驗證屬性的取值范圍呢. 想要了解比較優美的解決方案嗎???????????

    看看Hibernate Validator 是怎么做的吧.一見到她,相信你就會說: Oh God, 這就是我需要的.

    任何獲得Matrix授權的網站,轉載請保留以下作者信息和鏈接:
    作者:icess(作者的blog:http://blog.matrix.org.cn/page/icess)
    關鍵字:Hibernate Validator

    用Annotations 給類或者類的屬性加上約束(constraint),在運行期檢查屬性值是很優雅的.Hibernate Validator就是這樣的一個框架.該框架是十分容易的(就像參考文檔中宣稱的那樣),幾乎沒有什么學習曲線,Validator 是一個驗證框架 不需要和Hibernate的其他部分綁定就可以使用,只要在你的項目中添加Hibernate-annotations.jar庫就可以了.那么下面就讓我們看看怎么使用吧.

    Person.java 類

    /*
    ? *?Created?on?2006-1-12 Person.java
    ? *?@author?
    ? */
    package? test.annotation.validator;

    import? org.hibernate.validator.Length;
    import? org.hibernate.validator.Min;
    import? org.hibernate.validator.Valid;
     

    //@Serializability? //測試自定義約束
    public?class? Person?{

    ?? private? String?name;
    ?? private?int? age;
    ?? private? Address?address;
    ??
    ?? public? Person()?{}
    ??
    ?? @Valid //注意此處
    ?? public? Address?getAddress()?{
    ???? return? address;
    ?? }
    ?? public?void? setAddress(Address?address)?{
    ???? this .address?=?address;
    ?? }
    ??
    ?? @Min(value?=? 1 )
    ?? public?int? getAge()?{
    ???? return? age;
    ?? }
    ?? public?void? setAge( int? age)?{
    ???? this .age?=?age;
    ?? }
    ??
    ?? @Length(min?=? 4 )
    ?? public? String?getName()?{
    ???? return? name;
    ?? }
    ?? public?void? setName(String?name)?{
    ???? this .name?=?name;
    ?? }
    }

     

    Address.java 類

    /*
    ? *?Created?on?2006-1-12 Address.java
    ? *?@author?
    ? */
    package? test.annotation.validator;

    import? org.hibernate.validator.Length;
    import? org.hibernate.validator.Max;
    import? org.hibernate.validator.Min;

    public?class? Address?{

    ?? private? String?street;
    ?? private?int? num;
    ??
    ?? public? Address()?{}
    ??
    ?? @Min(value?=? 1 )
    ?? @Max(value?=? 100 )
    ?? public?int? getNum()?{
    ???? return? num;
    ?? }
    ?? public?void? setNum( int? num)?{
    ???? this .num?=?num;
    ?? }
    ??
    ?? @Length(min?=? 3 ,max?=? 8 )
    ?? public? String?getStreet()?{
    ???? return? street;
    ?? }
    ?? public?void? setStreet(String?street)?{
    ???? this .street?=?street;
    ?? }
    }

    上面是兩個用 Validator Annotations 注釋的 類. 每個屬性都用 約束限制了.? 下面看看測試的類吧:

    TestValidator.java 類

    /*
    ? *?Created?on?2006-1-12
    ? *?@author?icerain
    ? */
    package? test.annotation.validator;

    import? org.hibernate.validator.ClassValidator;
    import? org.hibernate.validator.InvalidValue;


    public?class? TestValidator?{
    ?? public?void? test()?{
    ???? Address?add?=? new? Address();
    ???? add.setNum( 0 );
    ???? add.setStreet( "1" );
    ????
    ???? Person?p?=? new? Person();
    ???? p.setAddress(add);
    ???? p.setAge( 0 );
    ???? p.setName( "ice" );
    ????
    ???? /******************Test?validator?********/

    ??? // 注意該處只驗證了Person 為了說明 @Valid 注釋的使用
    ???? ClassValidator<Person>?classValidator?=? new? ClassValidator<Person>?(Person. class );
    ???? InvalidValue[]?validMessages?=?classValidator.getInvalidValues(p);
    ???? for? (InvalidValue?value?:?validMessages)?{
    ??????
    ???? System.out.println( "InvalidValue?的長度是:"? +?validMessages.length
    ???????? + "?.?驗證消息是:?"? +?value.getMessage()?
    ???????? +? "?.?PropertyPath?是:"? +?value.getPropertyPath()
    ???????? + "?.\n\t?PropertyName?是:?"? +value.getPropertyName()
    ???????? +? "Value?是:?"? +?value.getValue()
    ???????? + "?Bean?是:?" +?value.getBean()
    ???????? + "\n\t?BeanClass?是:"? +?value.getBeanClass());
    ???? }
    ?? }
    ??
    ?? public?static?void? main(String[]?args)?{
    ???? new? TestValidator().test();
    ?? }
    }

     

    程序的輸出如下

    InvalidValue 的長度是:4 . 驗證消息是: 必須大于等于 1 . PropertyPath 是:age .

    PropertyName 是: age. Value 是: 0 Bean 是: test.annotation.validator.Person@dd87b2

    BeanClass 是:class test.annotation.validator.Person

    InvalidValue 的長度是:4 . 驗證消息是: 長度必須介于 4 與 2147483647 之間 . PropertyPath 是:name .

    PropertyName 是: name. Value 是: ice Bean 是: test.annotation.validator.Person@dd87b2

    BeanClass 是:class test.annotation.validator.Person

    InvalidValue 的長度是:4 . 驗證消息是: 必須大于等于 1 . PropertyPath 是:address.num .

    PropertyName 是: num. Value 是: 0 Bean 是: test.annotation.validator.Address@197d257

    BeanClass 是:class test.annotation.validator.Address

    InvalidValue 的長度是:4 . 驗證消息是: 長度必須介于 3 與 8 之間 . PropertyPath 是:address.street .

    PropertyName 是: street. Value 是: 1 Bean 是: test.annotation.validator.Address@197d257

    BeanClass 是:class test.annotation.validator.Address

    可以看出不滿足約束的值都被指出了.

    同時該句: ClassValidator<Person>?classValidator?=?new?ClassValidator<Person>?(Person.class);

    我們只驗證了 Person. 在Person里面的Address的屬性 由于有@Valid Annotations 所以 Address的相關屬性也被機聯驗證了 .

    如果 把 @Valid Annotations 去掉,結果如下:

    InvalidValue 的長度是:2 . 驗證消息是: 必須大于等于 1 . PropertyPath 是:age .

    PropertyName 是: age. Value 是: 0 Bean 是: test.annotation.validator.Person@18fef3d

    BeanClass 是:class test.annotation.validator.Person

    InvalidValue 的長度是:2 . 驗證消息是: 長度必須介于 4 與 2147483647 之間 . PropertyPath 是:name .

    PropertyName 是: name. Value 是: ice Bean 是: test.annotation.validator.Person@18fef3d

    BeanClass 是:class test.annotation.validator.Person

    可以看出 沒有驗證 Address.

    當然了 ,你還可以只驗證一個屬性 , 沒有必要驗證整個類.只需要在調用 classValidator.getInvalidValues(p,"age")方法時 加上你要驗證的屬性就可以了.如我們只想驗證age 屬性 把代碼改為如下所示:

    InvalidValue[] validMessages = classValidator.getInvalidValues(p,"age"); / /只驗證age 屬性

    運行結果如下:

    InvalidValue 的長度是:1 . 驗證消息是: 必須大于等于 1 . PropertyPath 是:age .

    PropertyName 是: age. Value 是: 0 Bean 是: test.annotation.validator.Person@1457cb

    BeanClass 是:class test.annotation.validator.Person

    只是驗證了 age 屬性.

    怎么樣 ,很簡單吧. 關于 Hibernate Validator 內建的驗證Annotations 大家可以看看 API 或者 參考文檔(中文版我正在翻譯中 請訪問我的 Blog 獲得最新信息).

    如果你要寫自己的約束呢 , 你不用擔心 ,這也是很容易的. 任何約束有兩部分組成: [約束描述符 即注釋]the constraint descriptor (the annotation) 和[約束validator 即 實現類] the constraint validator (the implementation class).下面我們擴展Hibernate Test suit 中的一個Test 來講解一下.

    首先: 要聲明一個 constraint descriptor .如下:

    package? test.annotation.validator;

    import? java.lang.annotation.Documented;
    import?static? java.lang.annotation.ElementType.TYPE;
    import?static? java.lang.annotation.ElementType.FIELD;
    import?static? java.lang.annotation.ElementType.METHOD;
    import? java.lang.annotation.Retention;
    import?static? java.lang.annotation.RetentionPolicy.RUNTIME;
    import? java.lang.annotation.Target;

    import? org.hibernate.validator.ValidatorClass;

    /**
    ? *?Dummy?sample?of?a?bean-level?validation?annotation
    ? *
    ? *? @author? Emmanuel?Bernard
    ? */
    @ValidatorClass(SerializabilityValidator. class )
    @Target({METHOD,FIELD,TYPE})
    @Retention(RUNTIME)
    @Documented
    public? @interface?Serializability?{
    ?? int? num()? default? 11 ;
    ?? String?message()? default? "bean?must?be?serialiable" ;
    }

    @ValidatorClass(SerializabilityValidator. class ) 指出了 constraint validator 類.

    @Target({METHOD,FIELD,TYPE})
    @Retention(RUNTIME)
    @Documented????????????????

    這幾個我就不用解釋了吧.

    Serializability?里面聲明了一個 message 顯示約束的提示信息. num 只是為了說明一個方面 在這里面沒有實際用途用 .

    然后就是 實現一個 constraint validator 類 該類要實現Validator<ConstraintAnnotation>.這里是SerializabilityValidator.java 如下:

    //$Id:?SerializabilityValidator.java,v?1.3?2005/11/17?18:12:11?epbernard?Exp?$
    package? test.annotation.validator;

    import? java.io.Serializable;

    import? org.hibernate.validator.Validator;

    /**
    ? *?Sample?of?a?bean-level?validator
    ? *
    ? *? @author? Emmanuel?Bernard
    ? */
    public?class? SerializabilityValidator? implements? Validator<Serializability>,?Serializable?{
    ?? public?boolean? isValid(Object?value)?{
    ??? //這里只是Validator 里面的 實現驗證規則的 方法. value 是要驗證的值.
    ???? System.out.println( "IN?SerializabilityValidator?isValid:" +value.getClass()+ ":?"? +value.toString());
    ???? return? value?instanceof?Serializable;
    ??}

    ??public?void?initialize(Serializability?parameters)?{
    ????//?在這里可以 取得
    constraint descriptor 里面的屬性 如上面我們聲明的 num
    ???? System.out.println( "IN?SerializabilityValidator:?parameters:" +?parameters.num()?);
    ?? }
    }

    然后在你的類中應用@Serializability? 就可以約束一個類實現Serializable 接口了. 如下:

    在我們的Person.java類 添加@Serializability? Annotations ,把Person.java 中的 //@Serializability //測試自定義約束 注釋去掉就ok了.

    運行結果如下:

    InvalidValue 的長度是:3 . 驗證消息是: bean must be serialiable . PropertyPath 是:null .

    PropertyName 是: null. Value 是: test.annotation.validator.Person@1a73d3c Bean 是: test.annotation.validator.Person@1a73d3c

    BeanClass 是:class test.annotation.validator.Person

    現在把Person類實現 java.io.Serializable 接口 則沒有出現 驗證錯誤消息.

    消息的國際化也是很簡單的,把 Serializability? 中的message 改為以{}擴住的 屬性文件的Key就可以了

    public? @interface?Serializability?{
    ?? int? num()? default? 11 ;
    ?? String?message()? default? "{Serializable}"; //"bean?must?be?serialiable"; //消息的國際化
    }

    然后編輯資料文件. 注意 該資源文件中要包括 Hibernate Validator 內建的資源. 可以在該org\hibernate\validator\resources 包里面的資源文件基礎上修改 ,在打包里面 這樣就可以了. 自己打包可能不太方便.你可以把該包里面的文件復制出來.然后放到你自己的項目包下在自己編輯, 該測試中 我是放在 test\resources 包下的.

    然后在 資源文件中添加 Serializable = '''''' 這么一行, 樣例如下:

    #DefaultValidatorMessages.properties (DefaultValidatorMessages_zh.properties 不再列出^_^)

     

    #下面是 Hibernate Validator 內建的國際化消息

    validator.assertFalse= assertion failed

    validator.assertTrue= assertion failed

    validator.future= must be a future date

    validator.length= length must be between {min} and {max}

    validator.max= must be less than or equal to {value}

    validator.min= must be greater than or equal to {value}

    validator.notNull= may not be null

    validator.past= must be a past date

    validator.pattern= must match "{regex}"

    validator.range= must be between {min} and {max}

    validator.size= size must be between {min} and {max}

    #下面是自定義的消息

    Serializable= Bean not Serializable? //加上自己定義的國際化消息.

    在構造 ClassValidator 時要添上 資源文件 如下:(在測試類中)

    ClassValidator<Person> classValidator = new ClassValidator<Person> (Person.class,ResourceBundle.getBundle("test.resources.DefaultValidatorMessages"));//加載資源

    這樣就可以了 .? 當然 你還可以 更改 Hibernate Validator 的消息(不是在上面的資源文件中直接修改 validator.length = ... 等等 ) , 還記得 Validator 注釋中有個 message 元素嗎? 你以前用的都是默認值,現在你可以該為你自己定義的了. 如:validator.length 我把他改為 "該字符串的長度不符合規定范圍范圍". 在資源文件中添加一行鍵值屬性對(key定義為 "myMsg")如下:

    myMsg=該字符串的長度不符合規定范圍范圍

    并且還要在 @Length 注釋中提供message的引用的key 如下 @Length(min = 4,message = "{ myMsg }")

    再一次運行測試 ,我們就可以看到上面兩條自定義綁定的消息了 .如下:

    InvalidValue 的長度是:3 . 驗證消息是: Bean 不是 可 Serializable . PropertyPath 是:null .
    PropertyName 是: null. Value 是: test.annotation.validator.Person@1bd4722 Bean 是: test.annotation.validator.Person@1bd4722
    BeanClass 是:class test.annotation.validator.Person


    InvalidValue 的長度是:3 . 驗證消息是: 該字符串的長度不符合規定范圍范圍 . PropertyPath 是:name .
    PropertyName 是: name. Value 是: ice Bean 是: test.annotation.validator.Person@1bd4722
    BeanClass 是:class test.annotation.validator.Person

    怎么樣,比你想象的簡單吧.

    OK 上面我們討論了 Hibernate Validator 的主要用法: 但是 該框架有什么用呢? ^_^

    看到這里其實不用我在多說了 大家都知道怎么用,什么時候用. 作為一篇介紹性文章我還是在此給出一個最常用的例子吧,更好的使用方式大家慢慢挖掘吧.

    比如 : 你現在在開發一個人力資源(HR)系統 (其實是我們ERP課程的一個作業 ^_^), 里面要處理大量的數據,尤其是在輸入各種資料時 如 登記員工信息. 如果你公司的員工的年齡要求是18 -- 60 那么你所輸入的年齡就不能超出這個范圍. 你可能會說這很容易啊 , 不用Validator就可以解決啊.這保持數據前驗證就可以啦 如if ( e.getAge() > 60 || e.getAge() < 18 ) ........ 給出錯誤信息 然后提示重新輸入不就OK啦 用得著 興師動眾的來個第三方框架嗎?

    是啊 當就驗證這一個屬性時, 沒有必要啊 ! 但是一個真正的HR 系統,會只有一個屬性要驗證嗎? 恐怕要有N多吧

    你要是每一個都那樣 寫一段驗證代碼 是不是很煩啊 ,況且也不方便代碼重用. 現在考慮一些 Validator 是不是更高效啊,攔截到 約束違例的 屬性 就可以直接得到 國際化的消息 可以把該消息顯示到一個彈出對話框上 提示更正? !

    Validator的用處不只這一種 ,你可以想到如何用呢 ! 歡迎發表你的高見!!

    OK 到此 我們的 Hibernate Validator 之旅就要先告一段落了 . 希望這是令你心曠神怡的一次寒冬之旅,

    把你學到的應用到你的項目中吧,一定會提高你的生產率的. 相信我 ,沒錯的? ^_^ !

    posted on 2006-08-22 11:20 Binary 閱讀(239) 評論(0)  編輯  收藏 所屬分類: Hibernate

    主站蜘蛛池模板: 亚洲最大黄色网站| 男人和女人高潮免费网站 | 免费a级毛片无码a∨免费软件| 亚洲αv久久久噜噜噜噜噜| 99久久久国产精品免费无卡顿| 亚洲国产成人久久精品大牛影视| 亚洲小说区图片区另类春色| 免费精品国产自产拍在| 国产亚洲精品美女久久久久久下载| 亚洲午夜无码久久久久| 欧洲精品成人免费视频在线观看| 九九久久国产精品免费热6| 亚洲高清不卡视频| 亚洲AV蜜桃永久无码精品| 美丽姑娘免费观看在线观看中文版| 亚洲风情亚Aⅴ在线发布| 国产V亚洲V天堂A无码| 日本高清色本免费现在观看| 久久大香香蕉国产免费网站| 亚洲AV无码一区二区乱子仑| 亚洲欧洲一区二区| 亚洲国产成人影院播放| 1000部拍拍拍18勿入免费视频下载| 中美日韩在线网免费毛片视频| 亚洲xxxxxx| 亚洲VA中文字幕不卡无码| 国产免费怕怕免费视频观看| 又黄又爽又成人免费视频| 免费精品久久天干天干| 国产亚洲Av综合人人澡精品| 亚洲一区免费在线观看| 亚洲精品无码久久久久| 国产jizzjizz免费视频| 99久久精品日本一区二区免费| 国产在线观a免费观看| 色婷婷亚洲一区二区三区| 亚洲不卡视频在线观看| 亚洲免费视频网站| 亚洲色欲色欲www在线丝| 亚洲av无码成人精品区在线播放| 西西大胆无码视频免费|