<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, 評(píng)論 - 5, 引用 - 0
    數(shù)據(jù)加載中……

    2006年9月18日

    一、 橋梁(Bridge)模式

         摘要: 一、?橋梁(Bridge)模式 橋梁模式是一個(gè)非常有用的模式,也是比較復(fù)雜的一個(gè)模式。熟悉這個(gè)模式對(duì)于理解面向?qū)ο蟮脑O(shè)計(jì)原則,包括"開-閉"原則(OCP)以及組合/聚合復(fù)用原則(CARP)都很有幫助。理解好這兩個(gè)原則,有助于形成正確的設(shè)計(jì)思想和培養(yǎng)良好的設(shè)計(jì)風(fēng)格。 注:《Java與模式》一書認(rèn)為Bridge模式不是一個(gè)使用頻率很高的模式,我不太贊同,我認(rèn)為Bridge模式中...  閱讀全文

    posted @ 2006-09-18 13:38 Binary 閱讀(3284) | 評(píng)論 (2)編輯 收藏

    2006年9月1日

    Hibernate Validator 簡(jiǎn)介

    在項(xiàng)目的業(yè)務(wù)屬性中,你是不是要經(jīng)常驗(yàn)證屬性的取值范圍呢. 想要了解比較優(yōu)美的解決方案嗎???????????

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

    任何獲得Matrix授權(quán)的網(wǎng)站,轉(zhuǎn)載請(qǐng)保留以下作者信息和鏈接:
    作者:icess(作者的blog:http://blog.matrix.org.cn/page/icess)
    關(guān)鍵字:Hibernate Validator

    用Annotations 給類或者類的屬性加上約束(constraint),在運(yùn)行期檢查屬性值是很優(yōu)雅的.Hibernate Validator就是這樣的一個(gè)框架.該框架是十分容易的(就像參考文檔中宣稱的那樣),幾乎沒有什么學(xué)習(xí)曲線,Validator 是一個(gè)驗(yàn)證框架 不需要和Hibernate的其他部分綁定就可以使用,只要在你的項(xiàng)目中添加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? //測(cè)試自定義約束
    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;
    ?? }
    }

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

    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?********/

    ??? // 注意該處只驗(yàn)證了Person 為了說明 @Valid 注釋的使用
    ???? ClassValidator<Person>?classValidator?=? new? ClassValidator<Person>?(Person. class );
    ???? InvalidValue[]?validMessages?=?classValidator.getInvalidValues(p);
    ???? for? (InvalidValue?value?:?validMessages)?{
    ??????
    ???? System.out.println( "InvalidValue?的長(zhǎng)度是:"? +?validMessages.length
    ???????? + "?.?驗(yàn)證消息是:?"? +?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 的長(zhǎng)度是:4 . 驗(yàn)證消息是: 必須大于等于 1 . PropertyPath 是:age .

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

    BeanClass 是:class test.annotation.validator.Person

    InvalidValue 的長(zhǎng)度是:4 . 驗(yàn)證消息是: 長(zhǎng)度必須介于 4 與 2147483647 之間 . PropertyPath 是:name .

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

    BeanClass 是:class test.annotation.validator.Person

    InvalidValue 的長(zhǎng)度是:4 . 驗(yàn)證消息是: 必須大于等于 1 . PropertyPath 是:address.num .

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

    BeanClass 是:class test.annotation.validator.Address

    InvalidValue 的長(zhǎng)度是:4 . 驗(yàn)證消息是: 長(zhǎng)度必須介于 3 與 8 之間 . PropertyPath 是:address.street .

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

    BeanClass 是:class test.annotation.validator.Address

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

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

    我們只驗(yàn)證了 Person. 在Person里面的Address的屬性 由于有@Valid Annotations 所以 Address的相關(guān)屬性也被機(jī)聯(lián)驗(yàn)證了 .

    如果 把@Valid Annotations 去掉,結(jié)果如下:

    InvalidValue 的長(zhǎng)度是:2 . 驗(yàn)證消息是: 必須大于等于 1 . PropertyPath 是:age .

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

    BeanClass 是:class test.annotation.validator.Person

    InvalidValue 的長(zhǎng)度是:2 . 驗(yàn)證消息是: 長(zhǎng)度必須介于 4 與 2147483647 之間 . PropertyPath 是:name .

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

    BeanClass 是:class test.annotation.validator.Person

    可以看出 沒有驗(yàn)證 Address.

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

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

    運(yùn)行結(jié)果如下:

    InvalidValue 的長(zhǎng)度是:1 . 驗(yàn)證消息是: 必須大于等于 1 . PropertyPath 是:age .

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

    BeanClass 是:class test.annotation.validator.Person

    只是驗(yàn)證了 age 屬性.

    怎么樣 ,很簡(jiǎn)單吧. 關(guān)于 Hibernate Validator 內(nèi)建的驗(yàn)證Annotations 大家可以看看 API 或者 參考文檔(中文版我正在翻譯中 請(qǐng)?jiān)L問我的 Blog 獲得最新信息).

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

    首先: 要聲明一個(gè) 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????????????????

    這幾個(gè)我就不用解釋了吧.

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

    然后就是 實(shí)現(xiàn)一個(gè) constraint validator 類 該類要實(shí)現(xiàn)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 里面的 實(shí)現(xiàn)驗(yàn)證規(guī)則的 方法. value 是要驗(yàn)證的值.
    ???? 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()?);
    ?? }
    }

    然后在你的類中應(yīng)用@Serializability? 就可以約束一個(gè)類實(shí)現(xiàn)Serializable 接口了. 如下:

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

    運(yùn)行結(jié)果如下:

    InvalidValue 的長(zhǎng)度是:3 . 驗(yàn)證消息是: 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

    現(xiàn)在把Person類實(shí)現(xiàn) java.io.Serializable 接口 則沒有出現(xiàn) 驗(yàn)證錯(cuò)誤消息.

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

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

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

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

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

     

    #下面是 Hibernate Validator 內(nèi)建的國際化消息

    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? //加上自己定義的國際化消息.

    在構(gòu)造 ClassValidator 時(shí)要添上 資源文件 如下:(在測(cè)試類中)

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

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

    myMsg=該字符串的長(zhǎng)度不符合規(guī)定范圍范圍

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

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

    InvalidValue 的長(zhǎng)度是:3 . 驗(yàn)證消息是: 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 的長(zhǎng)度是:3 . 驗(yàn)證消息是: 該字符串的長(zhǎng)度不符合規(guī)定范圍范圍 . PropertyPath 是:name .
    PropertyName 是: name. Value 是: ice Bean 是: test.annotation.validator.Person@1bd4722
    BeanClass 是:class test.annotation.validator.Person

    怎么樣,比你想象的簡(jiǎn)單吧.

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

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

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

    是啊 當(dāng)就驗(yàn)證這一個(gè)屬性時(shí), 沒有必要啊 ! 但是一個(gè)真正的HR 系統(tǒng),會(huì)只有一個(gè)屬性要驗(yàn)證嗎? 恐怕要有N多吧

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

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

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

    把你學(xué)到的應(yīng)用到你的項(xiàng)目中吧,一定會(huì)提高你的生產(chǎn)率的. 相信我 ,沒錯(cuò)的? ^_^ !

    posted @ 2006-09-01 14:05 Binary 閱讀(458) | 評(píng)論 (0)編輯 收藏

    Hibernate Annotations 實(shí)戰(zhàn)(二)

    -- hbm.xml 與 Annotations 性能比較

    任何獲得Matrix授權(quán)的網(wǎng)站,轉(zhuǎn)載請(qǐng)保留以下作者信息和鏈接:
    作者:icess(作者的blog:http://blog.matrix.org.cn/page/icess)
    關(guān)鍵字:Hibernate Validator

    我在前面一篇文章<Hibernate Annotations 實(shí)戰(zhàn)-- 從 hbm.xml 到 Annotations>:

    中,有很多開發(fā)者在談?wù)撝刑岬?有沒有必要從 hbm.xml 往 Annotations 上轉(zhuǎn)移. 那么在這篇文章中我們就來討論一下 hbm.xml 與 Annotations的優(yōu)缺點(diǎn),看看那種情況最適合你.

    首先,討論一下 xml 配置文件的優(yōu)點(diǎn), 個(gè)人認(rèn)為主要優(yōu)點(diǎn)就是當(dāng)你改變底層配置時(shí) 不需要改變和重新編譯代碼,只需要在xml 中更改就可以了,例如 Hibernate.cfg.xml 當(dāng)你要更改底層數(shù)據(jù)庫時(shí), 只要更改配置文件就可以了.Hibernate會(huì)為你做好別的事情.

    那么xml的缺點(diǎn)呢,個(gè)人認(rèn)為有以下幾點(diǎn):

    • 描述符多,不容易記憶,掌握 要深入了解還有看DTD文件

    • 無法做自動(dòng)校驗(yàn),需要人工查找

    • 讀取和解析xml配置要消耗一定時(shí)間,導(dǎo)致應(yīng)用啟動(dòng)慢,不便于測(cè)試和維護(hù)

    • 當(dāng)系統(tǒng)很大時(shí),大量的xml文件難以管理

    • 運(yùn)行中保存xml配置需要消耗額外的內(nèi)存

    • 在O/R Mapping的時(shí)候需要在java文件和xml配置文件之間交替,增大了工作量

    其中第一 二點(diǎn) 借助于先進(jìn)的IDE 可能不是什么問題. 但是對(duì)初學(xué)者還是個(gè)問題 ^_^.

     

    下面我們看看 Annotations的 特性吧! 可以解決xml遇到的問題,有以下優(yōu)點(diǎn)

    • 描述符減少。以前在xml配置中往往需要描述java屬性的類型,關(guān)系等等。而元數(shù)據(jù)本身就是java語言,從而省略了大量的描述符

    • 編譯期校驗(yàn)。錯(cuò)誤的批注在編譯期間就會(huì)報(bào)錯(cuò)。

    • 元數(shù)據(jù)批注在java代碼中,避免了額外的文件維護(hù)工作

    • 元數(shù)據(jù)被編譯成java bytecode,消耗的內(nèi)存少,讀取也很快,利于測(cè)試和維護(hù)

    關(guān)于 映射文件是使用 hbm.xml 文件還是使用 Annotations 我們來看看2者的性能吧. 先聲明一下,個(gè)人認(rèn)為映射文件一旦配置好就不會(huì)在很大程度上改變了.所以使用xml文件并不會(huì)帶來很大的好處.如果你認(rèn)為 映射文件在你的項(xiàng)目中也經(jīng)常變化,比如一列String數(shù)據(jù) ,今天你使用 length="16" 明天你認(rèn)為 該數(shù)據(jù)的長(zhǎng)度應(yīng)該更長(zhǎng)才能滿足業(yè)務(wù)需求 于是改為length="128" 等等類似的問題 . 如果你經(jīng)常有這方面的變動(dòng)的話,下面的比較你可以不用看了 , 你應(yīng)該使用 xml文件 因?yàn)锳nnotations 無法很好的滿足你的要求.

    現(xiàn)在讓我們就來看看2者的性能比較吧.

    (說明: 這里只是比較查找 插入 的時(shí)間快慢,沒有比較除運(yùn)行時(shí)間以外的其他性能,如 內(nèi)存占用量 等等)

    先來看看測(cè)試程序和配置.

    首先在 Hibernate.cfg.xml 文件中去掉了

    <property name="hibernate.hbm2ddl.auto">update</property>

    這一行, 因?yàn)樵谇懊娴膶?shí)驗(yàn)中以及建立了數(shù)據(jù)庫表了 不再需要更新了.如果你是第一次運(yùn)行該例子 還是要該行的.

    Test.java 如下:

    /*
    ?*?Created?on?2005
    ?*?@author?
    ?*/
    package?test.hibernate.annotation;

    import?org.hibernate.Session;
    import?org.hibernate.Transaction;

    public?class?Test?{
    ??
    ??public?static?void?main(String?[]?args)?{
    ????long?start?=?0;
    ????long?end?=?0;
    ????start?=?System.currentTimeMillis();??//程序開始時(shí)間
    ????
    ????Session?s?=?HibernateUtil.currentSession();
    ????long?mid?=??System.currentTimeMillis();??//初始化完畢的時(shí)間 (可能此時(shí)并沒有初始化完畢^(qū)_^)
    ????
    ????Transaction?tx?=?s.beginTransaction();????
    ????/********************測(cè)試讀取的代碼************************/
    ????Person?p?=?null;
    ????for(int?i?=?1;?i?<=?100;?i?++)?{
    ????p?=?(Person)?s.get(Person.class,?i);
    ????System.out.println(p.getName());
    ????}
    ????System.out.println(p.getName());

    ??? /********************測(cè)試讀取1次的代碼************************/
    ????Person?p?=?null;
    ????p?=?(Person)?s.get(Person.class,?1);
    ????System.out.println(p.getName());
    ????/*********************測(cè)試插入的代碼*************************************/
    ????/*
    ????for?(int?i?=?0;?i?<?100;?i?++)?{
    ??????Person?p?=?new?Person();
    ??????p.setAge(i+1);
    ??????p.setName("icerain"+i);
    ??????p.setSex("male"+i);
    ??????s.save(p);
    ??????s.flush();
    ????}
    ????*/
    ????tx.commit();
    ????HibernateUtil.closeSession();
    ????
    ????end?=?System.currentTimeMillis();?//測(cè)試結(jié)束時(shí)間
    ????System.out.println("String[]?-?start?time:?"?+?start);
    ????System.out.println("String[]?-?end?time:?"?+?end);
    ????System.out.println("Init?time?:?"?+?(mid-start)); // 打印初始化用的時(shí)間
    ????System.out.println("Last?time?is?:"?+(end?-?mid)?); //打印 數(shù)據(jù)操作的時(shí)間
    ????System.out.println("Total?time?:?"?+(end?-?start)); //打印總時(shí)間
    ?
    ?}
    }

    Annotations 包中的Person.java 如下

    package?test.hibernate.annotation;

    import?java.util.LinkedList;
    import?java.util.List;

    import?javax.persistence.AccessType;
    import?javax.persistence.Basic;
    import?javax.persistence.Entity;
    import?javax.persistence.GeneratorType;
    import?javax.persistence.Id;
    import?javax.persistence.Table;
    import?javax.persistence.Transient;

    /**
    ?*?Person?generated?by?hbm2java
    ?*/

    @SuppressWarnings("serial")
    @Entity(access?=?AccessType.PROPERTY)
    @Table
    public?class?Person?implements?java.io.Serializable?{
    ??private?Integer?id;
    ??private?String?name;
    ??private?String?sex;
    ??private?Integer?age;
    ??private?List?list?=?new?LinkedList();

    ??//?Constructors
    ??/**?default?constructor?*/
    ??public?Person()?{
    ??}

    ??/**?constructor?with?id?*/
    ??public?Person(Integer?id)?{
    ????this.id?=?id;
    ??}

    ??//?Property?accessors
    ??@Id(generate=GeneratorType.AUTO)
    ??public?Integer?getId()?{
    ????return?this.id;
    ??}

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

    ??@Basic
    ??public?String?getName()?{
    ????return?this.name;
    ??}

    ??public?void?setName(String?name)?{
    ????this.name?=?name;
    ??}

    ??@Basic
    ??public?String?getSex()?{
    ????return?this.sex;
    ??}

    ??public?void?setSex(String?sex)?{
    ????this.sex?=?sex;
    ??}

    ??@Basic
    ??public?Integer?getAge()?{
    ????return?this.age;
    ??}

    ??public?void?setAge(Integer?age)?{
    ????this.age?=?age;
    ??}
    ??@Transient
    ??public?List?getList()?{
    ????return?list;
    ??}
    ??public?void?setList(List?list)?{
    ????this.list?=?list;
    ??}

    }

    其他的代碼幾乎沒有改變:

    下面的每種類型的測(cè)試都測(cè)試了3次以上, 取中間的測(cè)試時(shí)間.

    測(cè)試機(jī)器配置:

    CPU:? AMD Athlon (xp) 2000+

    內(nèi)存: 784880KB

    硬盤: 三星 SP0812N

    讀取一次??的比較:(單位: 毫秒)

    使用Annotations 的測(cè)試數(shù)據(jù)使用Xml文件的測(cè)試數(shù)據(jù)簡(jiǎn)要說明
    Init time : 2444Init time : 2431測(cè)試前我認(rèn)為該項(xiàng)結(jié)果xml應(yīng)該比較大,要讀取映射文件啊,實(shí)際情況不是這樣,不知道為什么?
    Last time is :62Last time is :85相差比較大不知道為什么?
    Total time : 2506Total time : 2516xml文件總體上慢了一點(diǎn)

    ?? 讀取100次的比較:

    使用Annotations 的測(cè)試數(shù)據(jù)使用Xml文件的測(cè)試數(shù)據(jù)簡(jiǎn)要說明
    Init time : 2437Init time : 2422和前面初始化差不多
    Last time is :438Last time is :484有時(shí)間差
    Total time : 2875Total time : 2906也是xml文件總體上慢了一點(diǎn)

    插入100次的比較:

    使用Annotations 的測(cè)試數(shù)據(jù)使用Xml文件的測(cè)試數(shù)據(jù)簡(jiǎn)要說明
    Init time : 2453Init time : 2469和前面初始化差不多
    Last time is :469Last time is :656有時(shí)間差
    Total time : 2922Total time : 3125也是xml文件總體上慢了一點(diǎn)

    從上面的三次對(duì)比中大家可以看到 初始化的部分幾乎兩者是一樣的, 在數(shù)據(jù)操作上面 使用xml文件 總是比使用Annotations 慢一點(diǎn).在我們只操縱一個(gè)只有幾個(gè)屬性的小持久化類的操作中就有 幾十毫秒的差距. 幾十毫秒在計(jì)算機(jī)中算不算很大 大家應(yīng)該都知道,我就不在多說了.

    總結(jié): 經(jīng)過 xml 文件 和Annotations 的優(yōu)缺點(diǎn)和 性能上的對(duì)比.現(xiàn)在使用那個(gè)作為你持久化映射策略.我相信大家都會(huì)正確選擇的.

    測(cè)試后記: 經(jīng)過多次測(cè)試 感覺有時(shí)候很不穩(wěn)定 ,有的時(shí)候很穩(wěn)定不知道是測(cè)試有問題還是別的問題.大家可以自己測(cè)試一下. 有什么新的發(fā)現(xiàn) 請(qǐng)大家討論討論.

    posted @ 2006-09-01 14:04 Binary 閱讀(340) | 評(píng)論 (0)編輯 收藏

    第一個(gè)Hibernate with Annotation程式

    Hibernate是ORM的解決方案,其底層對(duì)數(shù)據(jù)庫的操作依賴于JDBC,所以您必須先取得JDBC驅(qū)動(dòng)程序,在這邊所使用的是MySQL,所以您必須至 MySQL? Connector/J 取得MySQL的JDBC驅(qū)動(dòng)程序。

    接下來至
    Hibernate 官方網(wǎng)站 取得Hibernate 3.2、Hibernate Annotations 3.2。

    您必須安裝JDK 5.0才可以使用Hibernate Annotations的功能。

    解開Hibernate 3.2的zip檔案后,當(dāng)中的hibernate3.jar是必要的,而在lib目錄中還包括了許多jar檔案,您可以在 Hibernate 3.0官方的參考手冊(cè) 上找到這些jar的相關(guān)說明,其中必要的是 antlr、dom4j、CGLIB、asm、Commons Collections、Commons Logging、 EHCache,Hibernate底層還需要Java Transaction API,所以您還需要jta.jar。

    解開Hibernate Annotations 3.2的zip檔案后,您需要hibernate-annotations.jar、ejb3-persistence.jar這兩個(gè)檔案。

    到這邊為止,總共需要以下的jar檔案:


    Hibernate可以運(yùn)行于單機(jī)之上,也可以運(yùn)行于Web應(yīng)用程序之中,如果是運(yùn)行于單機(jī),則將所有用到的jar檔案(包括JDBC驅(qū)動(dòng)程序)設(shè)定至CLASSPATH中,如果是運(yùn)行于Web應(yīng)用程序中,則將jar檔案置放于WEB-INF/lib中。

    如果您還需要額外的Library,再依需求加入,例如JUnit、Proxool等等,接下來可以將etc目錄下的 log4j.properties復(fù)制至Hibernate項(xiàng)目的Classpath下,并修改一下當(dāng)中的 log4j.logger.org.hibernate為error,也就是只在在錯(cuò)誤發(fā)生時(shí)顯示必要的訊息。

    接著設(shè)置基本的Hibernate配置文件,可以使用XML或Properties檔案,這邊先使用XML,檔名預(yù)設(shè)為hibernate.cfg.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <!DOCTYPE hibernate-configuration PUBLIC
    ? "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
    ? "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
    ?
    <hibernate-configuration>
    ??? <session-factory>
    ??????? <!-- 顯示實(shí)際操作數(shù)據(jù)庫時(shí)的SQL -->
    ??????? <property name="show_sql">true</property>
    ??????? <!-- SQL方言,這邊設(shè)定的是MySQL -->
    ??????? <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
    ??????? <!-- JDBC驅(qū)動(dòng)程序 -->
    ??????? <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
    ??????? <!-- JDBC URL -->
    ??????? <property name="connection.url">jdbc:mysql://localhost/demo</property>
    ??????? <!-- 數(shù)據(jù)庫使用者 -->
    ??????? <property name="connection.username">root</property>
    ??????? <!-- 數(shù)據(jù)庫密碼 -->
    ??????? <property name="connection.password">123456</property>
    ?
    ??????? <!-- 以下設(shè)置對(duì)象與數(shù)據(jù)庫表格映像類別 -->
    ??????? <mapping class="onlyfun.caterpillar.User"/>
    ??? </session-factory>
    </hibernate-configuration>

    這邊以一個(gè)簡(jiǎn)單的單機(jī)程序來示范Hibernate的配置與功能,首先作數(shù)據(jù)庫的準(zhǔn)備工作,在MySQL中新增一個(gè)demo數(shù)據(jù)庫,并建立user表格:
    CREATE TABLE user (
    id INT(11) NOT NULL auto_increment PRIMARY KEY,
    name VARCHAR(100) NOT NULL default'',
    age INT
    );
    對(duì)于這個(gè)表格,您有一個(gè)User類別與之對(duì)應(yīng),表格中的每一個(gè)字段將對(duì)應(yīng)至User實(shí)例上的Field成員。

    package onlyfun.caterpillar;
    ?
    import javax.persistence.*;
    ?
    @Entity
    @Table(name="user") // 非必要,在表格名稱與類別名稱不同時(shí)使用
    public class User {
    ? @Id
    ? @GeneratedValue(strategy=GenerationType.AUTO)
    ??? private Integer id;
    ?
    ? @Column(name="name") // 非必要,在字段名稱與屬性名稱不同時(shí)使用
    ??? private String name;
    ?
    ? @Column(name="age")
    ??? private Integer age; // 非必要,在字段名稱與屬性名稱不同時(shí)使用
    ???
    ??? // 必須要有一個(gè)預(yù)設(shè)的建構(gòu)方法
    ??? // 以使得Hibernate可以使用Constructor.newInstance()建立對(duì)象
    ??? public User() {
    ??? }
    ?
    ??? public Integer getId() {
    ??????? return id;
    ??? }
    ?
    ??? public void setId(Integer id) {
    ??????? this.id = id;
    ??? }
    ?
    ??? public String getName() {
    ??????? return name;
    ??? }
    ?
    ??? public void setName(String name) {
    ??????? this.name = name;
    ??? }
    ???
    ??? public Integer getAge() {
    ??????? return age;
    ??? }
    ?
    ??? public void setAge(Integer age) {
    ??????? this.age = age;
    ??? }
    }

    其中id是個(gè)特殊的屬性,Hibernate會(huì)使用它來作為主鍵識(shí)別,您可以定義主鍵產(chǎn)生的方式,這邊設(shè)定為自動(dòng)產(chǎn)生主鍵,可以看到,實(shí)體標(biāo)識(shí),主鍵生成,以及相關(guān)映像,都可以使用Annotation來完成。

    接下來撰寫一個(gè)測(cè)試的程序,這個(gè)程序直接以Java程序設(shè)計(jì)人員熟悉的語法方式來操作對(duì)象,而實(shí)際上也直接完成對(duì)數(shù)據(jù)庫的操作,程序?qū)?huì)將一筆數(shù)據(jù)存入表格之中:
    package onlyfun.caterpillar;
    ?
    import org.hibernate.SessionFactory;
    import org.hibernate.Session;
    import org.hibernate.Transaction;
    import org.hibernate.cfg.AnnotationConfiguration;
    import org.hibernate.cfg.Configuration;
    ?
    public class HibernateAnnotationDemo {
    ?
    ??? public static void main(String[] args) {
    ??????? // 需要AnnotationConfiguration讀取Annotation訊息
    ??????? Configuration config = new AnnotationConfiguration().configure();
    ??????? // 根據(jù) config 建立 SessionFactory
    ??????? // SessionFactory 將用于建立 Session
    ??????? SessionFactory sessionFactory = config.buildSessionFactory();
    ?
    ??????? // 將持久化的物件
    ??????? User user = new User();
    ??????? user.setName("caterpillar");
    ??????? user.setAge(new Integer(30));????
    ?
    ??????? // 開啟Session,相當(dāng)于開啟JDBC的Connection
    ??????? Session session = sessionFactory.openSession();
    ??????? // Transaction表示一組會(huì)話操作
    ??????? Transaction tx= session.beginTransaction();
    ??????? // 將對(duì)象映像至數(shù)據(jù)庫表格中儲(chǔ)存
    ??????? session.save(user);
    ??????? tx.commit();
    ??????? session.close();
    ??????? sessionFactory.close();
    ??????
    ??????? System.out.println("新增資料OK!請(qǐng)先用MySQL觀看結(jié)果!");
    ??? }
    }

    注意,使用Annotation時(shí),需要的是AnnotationConfiguration類別。

    如您所看到的,程序中只需要直接操作User對(duì)象,并進(jìn)行Session與Transaction的相關(guān)操作,Hibernate就會(huì)自動(dòng)完成對(duì)數(shù)據(jù)庫的操作,您看不到任何一行JDBC或SQL的陳述,撰寫好以上的各個(gè)檔案之后,各檔案的放置位置如下:


    接著可以開始運(yùn)行程序,結(jié)果如下:
    Hibernate: insert into user (name, age) values (?, ?)
    新增資料OK!請(qǐng)先用MySQL觀看結(jié)果!

    執(zhí)行結(jié)果中顯示了Hibernate所實(shí)際使用的SQL,由于這個(gè)程序還沒有查詢功能,所以要進(jìn)入MySQL中看看新增的數(shù)據(jù),如下:
    mysql> select * from user;
    +----+-----------------+------+
    | id??? | name???????? | age? |
    +----+-----------------+------+
    |? 1??? | caterpillar? | 30?? |
    +----+-----------------+------+
    1 row in set (0.03 sec)

    posted @ 2006-09-01 14:00 Binary 閱讀(302) | 評(píng)論 (0)編輯 收藏

    Hibernate Annotations 實(shí)戰(zhàn)

         摘要: 任何獲得Matrix授權(quán)的網(wǎng)站,轉(zhuǎn)載請(qǐng)保留以下作者信息和鏈接: 作者:icess(作者的blog:http://blog.matrix.org.cn/page/icess)關(guān)鍵字:Hibernate Validator 下面讓我們先看一個(gè)通常用 hbm.xml 映射文件的例子. 有3個(gè)類 .HibernateUtil.java 也就是 Hibernate文檔中推薦的工具類,Pers...  閱讀全文

    posted @ 2006-09-01 13:59 Binary 閱讀(406) | 評(píng)論 (0)編輯 收藏

    在filter中關(guān)閉session

    利用Thread-Specific Storage撰寫一個(gè)HibernateUtil

    HibernateSessionUtil.java
    								import java.io.Serializable;

    import net.sf.hibernate.HibernateException;
    import net.sf.hibernate.Session;
    import net.sf.hibernate.SessionFactory;
    import net.sf.hibernate.Transaction;

    public class HibernateSessionUtil implements Serializable
    {
    publicstaticfinal ThreadLocal tLocalsess = new ThreadLocal();

    publicstaticfinal ThreadLocal tLocaltx = new ThreadLocal();

    /*
    * getting the thread-safe session for using
    */
    publicstatic Session currentSession(){
    Session session = (Session) tLocalsess.get();

    //open a new one, if none can be found.
    try{
    if (session == null){
    session = openSession();
    tLocalsess.set(session);
    }
    }catch (HibernateException e){
    thrownew InfrastructureException(e);
    }
    return session;
    }

    /*
    * closing the thread-safe session
    */
    publicstatic void closeSession(){

    Session session = (Session) tLocalsess.get();
    tLocalsess.set(null);
    try{
    if (session != null && session.isOpen()){
    session.close();
    }

    }catch (HibernateException e){
    thrownew InfrastructureException(e);
    }
    }

    /*
    * begin the transaction
    */
    publicstatic void beginTransaction(){
    Transaction tx = (Transaction) tLocaltx.get();
    try{
    if (tx == null){
    tx = currentSession().beginTransaction();
    tLocaltx.set(tx);
    }
    }catch (HibernateException e){
    thrownew InfrastructureException(e);
    }
    }

    /*
    * close the transaction
    */
    publicstatic void commitTransaction(){
    Transaction tx = (Transaction) tLocaltx.get();
    try{
    if (tx != null && !tx.wasCommitted() && !tx.wasRolledBack())
    tx.commit();
    tLocaltx.set(null);
    }catch (HibernateException e){
    thrownew InfrastructureException(e);
    }
    }

    /*
    * for rollbacking
    */
    publicstatic void rollbackTransaction(){
    Transaction tx = (Transaction) tLocaltx.get();
    try{
    tLocaltx.set(null);
    if (tx != null && !tx.wasCommitted() && !tx.wasRolledBack()){
    tx.rollback();
    }
    }catch (HibernateException e){
    thrownew InfrastructureException(e);
    }
    }

    privatestatic Session openSession() throws HibernateException{
    return getSessionFactory().openSession();
    }

    privatestatic SessionFactory getSessionFactory() throws HibernateException{
    return SingletonSessionFactory.getInstance();
    }
    }

     filter中的程式碼如下

    HibernateSessionCloser.java
    								public class HibernateSessionCloser implements Filter{

    protected FilterConfig filterConfig = null;

    public void init(FilterConfig filterConfig)throws ServletException{
    this.filterConfig = filterConfig;
    }

    public void destroy(){
    this.filterConfig = null;
    }

    public void doFilter(ServletRequest request, ServletResponse response,
    FilterChain chain)
    throws IOException, ServletException {
    try{
    chain.doFilter(request, response);
    }
    finally{
    try{
    HibernateSessionUtil.commitTransaction();
    }catch (InfrastructureException e){
    HibernateSessionUtil.rollbackTransaction();
    }finally{
    HibernateSessionUtil.closeSession();
    }
    }

    }
    }

    然後在操作資料庫之前加上

    HibernateSessionUtil.beginTransaction();
    HibernateSessionUtil.currentSession();//取得Session

    posted @ 2006-09-01 13:51 Binary 閱讀(468) | 評(píng)論 (0)編輯 收藏

    acegi-security-sample-contacts-filter例子學(xué)習(xí)(二)

    功能實(shí)現(xiàn)分析

    這個(gè)例子使用了HSQL做數(shù)據(jù)庫,spring的AOP作為基礎(chǔ),使用Acegi做安全控制組件。
    聯(lián)系人管理的web應(yīng)用在啟動(dòng)時(shí)候,會(huì)做一系列初始化動(dòng)作:
    1. 讀取web.xml文件,

    2. 并解析文件里的內(nèi)容。
    a) context-param元素。
    i. contextConfigLocation屬性。這個(gè)屬性定義了spring所需要的3個(gè)屬性文件。它們分別是:applicationContext -acegi-security.xml、applicationContext-common-business.xml、 applicationContext-common-authorization.xml
    ii. log4jConfigLocation屬性。這個(gè)屬性定義了log4j配置文件。

    b) filter元素。
    這里定義了acegi的一個(gè)過濾器。Acegi的大部分過濾器都是這樣配置的。使用FilterToBeanProxy組件,給它傳遞一個(gè)targetClass屬性。這個(gè)targetClass必須實(shí)現(xiàn)javax.servlet.Filter接口。
    這里配置的是FilterChainProxy。這個(gè)FilterChainProxy比較好用,可以為它定義一串filter屬性。這些filter將會(huì)按照定義的順序被調(diào)用。例如,
    <bean id="filterChainProxy" class="net.sf.acegisecurity.util.FilterChainProxy">
    <property name="filterInvocationDefinitionSource">
    <value>
    CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
    PATTERN_TYPE_APACHE_ANT
    /**=httpSessionContextIntegrationFilter,authenticationProcessingFilter,basicProcessingFilter,rememberMeProcessingFilter,anonymousProcessingFilter,securityEnforcementFilter
    </value>
    </property>
    </bean>
    這個(gè)過濾器的mapping是“/*”。
    c) listener元素。
    i. ContextLoaderListener。這個(gè)是Spring使用來加載根applicationcontext。并分別解析 applicationContext-acegi-security.xml、applicationContext-common- business.xml、applicationContext-common-authorization.xml等配置文件,把相關(guān)的對(duì)象初始化
    iii. Log4jConfigListener。這個(gè)是spring用來初始化log4j組件的listener。
    iv. HttpSessionEventPublisher。這個(gè)組件將發(fā)布HttpSessionCreatedEvent和HttpSessionDestroyedEvent事件給spring的applicationcontext。
    d) servlet元素。
    i. contacts。這里采用了spring的MVC框架, 所以這個(gè)servlet是spring MVC的一個(gè)核心控制器(org.springframework.web.servlet.DispatcherServlet)。這個(gè)servlet 啟動(dòng)時(shí)候,會(huì)從contacts-servlet.xml里面讀取信息,并做相關(guān)的初始化。
    v. remoting。也是spring MVC的一個(gè)核心控制器。與contacts不同,這個(gè)servlet主要是提供web services服務(wù)。這個(gè)servlet啟動(dòng)時(shí)候, 會(huì)從remoting-servlet.xml里面讀取信息,并做相關(guān)的初始化。
    e) taglib元素。這里定義了spring的標(biāo)f) 簽庫。
    3. 解析applicationContext-acegi-security.xml。
    a) 過濾器鏈。定義了一個(gè)FilterChainProxy,b) 并指c) 定了一系列的過濾器鏈。httpSessionContextIntegrationFilter, authenticationProcessingFilter,basicProcessingFilter,rememberMeProcessingFilter,anonymousProcessingFilter,securityEnforcementFilter
    d) 認(rèn)證管理器。這個(gè)管理器由acegi提供。這個(gè)管理器需要一個(gè)providers參數(shù)。這個(gè)providers參數(shù)包含了提供系統(tǒng)認(rèn)證的對(duì)象。
    i. daoAuthenticationProvider。一般用戶認(rèn)證。
    ii. anonymousAuthenticationProvider。匿名用戶認(rèn)證。
    iv. rememberMeAuthenticationProvider。記住我認(rèn)證。

    e) 密碼加密。這里定義了一個(gè)acegi的Md5算法加密對(duì)象Md5PasswordEncoder。
    f) 定義了一個(gè)jdbcDao實(shí)現(xiàn)類。這個(gè)類由acegi提供的net.sf.acegisecurity.providers.dao.jdbc.JdbcDaoImpl。這個(gè)對(duì)象需要一個(gè)dataSource的參數(shù)。
    g) 定義daoAuthenticationProvider。這個(gè)對(duì)象由acegi提供。它有3個(gè)屬性:
    authenticationDao。這里指向前面定義的jdbcDao。
    userCache。這里指向后面定義的user緩存對(duì)象。
    passwordEncoder。這里指向前面定義的密碼加密對(duì)象。
    h) 用戶緩存管理。
    為了緩存user,這里使用spring的ehcache來緩存user。緩存機(jī)制:
    i. 定義緩存管理器――CacheManager。這個(gè)對(duì)象是spring的EhCacheManagerFactoryBean對(duì)象
    ii. 定義user緩存實(shí)際執(zhí)行對(duì)象――UserCacheBackend。這個(gè)對(duì)象是spring的EhCacheFactoryBean。它有兩個(gè)屬性:
    1. cacheManager。這里指向前面定義的緩存管理器。
    2. cacheName。
    iii. 定義user緩存――UserCache。它是acegi提供的EhCacheBasedUserCache對(duì)象。它有一個(gè)屬性:
    1. cache。這里指向的是前面定義的userCacheBackend。

    i) 定義接收來自DaoAuthenticationProvider的認(rèn)證事件的listener――LoggerListener。
    j)
    4. 解析applicationContext-common-business.xml。
    a) dataSource.
    這里使用了spring的DriverManagerDataSource對(duì)象。這個(gè)對(duì)象是一個(gè)JDBC數(shù)據(jù)源的定義。
    b) TransactionManager。這里使用spring的DataSourceTransactionManager對(duì)象。
    c) 事務(wù)攔截器。這里使用spring的事務(wù)攔截器TransactionInterceptor。它有2個(gè)屬性:
    transactionManager。這個(gè)屬性指向前面定義的TransactionManager。
    transactionAttributeSource。這個(gè)屬性里, 指定了ContactManager的各個(gè)方法的事務(wù)方面的要求。
    d) DataSourcePopulator。
    使用sample.contact.DataSourcePopulator對(duì)象,往HSQL里創(chuàng)建相關(guān)的表結(jié)構(gòu)和數(shù)據(jù)。
    實(shí)現(xiàn)原理:DataSourcePopulator 實(shí)現(xiàn)了接口 InitializingBean。其中afterPropertiesSet方法將在spring初始化DataSourcePopulator后被調(diào)用。
    e) ContactDao。這里指向一個(gè)ContactDaoSpring對(duì)象。它繼承spring的 JdbcDaoSupport,g) 并實(shí)現(xiàn)ContactDao接口。它是真正實(shí)現(xiàn)JDBC操作的對(duì)象。
    h) ContactManager。這里使用的是spring的ProxyFactoryBean。它有2個(gè)屬性:
    i. ProxyInterfaces。代理接口:sample.contact.ContactManager

    ii. InterceptorNames。攔截器名稱??梢杂卸鄠€(gè),iv. 這里包括:transactionInterceptor、contactManagerSecurity、contactManagerTarget。其中,v. transactionInterceptor是前面定義的事務(wù)攔截器。ContactManagerSecurity則是在 applicationContext-common-authorization.xml里定義的方法調(diào)用授權(quán)。
    i) ContactManagerTarget。這里指向的是sample.contact.ContactManagerBackend對(duì)象。 ContactManagerBackend實(shí)現(xiàn)了ContactManager接口和InitializingBean接口。它有2個(gè)自定義屬性: contactDao和basicAclExtendedDao。這里會(huì)調(diào)用ACL的API去做些創(chuàng)建權(quán)限和刪除權(quán)限的工作。

    posted @ 2006-09-01 13:45 Binary 閱讀(891) | 評(píng)論 (0)編輯 收藏

    acegi-security-sample-contacts-filter例子學(xué)習(xí)(一)

    這是一個(gè) Acegi 官方的例子。它以聯(lián)系人的管理為例子,說明如何使用 Acegi 作權(quán)限控制。這個(gè)例子包含在 acegi 的包里面。下載地址: http://prdownloads.sourceforge.net/acegisecurity/acegi-security-0.8.3.zip?download。

    聯(lián)系人管理說明了下列中心的Acegi安全控制能力:

    • Role-based security (基于角色的安全) ――每個(gè)責(zé)任人都是某個(gè)角色的一員。而角色被用來限制對(duì)某些安全對(duì)象的訪問。
    • Domain object instance security (域?qū)ο髮?shí)例安全) ――合同,這個(gè)系統(tǒng)里的主要域?qū)ο螅瑩碛幸粋€(gè)訪問控制列表( ACL ),用來指明誰允許讀、管理和刪除對(duì)象。
    • Method invocation security (方法調(diào)用安全)―― 這個(gè) ContactManager 服務(wù)層對(duì)象 包含一些受保護(hù)的和公開的方法。
    • Web request security Web 請(qǐng)求安全) ――這個(gè)“ /secure URI 路徑被使用 Acegi 安全保護(hù),使得沒有 ROLE_USER 角色的用戶無法訪問。 .
    • Security unaware application objects (保護(hù)未知的應(yīng)用對(duì)象) ――受保護(hù)的對(duì)象與 Acegi 之間沒有明顯的耦合或契約,所以它們沒有察覺到安全是由 Acegi 提供的。 *
    • Security taglib usage (安全標(biāo)簽庫使用) ――所有的 JSP 使用 Acegi 安全標(biāo)簽庫來封裝安全信息。 *
    • Fully declarative security( 完全聲明式的安全 ) ――每一個(gè)安全方面特性都是在 application context 里面使用標(biāo)準(zhǔn)的 Acegi 安全對(duì)象來配置的。 *
    • Database-sourced security data (支持?jǐn)?shù)據(jù)庫來源的安全數(shù)據(jù)) ――所有的用戶、角色和 ACL 信息都可以從一個(gè)兼容 JDBC 的內(nèi)存數(shù)據(jù)庫獲得。
    • Integrated form-based and BASIC authentication (集成基于表單和 BASIC 驗(yàn)證)―― 任何 BASIC 驗(yàn)證頭部被檢測(cè)以及作為驗(yàn)證使用。默認(rèn)使用基于表單的普通交互式驗(yàn)證。
    • Remember-me services (記住我的服務(wù))―― Acegi 安全的插件式的“ remember-me 策略被演示。在登錄表單里有一個(gè)相關(guān)的選擇框與之對(duì)應(yīng)。

    聯(lián)系人管理的業(yè)務(wù)功能描述:

    1.1. 每個(gè)用戶登錄后,可以看到一個(gè)聯(lián)系人列表。例如,

    marissa's Contacts

    id

    Name

    Email

    1

    John Smith

    john@somewhere.com

    Del

    Admin Permission

    2

    Michael Citizen

    michael@xyz.com



    3

    Joe Bloggs

    joe@demo.com

    Del


    4

    Karen Sutherland

    karen@sutherland.com

    Del

    Admin Permission

    Add

    說明:用戶沒有權(quán)限訪問的聯(lián)系人信息,將不會(huì)顯示。

    2.2. 用戶可以增加新的聯(lián)系人信息。

    3.3. 如果有刪除權(quán)限,用戶可以看到在聯(lián)系人后面有一個(gè)“ Del ”鏈接。用戶可以點(diǎn)擊這個(gè)鏈接來刪除某個(gè)聯(lián)系人信息。

    4.4. 如果有管理權(quán)限,用戶可以看到在聯(lián)系人后面有一個(gè)“ Admin Permission ”鏈接。用戶可以點(diǎn)擊這個(gè)鏈接來管理訪問這個(gè)聯(lián)系人的權(quán)限。例如,

    Administer Permissions

    sample.contact.Contact@26807f: Id: 1; Name: John Smith; Email: john@somewhere.com

    -R--- [2] dianne

    Del

    -RW-D [22] peter

    Del

    A---- [1] marissa

    Del

    Add Permission Manage

    說明:每一行記錄包含有 3 列。

    第一列表示權(quán)限,例如,“ -RW-D ”表示可讀、可寫、可刪除。

    第二列也表示權(quán)限,但它是以類似 unix 權(quán)限的數(shù)字表達(dá)。例如,“ [22] , 表示可讀、可寫、可刪除。

    第三列是用戶名稱。

    每一行記錄后面都有一個(gè)“ Del ”鏈接。點(diǎn)擊這個(gè)鏈接,可以刪除掉指定用戶對(duì)這個(gè)聯(lián)系人信息的權(quán)限。

    5.5. 用戶可以為某個(gè)聯(lián)系人信息添加權(quán)限。例如,

    Add Permission

    Contact:

    sample.contact.Contact@1787005: Id: 1; Name: John Smith; Email: john@somewhere.com


    Recipient:


    Permission:


    說明:權(quán)限是動(dòng)態(tài)添加的。例如,上圖中給用戶 scott 增加了讀聯(lián)系人 John 的權(quán)限。那么 scott 馬上就可以看到聯(lián)系人 John 的信息了。

    posted @ 2006-09-01 13:44 Binary 閱讀(636) | 評(píng)論 (0)編輯 收藏

    WebWork教程-ServletDispatcher

         摘要: ServletDispatcher 原理 ServletDispatcher 是默認(rèn)的處理 Web Http 請(qǐng)求的調(diào)度器,它是一個(gè) JavaServlet ,是 WebWork 框架的控制器。...  閱讀全文

    posted @ 2006-09-01 13:41 Binary 閱讀(651) | 評(píng)論 (0)編輯 收藏

    WebWork教程-validator

    驗(yàn)證框架
    WebWork 提供了在 Action 執(zhí)行之前,對(duì)輸入數(shù)據(jù)的驗(yàn)證功能,它使用了其核心 XWork 的驗(yàn)證框架。提供了如下功能:
    1、?? 可配置的驗(yàn)證文件。它的驗(yàn)證文件是一個(gè)獨(dú)立的 XML 配置文件,對(duì)驗(yàn)證的添加、修改只需更改配置文件,無需編譯任何的 Class 。
    2、?? 驗(yàn)證文件和被驗(yàn)證的對(duì)象完全解藕。驗(yàn)證對(duì)象是普通的 JavaBean 就可以了(可以是 FormBean 、域?qū)ο蟮龋?,它們不需?shí)現(xiàn)任何額外的方法或繼承額外的類。
    3、?? 多種不同的驗(yàn)證方式。因?yàn)樗?yàn)證功能是可以繼承的,所以可以用多種不同的方式指定驗(yàn)證文件,比如:通過父類的 Action 、通過 Action 、通過 Action 的方法、通過 Action 所使用的對(duì)象,等等。
    4、?? 強(qiáng)大的表達(dá)式驗(yàn)證。它使用了 OGNL 的表達(dá)式語言,提供強(qiáng)大的表達(dá)式驗(yàn)證功能。
    5、?? 同時(shí)支持服務(wù)器端和客戶端驗(yàn)證。
    下面我們來看看如何為用戶注冊(cè)添加驗(yàn)證功能:
    1、?? 注冊(cè)我們的驗(yàn)證類型
    WebWork 為不同的驗(yàn)證要求提供不同的驗(yàn)證類型。一個(gè)驗(yàn)證類型,一般是有一個(gè)類來提供。這個(gè)類必須實(shí)現(xiàn)接口: com.opensymphony.xwork.validator.Validator ,但我們?cè)趯懽约旱尿?yàn)證類型時(shí),無需直接實(shí)現(xiàn) Validator 接口,它有抽象類可供直接使用如 ValidatorSupport 、 FieldValidatorSupport 等。
    驗(yàn)證類型在使用之前,必須要在 ValidatorFactory com.opensymphony.xwork.validator . ValidatorFactory )中 注冊(cè)??梢杂卸N方法實(shí)現(xiàn)驗(yàn)證類型的注冊(cè)。一、寫程序代碼進(jìn)行注冊(cè),它使用 ValidatorFactory 類的靜態(tài)方法: registerValidator(String name, String className) 。 二、使用配置文件 validators.xml 進(jìn)行注冊(cè),要求把文件 validators.xml 放到 ClassPath 的跟目錄中( /WEB-INF/classes )。但在實(shí)際開發(fā)中,一般都使用第二中注冊(cè)方法。我們的驗(yàn)證類型注冊(cè)如下:
    <validators>
    ??? <validator name="required" class="com.opensymphony.xwork.validator.validators.RequiredFieldValidator"/>
    ?? ?<validator name="requiredstring" class="com.opensymphony.xwork.validator.validators.RequiredStringValidator"/>
    ??? <validator name="int" class="com.opensymphony.xwork.validator.validators.IntRangeFieldValidator"/>
    ??? <validator name="date" class="com.opensymphony.xwork.validator.validators.DateRangeFieldValidator"/>
    ??? <validator name="expression" class="com.opensymphony.xwork.validator.validators.ExpressionValidator"/>
    ??? <validator name="fieldexpression" class="com.opensymphony.xwork.validator.validators.FieldExpressionValidator"/>
    ??? <validator name="email" class="com.opensymphony.xwork.validator.validators.EmailValidator"/>
    ??? <validator name="url" class="com.opensymphony.xwork.validator.validators.URLValidator"/>
    ??? <validator name="visitor" class="com.opensymphony.xwork.validator.validators.VisitorFieldValidator"/>
    ??? <validator name="conversion" class="com.opensymphony.xwork.validator.validators.ConversionErrorFieldValidator"/>
    ??? <validator name="stringlength" class="com.opensymphony.xwork.validator.validators.StringLengthFieldValidator"/>
    </validators>
    注冊(cè)驗(yàn)證類型的配置文件非常簡(jiǎn)單。它使用標(biāo)簽 <validator > 提供名-值對(duì)的形式注冊(cè)。這樣我們的驗(yàn)證文件就可以直接引用它的名字。
    2、?? 開啟 Action 的驗(yàn)證功能
    ? 如果 Action 要使用驗(yàn)證框架的驗(yàn)證功能,它必須在配置文件中指定攔截器“ validation ”,它的定義如下:
    <interceptor name="validation" class="com.opensymphony.xwork.validator.ValidationInterceptor"/> 。
    我們的驗(yàn)證文件必須以 ActionName-validation.xml 格式命名,它必須被放置到與這個(gè) Action 相同的包中。你也可以為這個(gè) Action 通過別名的方式指定驗(yàn)證文件,它的命名格式為: ActionName-aliasname-validation.xml 。“ ActionName ”是我們 Action 的類名;“ aliasname ”是我們?cè)谂渲梦募?/span> xwork.xml )中定義這個(gè) Action 所用到的名稱。這樣,同一個(gè) Action 類,在配置文件中的不同定義就可以對(duì)應(yīng)不同的驗(yàn)證文件。驗(yàn)證框架也會(huì)根據(jù) Action 的繼承結(jié)構(gòu)去查找 Action 的父類驗(yàn)證文件,如果找到它會(huì)去執(zhí)行這個(gè)父類的驗(yàn)證。
    ?
    3、?? 實(shí)現(xiàn)我們的驗(yàn)證文件: RegisterActionSupport-validation.xml
    <!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.dtd">
    <validators>
    ??? <field name="user.username">
    ??? <field-validator type="requiredstring">
    ??????????? <message>You must enter a value for username.</message>
    ??????? </field-validator>
    ??? </field>
    ??? <field name="user.password">
    ??? <field-validator type="requiredstring">
    ??????????? <message>You must enter a value for password.</message>
    ??????? </field-validator>
    ??????? <field-validator type="fieldexpression">
    ??????????? <param name="expression">user.password == verifyPassword</param>
    ??????????? <message>Passwords don't match.</message>
    ??????? </field-validator>
    ??? </field>
    ??? <field name="user.email">
    ??? <field-validator type="email">
    ??????????? <message>You must enter a valid email.</message>
    ??????? </field-validator>
    ??? </field>
    ??? <field name="user.age">
    ??? <field-validator type="int">
    ??????????? <param name="min">6</param>
    ??????????? <param name="max">100</param>
    ??????????? <message>Age must be between ${min} and ${max}, current value is ${user.age}.</message>
    ?????? ?</field-validator>
    ??? </field>
    </validators>
    說明:
    1 )、 <field > 標(biāo)簽代表一個(gè)字段,它的屬性“ name ”和頁面輸入框的“ name ”屬性必需完全一致,其實(shí)它也就是我們的表達(dá)式語言。
    2 )、 <field-validator > 標(biāo)簽定義我們的驗(yàn)證規(guī)則, type 屬性的值就是就是我們前面定義的驗(yàn)證類型。
    3 )、驗(yàn)證文件中,字段的數(shù)據(jù)是通過表達(dá)式語言從我們的值堆棧( OgnlValueStack )中取得,一般是 Action Model 對(duì)象。例如:我們的字段“ user.age ”,它會(huì)通過 Action getUser().getAge() 來取得用戶輸入的年齡,再來根據(jù)驗(yàn)證的類型“ int ”和最大值最小值的參數(shù)來判斷輸入的數(shù)據(jù)是否能通過驗(yàn)證。
    4 )、不管驗(yàn)證是否通過,我們的 Action 都會(huì)執(zhí)行,但如果驗(yàn)證沒有通過,它不會(huì)調(diào)用 Action execute() 方法。
    ?
    4、?? 顯示 Action 的驗(yàn)證錯(cuò)誤信息
    如果用戶輸入的數(shù)據(jù)驗(yàn)證沒有通過,我們需重新返回輸入頁面,并給出錯(cuò)誤信息提示。攔截器棧“ validationWorkflowStack ”為我們實(shí)現(xiàn)了這個(gè)功能。它首先驗(yàn)證用戶輸入的數(shù)據(jù),如果驗(yàn)證沒有通過將不執(zhí)行我們 Action execute() 方法,而是將請(qǐng)求重新返回到輸入頁面。
    我們的 xwork.xml 配置文件如下:
    <action name="registerSupport" class="example.register.RegisterActionSupport">
    ??????????? <result name="success" type="dispatcher">
    ??????????????? <param name="location">/register-result.jsp</param>
    ??????????? </result>
    ??????????? <result name="input" type="dispatcher">
    ??????????????? <param name="location">/registerSupport.jsp</param>
    ??????????? </result>
    ??????????? <interceptor-ref name="validationWorkflowStack"/>
    ??????? </action>
    ?
    通過接口 ValidationAware , 我們可以獲得類級(jí)別或字段級(jí)別的驗(yàn)證錯(cuò)誤信息,這個(gè)錯(cuò)誤信息也就是我們驗(yàn)證文件中 <message> 標(biāo)簽里的數(shù)據(jù)。 ActionSupport 類已實(shí)現(xiàn)了此接口,這樣在應(yīng)用中我們的 Action 只要繼承 ActionSupport 類就可以了。 RegisterActionSupport .java 代碼如下:
    package example.register;
    ?
    import com.opensymphony.xwork.ActionSupport;
    ?
    public class RegisterActionSupport extends ActionSupport {
    ?
    ??? private User user= new User();
    ??? private String verifyPassword;
    ???
    ??? public User getUser(){
    ??????? returnthis.user;
    ??? }
    ???
    ??? public String execute(){
    ??????? // 在這里調(diào)用用戶注冊(cè)的業(yè)務(wù)邏輯,比如:將注冊(cè)信息存儲(chǔ)到數(shù)據(jù)庫
    ??????? return SUCCESS;
    ??? }
    ?
    ??? public String getVerifyPassword(){
    ??????? returnthis.verifyPassword;
    ??? }
    ???
    ??? publicvoid setVerifyPassword(String verPassword){
    ??????? this.verifyPassword = verPassword;
    ??? }
    }
    我們 WebWork UI 標(biāo)簽庫直接提供了驗(yàn)證錯(cuò)誤信息顯示功能。如果字段級(jí)別的驗(yàn)證沒有通過,它會(huì)在輸入框上方顯示驗(yàn)證文件定義的錯(cuò)誤提示信息。我們將用戶輸入的頁面更改如下:
    registerSupport.jsp
    <%@ taglib uri="webwork" prefix="ww" %>
    <html>
    <head><title>Register Example</title></head>
    <body>
    <table border=0 width=97%>
    <tr><td align="left">
    ??? <ww:form name="'test'" action="'/example/registerSupport.action'" method="'POST'">
    ??????????? <ww:textfield label="'Username'" name="'user.username'" required="true"/>
    ??????????? <ww:textfield label="'Password'" name="'user.password'" required="true"/>
    ??????????? <ww:textfield label="'VerifyPassword'" name="'verifyPassword'" required="true"/>
    ?????????? ?<ww:textfield label="'Email'" name="'user.email'" required="true"/>
    ??????????? <ww:textfield label="'Age'" name="'user.age'" required="true"/>
    ??????????? <ww:submit value="'Submit'"/>
    ???????? </ww:form>
    </td></tr>
    </table>
    </body>
    </html>
    我們上面的例子使用的是服務(wù)器端驗(yàn)證。 WebWork 也為我們提供了方便的客戶端驗(yàn)證。它將驗(yàn)證自動(dòng)生成 JavaScript 腳本。如果要使用客戶端驗(yàn)證只需改變相應(yīng)的驗(yàn)證類型就可以了(輸入頁面的表單必需使用 <ww:form> 標(biāo)簽,并設(shè)置屬性“ validate="true" ”)。具體的驗(yàn)證類型可以在 WebWork 的包 com.opensymphony.webwork.validators 中找到。

    posted @ 2006-09-01 13:40 Binary 閱讀(677) | 評(píng)論 (0)編輯 收藏

    主站蜘蛛池模板: 在线视频精品免费| 亚洲av无码不卡久久| 成人性生交大片免费看中文| 亚洲精品国产电影| 特级做a爰片毛片免费看| 无码专区一va亚洲v专区在线| 在线观看亚洲专区| 亚洲av午夜成人片精品电影| 曰批全过程免费视频免费看| 亚洲高清视频一视频二视频三| 美女免费视频一区二区三区| 亚洲电影日韩精品| 国产精品免费一区二区三区| 国产亚洲午夜高清国产拍精品 | 污视频在线观看免费| 亚洲AV色香蕉一区二区| 性xxxx视频免费播放直播| 久久久久久亚洲Av无码精品专口| 最近最好最新2019中文字幕免费| 亚洲成a人片在线观看播放| 男女免费观看在线爽爽爽视频 | 久久青青草原国产精品免费| 久久久久亚洲Av片无码v| 84pao国产成视频免费播放| 亚洲一级免费毛片| 免费毛片网站在线观看| 免费的黄网站男人的天堂 | 高清国语自产拍免费视频国产 | 在线观看人成视频免费无遮挡 | 亚洲免费闲人蜜桃| 亚洲色最新高清av网站| 四虎影视永久免费观看网址| 国产精品免费久久久久久久久| 久久精品国产96精品亚洲| 精品女同一区二区三区免费站| 精品丝袜国产自在线拍亚洲| 国产无遮挡裸体免费视频| 无码的免费不卡毛片视频| 亚洲国产成人一区二区三区| 91高清免费国产自产| 亚洲国产精品无码久久久秋霞1|