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

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

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

    Denis's Java Library

    The only documentation is the code itself

    2006年2月5日 #

    Spring中的DAO和Service

         摘要: 我們開發(fā)程序的目的是為了完成業(yè)務功能, 理想的情況下程序中的每一條語句都應該是與業(yè)務直接相關的, 例如程序中不應該出現(xiàn)連接數(shù)據(jù)庫, 讀取某個字段等純技術性的操作, 而應該是得到用戶A的基本信息等具有業(yè)務含義的操作. dao(data access object)層存在的意。。。。。  閱讀全文

    posted @ 2006-02-05 17:17 DenisLing 閱讀(1622) | 評論 (0)編輯 收藏

    2005年12月20日 #

    數(shù)據(jù)庫設計的范式大綱及一個小的實例說明

     

    數(shù)據(jù)庫設計的范式大綱

    第一范式:

    對于表中的每一行,必須且僅僅有唯一的行值.在一行中的每一列僅有唯一的值并且具有原子性.

    第二范式:

    第二范式要求非主鍵列是主鍵的子集,非主鍵列活動必須完全依賴整個主鍵。主鍵必須有唯一性的元素,一個主鍵可以由一個或更多的組成唯一值的列組成。一旦創(chuàng)建,主鍵無法改變,外鍵關聯(lián)一個表的主鍵。主外鍵關聯(lián)意味著一對多的關系.

    第三范式:

    第三范式要求非主鍵列互不依賴.

    第四范式:

    第四范式禁止主鍵列和非主鍵列一對多關系不受約束

    第五范式:

    第五范式將表分割成盡可能小的塊,為了排除在表中所有的冗余.

     

    下面先討論前3個范式:

     

    引言

      數(shù)據(jù)庫的設計范式是數(shù)據(jù)庫設計所需要滿足的規(guī)范,滿足這些規(guī)范的數(shù)據(jù)庫是簡潔的、結構明晰的,同時,不會發(fā)生插入 (insert)、刪除(delete)和更新(update)操作異常。反之則是亂七八糟,不僅給數(shù)據(jù)庫的編程人員制造麻煩,而且面目可憎,可能存儲了 大量不需要的冗余信息。

      設計范式是不是很難懂呢?非也,大學教材上給我們一堆數(shù)學公式我們當然看不懂,也記不住。所以我們很多人就根本不按照范式來設計數(shù)據(jù)庫。

      實質(zhì)上,設計范式用很形象、很簡潔的話語就能說清楚,道明白。本文將對范式進行通俗地說明,并以筆者曾經(jīng)設計的一個簡單論壇的數(shù)據(jù)庫為例來講解怎樣將這些范式應用于實際工程。

      范式說明

      第一范式(1NF):數(shù)據(jù)庫表中的字段都是單一屬性的,不可再分。這個單一屬性由基本類型構成,包括整型、實數(shù)、字符型、邏輯型、日期型等。

      例如,如下的數(shù)據(jù)庫表是符合第一范式的:

    字段1

    字段2

    字段3

    字段4

     

     

     

     


      而這樣的數(shù)據(jù)庫表是不符合第一范式的:

    字段1

    字段2

    字段3

    字段4

     

     

    字段3.1

    字段3.2

     







      很顯然,在當前的任何關系數(shù)據(jù)庫管理系統(tǒng)(DBMS)中,傻瓜也不可能做出不符合第一范式的數(shù)據(jù)庫,因為這些DBMS不允許你把數(shù)據(jù)庫表的一列再分成二列或多列。因此,你想在現(xiàn)有的DBMS中設計出不符合第一范式的數(shù)據(jù)庫都是不可能的。

      第二范式(2NF):數(shù)據(jù)庫表中不存在非關鍵字段對任一候選關鍵字段的部分函數(shù)依賴(部分函數(shù)依賴指的是存在組合關鍵字中的某些字段決定非關鍵字段的情況),也即所有非關鍵字段都完全依賴于任意一組候選關鍵字。

      假定選課關系表為SelectCourse(學號, 姓名, 年齡, 課程名稱, 成績, 學分),關鍵字為組合關鍵字(學號, 課程名稱),因為存在如下決定關系:

      (學號, 課程名稱) → (姓名, 年齡, 成績, 學分)

      這個數(shù)據(jù)庫表不滿足第二范式,因為存在如下決定關系:

      (課程名稱) → (學分)

      (學號) → (姓名, 年齡)

      即存在組合關鍵字中的字段決定非關鍵字的情況。

      由于不符合2NF,這個選課關系表會存在如下問題:

      (1) 數(shù)據(jù)冗余:

      同一門課程由n個學生選修,"學分"就重復n-1次;同一個學生選修了m門課程,姓名和年齡就重復了m-1次。

      (2) 更新異常:

      若調(diào)整了某門課程的學分,數(shù)據(jù)表中所有行的"學分"值都要更新,否則會出現(xiàn)同一門課程學分不同的情況。

      (3) 插入異常:

      假設要開設一門新的課程,暫時還沒有人選修。這樣,由于還沒有"學號"關鍵字,課程名稱和學分也無法記錄入數(shù)據(jù)庫。

      (4) 刪除異常:

      假設一批學生已經(jīng)完成課程的選修,這些選修記錄就應該從數(shù)據(jù)庫表中刪除。但是,與此同時,課程名稱和學分信息也被刪除了。很顯然,這也會導致插入異常。

      把選課關系表SelectCourse改為如下三個表:

      學生:Student(學號, 姓名, 年齡)

      課程:Course(課程名稱, 學分)

      選課關系:SelectCourse(學號, 課程名稱, 成績)

      這樣的數(shù)據(jù)庫表是符合第二范式的,消除了數(shù)據(jù)冗余、更新異常、插入異常和刪除異常。

      另外,所有單關鍵字的數(shù)據(jù)庫表都符合第二范式,因為不可能存在組合關鍵字。

       第三范式(3NF):在第二范式的基礎上,數(shù)據(jù)表中如果不存在非關鍵字段對任一候選關鍵字段的傳遞函數(shù)依賴則符合第三范式。所謂傳遞函數(shù)依賴,指的是如 果存在"A → B → C"的決定關系,則C傳遞函數(shù)依賴于A。因此,滿足第三范式的數(shù)據(jù)庫表應該不存在如下依賴關系:

      關鍵字段非關鍵字段x → 非關鍵字段y

      假定學生關系表為Student(學號, 姓名, 年齡, 所在學院, 學院地點, 學院電話),關鍵字為單一關鍵字"學號",因為存在如下決定關系:

      (學號) → (姓名, 年齡, 所在學院, 學院地點, 學院電話)

      這個數(shù)據(jù)庫是符合2NF的,但是不符合3NF,因為存在如下決定關系:

      (學號) → (所在學院) → (學院地點, 學院電話)

      即存在非關鍵字段"學院地點""學院電話"對關鍵字段"學號"的傳遞函數(shù)依賴。

      它也會存在數(shù)據(jù)冗余、更新異常、插入異常和刪除異常的情況,讀者可自行分析得知。

      把學生關系表分為如下兩個表:

      學生:(學號, 姓名, 年齡, 所在學院)

      學院:(學院, 地點, 電話)

      這樣的數(shù)據(jù)庫表是符合第三范式的,消除了數(shù)據(jù)冗余、更新異常、插入異常和刪除異常。

      鮑依斯-科得范式(BCNF):在第三范式的基礎上,數(shù)據(jù)庫表中如果不存在任何字段對任一候選關鍵字段的傳遞函數(shù)依賴則符合第三范式。

      假設倉庫管理關系表為StorehouseManage(倉庫ID, 存儲物品ID, 管理員ID, 數(shù)量),且有一個管理員只在一個倉庫工作;一個倉庫可以存儲多種物品。這個數(shù)據(jù)庫表中存在如下決定關系:

      (倉庫ID, 存儲物品ID) →(管理員ID, 數(shù)量)

      (管理員ID, 存儲物品ID) → (倉庫ID, 數(shù)量)

      所以,(倉庫ID, 存儲物品ID)(管理員ID, 存儲物品ID)都是StorehouseManage的候選關鍵字,表中的唯一非關鍵字段為數(shù)量,它是符合第三范式的。但是,由于存在如下決定關系:

      (倉庫ID) → (管理員ID)

      (管理員ID) → (倉庫ID)

      即存在關鍵字段決定關鍵字段的情況,所以其不符合BCNF范式。它會出現(xiàn)如下異常情況:

      (1) 刪除異常:

      當倉庫被清空后,所有"存儲物品ID""數(shù)量"信息被刪除的同時,"倉庫ID""管理員ID"信息也被刪除了。

      (2) 插入異常:

      當倉庫沒有存儲任何物品時,無法給倉庫分配管理員。

      (3) 更新異常:

      如果倉庫換了管理員,則表中所有行的管理員ID都要修改。

      把倉庫管理關系表分解為二個關系表:

      倉庫管理:StorehouseManage(倉庫ID, 管理員ID)

      倉庫:Storehouse(倉庫ID, 存儲物品ID, 數(shù)量)

      這樣的數(shù)據(jù)庫表是符合BCNF范式的,消除了刪除異常、插入異常和更新異常。

    范式應用

      我們來逐步搞定一個論壇的數(shù)據(jù)庫,有如下信息:

      (1) 用戶:用戶名,email,主頁,電話,聯(lián)系地址

      (2) 帖子:發(fā)帖標題,發(fā)帖內(nèi)容,回復標題,回復內(nèi)容

      第一次我們將數(shù)據(jù)庫設計為僅僅存在表:
      

    用戶名

    email

    主頁

    電話

    聯(lián)系地址

    發(fā)帖標題

    發(fā)帖內(nèi)容

    回復標題

    回復內(nèi)容


      這個數(shù)據(jù)庫表符合第一范式,但是沒有任何一組候選關鍵字能決定數(shù)據(jù)庫表的整行,唯一的關鍵字段用戶名也不能完全決定整個元組。我們需要增加"發(fā)帖ID""回復ID"字段,即將表修改為:

    用戶名

    email

    主頁

    電話

    聯(lián)系地址

    發(fā)帖ID

    發(fā)帖標題

    發(fā)帖內(nèi)容

    回復ID

    回復標題

    回復內(nèi)容


      這樣數(shù)據(jù)表中的關鍵字(用戶名,發(fā)帖ID,回復ID)能決定整行:

      (用戶名,發(fā)帖ID,回復ID) → (email,主頁,電話,聯(lián)系地址,發(fā)帖標題,發(fā)帖內(nèi)容,回復標題,回復內(nèi)容)

      但是,這樣的設計不符合第二范式,因為存在如下決定關系:

      (用戶名) → (email,主頁,電話,聯(lián)系地址)

      (發(fā)帖ID) → (發(fā)帖標題,發(fā)帖內(nèi)容)

      (回復ID) → (回復標題,回復內(nèi)容)

      即非關鍵字段部分函數(shù)依賴于候選關鍵字段,很明顯,這個設計會導致大量的數(shù)據(jù)冗余和操作異常。

      我們將數(shù)據(jù)庫表分解為(帶下劃線的為關鍵字):

      (1) 用戶信息:用戶名,email,主頁,電話,聯(lián)系地址

      (2) 帖子信息:發(fā)帖ID,標題,內(nèi)容

      (3) 回復信息:回復ID,標題,內(nèi)容

      (4) 發(fā)貼:用戶名,發(fā)帖ID

      (5) 回復:發(fā)帖ID,回復ID

      這樣的設計是滿足第123范式和BCNF范式要求的,但是這樣的設計是不是最好的呢?

      不一定。

       觀察可知,第4"發(fā)帖"中的"用戶名""發(fā)帖ID"之間是1N的關系,因此我們可以把"發(fā)帖"合并到第2項的"帖子信息"中;第5"回復"中的 "發(fā)帖ID""回復ID"之間也是1N的關系,因此我們可以把"回復"合并到第3項的"回復信息"中。這樣可以一定量地減少數(shù)據(jù)冗余,新的設計為:

      (1) 用戶信息:用戶名,email,主頁,電話,聯(lián)系地址

      (2) 帖子信息:用戶名,發(fā)帖ID,標題,內(nèi)容

      (3) 回復信息:發(fā)帖ID,回復ID,標題,內(nèi)容

      數(shù)據(jù)庫表1顯然滿足所有范式的要求;

      數(shù)據(jù)庫表2中存在非關鍵字段"標題""內(nèi)容"對關鍵字段"發(fā)帖ID"的部分函數(shù)依賴,即不滿足第二范式的要求,但是這一設計并不會導致數(shù)據(jù)冗余和操作異常;

      數(shù)據(jù)庫表3中也存在非關鍵字段"標題""內(nèi)容"對關鍵字段"回復ID"的部分函數(shù)依賴,也不滿足第二范式的要求,但是與數(shù)據(jù)庫表2相似,這一設計也不會導致數(shù)據(jù)冗余和操作異常。

      由此可以看出,并不一定要強行滿足范式的要求,對于1N關系,當1的一邊合并到N的那邊后,N的那邊就不再滿足第二范式了,但是這種設計反而比較好!

      對于MN的關系,不能將M一邊或N一邊合并到另一邊去,這樣會導致不符合范式要求,同時導致操作異常和數(shù)據(jù)冗余。
    對于11的關系,我們可以將左邊的1或者右邊的1合并到另一邊去,設計導致不符合范式要求,但是并不會導致操作異常和數(shù)據(jù)冗余。

      結論

      滿足范式要求的數(shù)據(jù)庫設計是結構清晰的,同時可避免數(shù)據(jù)冗余和操作異常。這并意味著不符合范式要求的設計一定是錯誤的,在數(shù)據(jù)庫表中存在111N關系這種較特殊的情況下,合并導致的不符合范式要求反而是合理的。

      在我們設計數(shù)據(jù)庫的時候,一定要時刻考慮范式的要求。

    posted @ 2005-12-20 10:54 DenisLing 閱讀(1812) | 評論 (3)編輯 收藏

    2005年12月19日 #

    對spring事務類型詳解的一點補充(關于嵌套事務)

         摘要: 可能大家對PROPAGATION_NESTED還不怎么了解,覺得有必要再補充一下^_^!  閱讀全文

    posted @ 2005-12-19 16:02 DenisLing 閱讀(3221) | 評論 (5)編輯 收藏

    2005年12月18日 #

    Spring事務類型祥解

         摘要: 大家可能在spring中經(jīng)常看到這樣的定義:


    PROPAGATION_REQUIRED,readOnlyPROPAGATION_REQUIRED

    估計有好多朋友還沒有弄清楚里面的值的意思,仔細看完下面應該知道自己什么情況下面應該使用什么樣的聲明。^_^  閱讀全文

    posted @ 2005-12-18 16:30 DenisLing 閱讀(9629) | 評論 (2)編輯 收藏

    2005年12月1日 #

    spring聲明式事務管理祥述

    Spring也提供了聲明式事務管理。這是通過Spring AOP實現(xiàn)的。

    Spring 中進行事務管理的通常方式是利用AOP(面向切片編程)的方式,為普通java類封裝事務控制,它是通過動態(tài)代理實現(xiàn)的,由于接口是延遲實例化的, spring在這段時間內(nèi)通過攔截器,加載事務切片。原理就是這樣,具體細節(jié)請參考jdk中有關動態(tài)代理的文檔。本文主要講解如何在spring中進行事 務控制。
    動態(tài)代理的一個重要特征是,它是針對接口的,所以我們的dao要通過動態(tài)代理來讓spring接管事務,就必須在dao前面抽象出一個接口,當然如果沒有這樣的接口,那么spring會使用CGLIB來解決問題,但這不是spring推薦的方式,所以不做討論.

    大多數(shù)Spring用戶選擇聲明式事務管理。這是最少影響應用代碼的選擇, 因而這是和非侵入性的輕量級容器的觀念是一致的。

    從考慮EJB CMT和Spring聲明式事務管理的相似以及不同之處出發(fā)是很有益的。 它們的基本方法是相似的:都可以指定事務管理到單獨的方法;如果需要可以在事務上 下文調(diào)用setRollbackOnly()方法。不同之處如下:

    • 不象EJB CMT綁定在JTA上,Spring聲明式事務管理可以在任何環(huán)境下使用。 只需更改配置文件,它就可以和JDBC、JDO、Hibernate或其他的事務機制一起工作

    • Spring可以使聲明式事務管理應用到普通Java對象,不僅僅是特殊的類,如EJB

    • Spring提供聲明式回滾規(guī)則:EJB沒有對應的特性, 我們將在下面討論這個特性。回滾可以聲明式控制,不僅僅是編程式的

    • Spring允許你通過AOP定制事務行為。例如,如果需要,你可以在事務 回滾中插入定制的行為。你也可以增加任意的通知,就象事務通知一樣。使用 EJB CMT,除了使用setRollbackOnly(),你沒有辦法能 夠影響容器的事務管理

    • Spring不提供高端應用服務器提供的跨越遠程調(diào)用的事務上下文傳播。如 果你需要這些特性,我們推薦你使用EJB。然而,不要輕易使用這些特性。通常我 們并不希望事務跨越遠程調(diào)用

    回滾規(guī)則的概念是很重要的:它們使得我們可以指定哪些異常應該發(fā)起自 動回滾。我們在配置文件中,而不是Java代碼中,以聲明的方式指定。因此,雖然我們?nèi)?然可以編程調(diào)用TransactionStatus對象的 setRollbackOnly()方法來回滾當前事務,多數(shù)時候我們可以 指定規(guī)則,如MyApplicationException應該導致回滾。 這有顯著的優(yōu)點,業(yè)務對象不需要依賴事務基礎設施。例如,它們通常不需要引 入任何Spring API,事務或其他任何東西。

    EJB的默認行為是遇到系統(tǒng)異常(通常是運行時異常), EJB容器自動回滾事務。EJB CMT遇到應用程序異常 (除了java.rmi.RemoteException外的checked異常)時不 會自動回滾事務。雖然Spring聲明式事務管理沿用EJB的約定(遇到unchecked 異常自動回滾事務),但是這是可以定制的。

    按照我們的測試,Spring聲明式事務管理的性能要勝過EJB CMT。

    通 常通過TransactionProxyFactoryBean設置Spring事務代理。我們需 要一個目標對象包裝在事務代理中。這個目標對象一般是一個普通Java對象的bean。當我 們定義TransactionProxyFactoryBean時,必須提供一個相關的 PlatformTransactionManager的引用和事務屬性事務屬性含有上面描述的事務定義。

    <bean id="petStore" 
    class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
    <property name="transactionManager"><ref bean="transactionManager"/></property>
    <property name="target"><ref bean="petStoreTarget"/></property>
    <property name="transactionAttributes">
    <props>
    <prop key="insert*">PROPAGATION_REQUIRED,-MyCheckedException</prop>
    <prop key="update*">PROPAGATION_REQUIRED</prop>
    <prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
    </props>
    </property>
    </bean>

    事 務代理會實現(xiàn)目標對象的接口:這里是id為petStoreTarget的bean。(使用 CGLIB也可以實現(xiàn)具體類的代理。只要設置proxyTargetClass屬性為true就可以。 如果目標對象沒有實現(xiàn)任何接口,這將自動設置該屬性為true。通常,我們希望面向接口而不是 類編程。)使用proxyInterfaces屬性來限定事務代理來代 理指定接口也是可以的(一般來說是個好想法)。也可以通過從 org.springframework.aop.framework.ProxyConfig繼承或所有AOP代理工廠共享 的屬性來定制TransactionProxyFactoryBean的行為。

    這里的transactionAttributes屬性定義在 org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource 中的屬性格式來設置。這個包括通配符的方法名稱映射是很直觀的。注意 insert*的映射的值包括回滾規(guī)則。添加的-MyCheckedException 指定如果方法拋出MyCheckedException或它的子類,事務將 會自動回滾。可以用逗號分隔定義多個回滾規(guī)則。-前綴強制回滾,+前綴指定提交(這允許即使拋出unchecked異常時也可以提交事務,當然你自己要明白自己 在做什么)。

    TransactionProxyFactoryBean允許你通過 “preInterceptors”和“postInterceptors”屬性設置“前”或“后”通知來提供額外的 攔截行為。可以設置任意數(shù)量的“前”和“后”通知,它們的類型可以是 Advisor(可以包含一個切入點), MethodInterceptor或被當前Spring配置支持的通知類型 (例如ThrowAdviceAfterReturningtAdviceBeforeAdvice, 這些都是默認支持的)。這些通知必須支持實例共享模式。如果你需要高級AOP特 性來使用事務,如有狀態(tài)的maxin,那最好使用通用的 org.springframework.aop.framework.ProxyFactoryBean, 而不是TransactionProxyFactoryBean實用代理創(chuàng)建者。

    也可以設置自動代理:配置AOP框架,不需要單獨的代理定義類就可以生成類的 代理。

    附兩個spring的事務配置例子:
    <prop key="add">
         PROPAGATION_REQUIRES_NEW, -MyException
    </prop>
    注:上面的意思是add方法將獨占一個事務,當事務處理過程中產(chǎn)生MyException異常或者該異常的子類將回滾該事務。

    <prop key="loadAll">
        PROPAGATION_SUPPORTS, ISOLATION_READ_COMMITED, Readonly
    </prop>
    注:表示loadAll方法支持事務,而且不會讀取沒有提交事務的數(shù)據(jù)。它的數(shù)據(jù)為只讀(這樣有助于提高讀取的性能)

    附A Spring中的所有事務策略

    PROPAGATION_MANDATORY
    PROPAGATION_NESTED
    PROPAGATION_NEVER
    PROPAGATION_NOT_SUPPORTED
    PROPAGATION_REQUIRED
    PROPAGATION_REQUIRED_NEW
    PROPAGATION_SUPPORTS

    附B Spring中所有的隔離策略:

    ISOLATION_DEFAULT
    ISOLATION_READ_UNCOMMITED
    ISOLATION_COMMITED
    ISOLATION_REPEATABLE_READ
    ISOLATION_SERIALIZABLE

    posted @ 2005-12-01 11:47 DenisLing 閱讀(15358) | 評論 (0)編輯 收藏

    2005年11月28日 #

    webwork開發(fā)團隊加入Struts(吃驚)

    早上一過來看到下面的新聞感覺驚訝的要死!不知道和我一樣在struts和webwork之間一直在徘徊的朋友們看了由什么感覺。本來我的態(tài)度是想慢慢放棄struts的…… 看樣子要重新看待struts了。原文如下:

    WebWork joining Struts


    Yes, . The WebWork development team (Jason and I) have been working with the Struts development team (Don Brown and Ted Husted) and have come to the conclusion that the best thing for Java community would be to merge WebWork in to Struts.

    Read Ted's email here, but the gist of it is this: WebWork is a great technology, and Struts is a great community. It's a perfect match and bringing the two together will only be better for WebWork and Struts users alike. The only down side for me is that I'll be working less with OpenSymphony, but I believe that is a small price for all the great benefits that come from this merger.

    Just to be clear, WebWork is not going away. WebWork 2.2 is still coming out any day now, and there may even be a WebWork 2.3. But new minor/major versions won't be coming out under the WebWork name for much longer. Instead, they will be released under the Struts incubator program with the intent to eventually become Struts Action Framework 2.0.

    So don't worry, WebWork 2.1.8, 2.2.1, and other bug fix releases will continue to come out and we will support the WebWork community as long as needed. In addition, we'll make compatibility with both Struts and WebWork a high priority, so future releases may help with that. To be clear: no one is leaving WebWork and it will continue to be supported for a very long time.

    With this renewed energy, larger development team, and larger community, the combined efforts of Struts and WebWork will surely make the Struts platform the easiest, fastest, and most powerful Java web framework available. We hope that all the WebWork users and developers are as excited about this as we are and are ready to take WebWork to the next level.

    原文地址:http://www.opensymphony.com/webwork/

    以前一直在struts和webwork之間猶豫,看來struts氣數(shù)未盡呀。apache組織還是比較只值得信賴的。呵呵!

    posted @ 2005-11-28 08:47 DenisLing 閱讀(997) | 評論 (6)編輯 收藏

    2005年11月21日 #

    自定義標簽獲取struts中action的全部路徑(原創(chuàng))

          由于項目里面由需要一個form可以提交多個action(本來可以用 dispatch值來實現(xiàn),后來考慮到要使用validator框架驗證)。后來考慮的方案為使用js來控制form的流向,例如
          
    form.action='/bookstore/checkId.do'

    不過新的問題來了!如何能不用hardcode而拿到我要的action的實際路徑呢?比如我定義的struts-config文件里面的action是 
    path="/checkId"
    但是實際解釋后的path是:
    action='/bookstore/checkId.do'
    前 綴和后面的后綴.do都是根據(jù)你的項目部署的路徑和你在web.xml中配置的mapping的后綴有關系,如果我把內(nèi)容寫死到jsp中那以后我要是想把 checkId.do改成checkId.action那就要更改jsp,由于struts本來提供的幾個taglib里面的

    <html:form action="/checkId" >

    綜合了一下決定還是自己寫個taglib來實現(xiàn),其實只需要照著struts 中的 FormTag.java 文件依葫蘆畫瓢就可以了,一下為本人的代碼部分

    StrutsActionCustomTag.java
    package com.denis.framework.common.taglib.strutsActionExt;

    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.jsp.JspException;
    import javax.servlet.jsp.tagext.TagSupport;

    import org.apache.struts.taglib.TagUtils;

    public class StrutsActionCustomTag extends TagSupport {

       
    protected String actionName = null;
       
        
    public String getActionName() {
           
    return actionName;
        }


        
    public void setActionName(String actionName) {
           
    this.actionName = actionName;
        }


        
    public int doStartTag() throws JspException {

            StringBuffer results 
    = new StringBuffer();
            HttpServletResponse response 
    =
                (HttpServletResponse) 
    this.pageContext.getResponse();
           
            results.append(response.encodeURL( TagUtils.getInstance().getActionMappingURL( 
    this.actionName , this.pageContext)) );

            TagUtils.getInstance().write(pageContext, results.toString());

           
    return (EVAL_BODY_INCLUDE);
        }


        
    public void release() {
           
    super.release();
           
    this.actionName = null ;

        }

    }


    tld定義部分

    framework-struts.tld
    <?xml version="1.0" encoding="UTF-8"?>

    <!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN" "http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">
    <taglib>

    <tlibversion>1.0</tlibversion>
        <jspversion>1.1</jspversion>
        <shortname>framework</shortname>
        <uri>http://www.denisFramework.org/Framework-Tag</uri>
        <tag>
        <name>getActionUrl</name>
        <tagclass>com.denis.framework.common.taglib.strutsActionExt.StrutsActionCustomTag</tagclass>
        <bodycontent>empty</bodycontent>
        <attribute>
             <name>actionName</name>
             <required>true</required>
             <rtexprvalue>true</rtexprvalue>
        </attribute>
    </tag>

    </taglib>



    ok ! 直接在jsp中如下使用即可取到action的真正路徑

     
    <%@ page language="java"%>
    <%@ taglib uri="http://jakarta.apache.org/struts/tags-bean" prefix="bean"%> 
    <%@ taglib uri="http://jakarta.apache.org/struts/tags-html" prefix="html"%>
    <%@ taglib uri="/WEB-INF/framework-struts.tld" prefix="framework" %>
     
    <html> 
       
    <head>
           
    <title>JSP for loginForm form</title>
       
    </head>
       
    <body>
           
    <framework:getActionUrl actionName="login" />
           
    <html:form action="/login">
                name : 
    <html:text property="name"/><html:errors property="name"/><br/>
                password : 
    <html:password property="password"/><html:errors property="password"/><br/>
               
    <html:submit/><html:cancel/>
           
    </html:form>
       
    </body>
    </html>



    大家要是有更好的解決方法希望能指正!謝謝!

    posted @ 2005-11-21 15:52 DenisLing 閱讀(1858) | 評論 (1)編輯 收藏

    使用 Spring 更好地處理 Struts 動作 (轉自ibm 個人感覺受益非淺)

    Struts Recipes 的合著者 George Franciscus 將介紹另一個重大的 Struts 整合竅門 —— 這次是將 Struts 應用程序導入 Spring 框架。請跟隨 George,他將向您展示如何改變 Struts 動作,使得管理 Struts 動作就像管理 Spring beans 那樣。結果是一個增強的 web 框架,這個框架可以方便地利用 Spring AOP 的優(yōu)勢。

    您肯定已經(jīng)聽說過控制反轉 (IOC) 設計模式,因為很長一段時間以來一直在流傳關于它的信息。如果您在任何功能中使用過 Spring 框架,那么您就知道其原理的作用。在本文中,我利用這一原理把一個 Struts 應用程序注入 Spring 框架,您將親身體會到 IOC 模式的強大。

    將一個 Struts 應用程序整合進 Spring 框架具有多方面的優(yōu)點。首先,Spring 是為解決一些關于 JEE 的真實世界問題而設計的,比如復雜性、低性能和可測試性,等等。第二,Spring 框架包含一個 AOP 實現(xiàn),允許您將面向方面技術應用于面向對象的代碼。第三,一些人可能會說 Spring 框架只有處理 Struts 比 Struts 處理自己好。但是這是觀點問題,我演示三種將 Struts 應用程序整合到 Spring 框架的方法后,具體由您自己決定使用哪一種。

    我所演示的方法都是執(zhí)行起來相對簡單的,但是它們卻具有明顯不同的優(yōu)點。我為每一種方法創(chuàng)建了一個獨立而可用的例子,這樣您就可以完全理解每種方法。 請參閱 下載 部分獲得完整例子源代碼。請參閱 參考資料,下載 Struts MVC 和 Spring 框架。

    為什么 Spring 這么了不起?

    Spring 的創(chuàng)立者 Rod Johnson 以一種批判的眼光看待 Java? 企業(yè)軟件開發(fā),并且提議很多企業(yè)難題都能夠通過戰(zhàn)略地使用 IOC 模式(也稱作依賴注入)來解決。當 Rod 和一個具有奉獻精神的開放源碼開發(fā)者團隊將這個理論應用于實踐時,結果就產(chǎn)生了 Spring 框架。簡言之,Spring 是一個輕型的容器,利用它可以使用一個外部 XML 配置文件方便地將對象連接在一起。每個對象都可以通過顯示一個 JavaBean 屬性收到一個到依賴對象的引用,留給您的簡單任務就只是在一個 XML 配置文件中把它們連接好。

    IOC 和 Spring

    IOC 是一種使應用程序邏輯外在化的設計模式,所以它是被注入而不是被寫入客戶機代碼中。將 IOC 與接口編程應用結合,就像 Spring 框架那樣,產(chǎn)生了一種架構,這種架構能夠減少客戶機對特定實現(xiàn)邏輯的依賴。請參閱 參考資料 了解更多關于 IOC 和 Spring 的信息。

    依 賴注入是一個強大的特性,但是 Spring 框架能夠提供更多特性。Spring 支持可插拔的事務管理器,可以給您的事務處理提供更廣泛的選擇范圍。它集成了領先的持久性框架,并且提供一個一致的異常層次結構。Spring 還提供了一種使用面向方面代碼代替正常的面向對象代碼的簡單機制。

    Spring AOP 允許您使用攔截器 在一個或多個執(zhí)行點上攔截應用程序邏輯。加強應用程序在攔截器中的日志記錄邏輯會產(chǎn)生一個更可讀的、實用的代碼基礎,所以攔截器廣泛用于日志記錄。您很快就會看到,為了處理橫切關注點,Spring AOP 發(fā)布了它自己的攔截器,您也可以編寫您自己的攔截器。





    整合 Struts 和 Spring

    與 Struts 相似,Spring 可以作為一個 MVC 實現(xiàn)。這兩種框架都具有自己的優(yōu)點和缺點,盡管大部分人同意 Struts 在 MVC 方面仍然是最好的。很多開發(fā)團隊已經(jīng)學會在時間緊迫的時候利用 Struts 作為構造高品質(zhì)軟件的基礎。Struts 具有如此大的推動力,以至于開發(fā)團隊寧愿整合 Spring 框架的特性,而不愿意轉換成 Spring MVC。沒必要進行轉換對您來說是一個好消息。Spring 架構允許您將 Struts 作為 Web 框架連接到基于 Spring 的業(yè)務和持久層。最后的結果就是現(xiàn)在一切條件都具備了。

    在接下來的小竅門中,您將會了解到三種將 Struts MVC 整合到 Spring 框架的方法。我將揭示每種方法的缺陷并且對比它們的優(yōu)點。 一旦您了解到所有三種方法的作用,我將會向您展示一個令人興奮的應用程序,這個程序使用的是這三種方法中我最喜歡的一種。





    三個小竅門

    接下來的每種整合技術(或者竅門)都有自己的優(yōu)點和特點。我偏愛其中的一種,但是我知道這三種都能夠加深您對 Struts 和 Spring 的理解。在處理各種不同情況的時候,這將給您提供一個廣闊的選擇范圍。方法如下:

    • 使用 Spring 的 ActionSupport 類整合 Structs
    • 使用 Spring 的 DelegatingRequestProcessor 覆蓋 Struts 的 RequestProcessor
    • 將 Struts Action 管理委托給 Spring 框架

    裝載應用程序環(huán)境

    無論您使用哪種技術,都需要使用 Spring 的 ContextLoaderPlugin 為 Struts 的 ActionServlet 裝載 Spring 應用程序環(huán)境。就像添加任何其他插件一樣,簡單地向您的 struts-config.xml 文件添加該插件,如下所示:


    <plug-in className=
    "org.springframework.web.struts.ContextLoaderPlugIn">
    <set-property property=
    "contextConfigLocation" value="/WEB-INF/beans.xml"/>
    </plug-in>


    前面已經(jīng)提到過,在 下載 部分,您能夠找到這三個完全可使用的例子的完整源代碼。每個例子都為一個書籍搜索應用程序提供一種不同的 Struts 和 Spring 的整合方法。您可以在這里看到例子的要點,但是您也可以下載應用程序以查看所有的細節(jié)。





    竅門 1. 使用 Spring 的 ActionSupport

    手動創(chuàng)建一個 Spring 環(huán)境是一種整合 Struts 和 Spring 的最直觀的方式。為了使它變得更簡單,Spring 提供了一些幫助。為了方便地獲得 Spring 環(huán)境,org.springframework.web.struts.ActionSupport 類提供了一個 getWebApplicationContext() 方法。您所做的只是從 Spring 的 ActionSupport 而不是 Struts Action 類擴展您的動作,如清單 1 所示:


    清單 1. 使用 ActionSupport 整合 Struts

    package ca.nexcel.books.actions;

    import java.io.IOException;

    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;

    import org.apache.struts.action.ActionError;
    import org.apache.struts.action.ActionErrors;
    import org.apache.struts.action.ActionForm;
    import org.apache.struts.action.ActionForward;
    import org.apache.struts.action.ActionMapping;
    import org.apache.struts.action.DynaActionForm;
    import org.springframework.context.ApplicationContext;
    import org.springframework.web.struts.ActionSupport;

    import ca.nexcel.books.beans.Book;
    import ca.nexcel.books.business.BookService;

    public class SearchSubmit extends ActionSupport { |(1)


    public ActionForward execute(
    ActionMapping mapping,
    ActionForm form,
    HttpServletRequest request,
    HttpServletResponse response)
    throws IOException, ServletException {

    DynaActionForm searchForm = (DynaActionForm) form;
    String isbn = (String) searchForm.get("isbn");

    //the old fashion way
    //BookService bookService = new BookServiceImpl();

    ApplicationContext ctx =
    getWebApplicationContext(); |(2)
    BookService bookService =
    (BookService) ctx.getBean("bookService"); |(3)

    Book book = bookService.read(isbn.trim());

    if (null == book) {
    ActionErrors errors = new ActionErrors();
    errors.add(ActionErrors.GLOBAL_ERROR,new ActionError
    ("message.notfound"));
    saveErrors(request, errors);
    return mapping.findForward("failure") ;
    }

    request.setAttribute("book", book);
    return mapping.findForward("success");
    }
    }


    讓我們快速思考一下這里到底發(fā)生了什么。在 (1) 處,我通過從 Spring 的 ActionSupport 類而不是 Struts 的 Action 類進行擴展,創(chuàng)建了一個新的 Action在 (2) 處,我使用 getWebApplicationContext() 方法獲得一個 ApplicationContext為了獲得業(yè)務服務,我使用在 (2) 處獲得的環(huán)境在 (3) 處查找一個 Spring bean。

    這 種技術很簡單并且易于理解。不幸的是,它將 Struts 動作與 Spring 框架耦合在一起。如果您想替換掉 Spring,那么您必須重寫代碼。并且,由于 Struts 動作不在 Spring 的控制之下,所以它不能獲得 Spring AOP 的優(yōu)勢。當使用多重獨立的 Spring 環(huán)境時,這種技術可能有用,但是在大多數(shù)情況下,這種方法不如另外兩種方法合適。





    竅門 2. 覆蓋 RequestProcessor

    將 Spring 從 Struts 動作中分離是一個更巧妙的設計選擇。分離的一種方法是使用 org.springframework.web.struts.DelegatingRequestProcessor 類來覆蓋 Struts 的 RequestProcessor 處理程序,如清單 2 所示:


    清單 2. 通過 Spring 的 DelegatingRequestProcessor 進行整合

    <?xml version="1.0" encoding="ISO-8859-1" ?>

    <!DOCTYPE struts-config PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"
    "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">

    <struts-config>
    <form-beans>
    <form-bean name="searchForm"
    type="org.apache.struts.validator.DynaValidatorForm">
    <form-property name="isbn" type="java.lang.String"/>
    </form-bean>

    </form-beans>

    <global-forwards type="org.apache.struts.action.ActionForward">
    <forward name="welcome" path="/welcome.do"/>
    <forward name="searchEntry" path="/searchEntry.do"/>
    <forward name="searchSubmit" path="/searchSubmit.do"/>
    </global-forwards>

    <action-mappings>
    <action path="/welcome" forward="/WEB-INF/pages/welcome.htm"/>
    <action path="/searchEntry" forward="/WEB-INF/pages/search.jsp"/>
    <action path="/searchSubmit"
    type="ca.nexcel.books.actions.SearchSubmit"
    input="/searchEntry.do"
    validate="true"
    name="searchForm">
    <forward name="success" path="/WEB-INF/pages/detail.jsp"/>
    <forward name="failure" path="/WEB-INF/pages/search.jsp"/>
    </action>

    </action-mappings>

    <message-resources parameter="ApplicationResources"/>

    <controller processorClass="org.springframework.web.struts.
    DelegatingRequestProcessor"/> |(1)

    <plug-in className="org.apache.struts.validator.ValidatorPlugIn">
    <set-property property="pathnames"
    value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml"/>
    </plug-in>


    <plug-in className="org.springframework.web.struts.ContextLoaderPlugIn">
    <set-property property="csntextConfigLocation" value="/WEB-INF/beans.xml"/>
    </plug-in>

    </struts-config>


    我利用了 <controller> 標記來用 DelegatingRequestProcessor 覆蓋默認的 Struts RequestProcessor下一步是在我的 Spring 配置文件中注冊該動作,如清單 3 所示:


    清單 3. 在 Spring 配置文件中注冊一個動作

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
    "http://www.springframework.org/dtd/spring-beans.dtd">

    <beans>
    <bean id="bookService" class="ca.nexcel.books.business.BookServiceImpl"/>

    <bean name="/searchSubmit"
    class="ca.nexcel.books.actions.SearchSubmit"> |(1)
    <property name="bookService">
    <ref bean="bookService"/>
    </property>
    </bean>
    </beans>


    注意:在 (1) 處,我使用名稱屬性注冊了一個 bean,以匹配 struts-config 動作映射名稱。SearchSubmit 動作揭示了一個 JavaBean 屬性,允許 Spring 在運行時填充屬性,如清單 4 所示:


    清單 4. 具有 JavaBean 屬性的 Struts 動作

    package ca.nexcel.books.actions;

    import java.io.IOException;

    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;

    import org.apache.struts.action.Action;
    import org.apache.struts.action.ActionError;
    import org.apache.struts.action.ActionErrors;
    import org.apache.struts.action.ActionForm;
    import org.apache.struts.action.ActionForward;
    import org.apache.struts.action.ActionMapping;
    import org.apache.struts.action.DynaActionForm;

    import ca.nexcel.books.beans.Book;
    import ca.nexcel.books.business.BookService;

    public class SearchSubmit extends Action {

    private BookService bookService;
    public BookService getBookService() {
    return bookService;
    }

    public void setBookService(BookService bookService) { | (1)
    this.bookService = bookService;
    }

    public ActionForward execute(
    ActionMapping mapping,
    ActionForm form,
    HttpServletRequest request,
    HttpServletResponse response)
    throws IOException, ServletException {

    DynaActionForm searchForm = (DynaActionForm) form;
    String isbn = (String) searchForm.get("isbn");

    Book book = getBookService().read(isbn.trim()); |(2)

    if (null == book) {
    ActionErrors errors = new ActionErrors();
    errors.add(ActionErrors.GLOBAL_ERROR,new ActionError("message.notfound"));
    saveErrors(request, errors);
    return mapping.findForward("failure") ;
    }

    request.setAttribute("book", book);
    return mapping.findForward("success");
    }

    }


    在清單 4 中,您可以了解到如何創(chuàng)建 Struts 動作。在 (1) 處,我創(chuàng)建了一個 JavaBean 屬性。DelegatingRequestProcessor自 動地配置這種屬性。這種設計使 Struts 動作并不知道它正被 Spring 管理,并且使您能夠利用 Sping 的動作管理框架的所有優(yōu)點。由于您的 Struts 動作注意不到 Spring 的存在,所以您不需要重寫您的 Struts 代碼就可以使用其他控制反轉容器來替換掉 Spring。

    DelegatingRequestProcessor 方法的確比第一種方法好,但是仍然存在一些問題。如果您使用一個不同的 RequestProcessor則需要手動整合 Spring 的 DelegatingRequestProcessor添加的代碼會造成維護的麻煩并且將來會降低您的應用程序的靈活性。此外,還有過一些使用一系列命令來代替 Struts RequestProcessor 的傳聞。 這種改變將會對這種解決方法的使用壽命造成負面的影響。





    竅門 3. 將動作管理委托給 Spring

    一個更好的解決方法是將 Strut 動作管理委托給 Spring。您可以通過在 struts-config 動作映射中注冊一個代理來實現(xiàn)。代理負責在 Spring 環(huán)境中查找 Struts 動作。由于動作在 Spring 的控制之下,所以它可以填充動作的 JavaBean 屬性,并為應用諸如 Spring 的 AOP 攔截器之類的特性帶來了可能。

    清單 5 中的 Action 類與清單 4 中的相同。但是 struts-config 有一些不同:


    清單 5. Spring 整合的委托方法

    <?xml version="1.0" encoding="ISO-8859-1" ?>

    <!DOCTYPE struts-config PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"
    "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">

    <struts-config>
    <form-beans>
    <form-bean name="searchForm"
    type="org.apache.struts.validator.DynaValidatorForm">
    <form-property name="isbn" type="java.lang.String"/>
    </form-bean>

    </form-beans>

    <global-forwards type="org.apache.struts.action.ActionForward">
    <forward name="welcome" path="/welcome.do"/>
    <forward name="searchEntry" path="/searchEntry.do"/>
    <forward name="searchSubmit" path="/searchSubmit.do"/>
    </global-forwards>

    <action-mappings>
    <action path="/welcome" forward="/WEB-INF/pages/welcome.htm"/>
    <action path="/searchEntry" forward="/WEB-INF/pages/search.jsp"/>
    <action path="/searchSubmit"
    type="org.springframework.web.struts.DelegatingActionProxy" |(1)
    input="/searchEntry.do"
    validate="true"
    name="searchForm">
    <forward name="success" path="/WEB-INF/pages/detail.jsp"/>
    <forward name="failure" path="/WEB-INF/pages/search.jsp"/>
    </action>

    </action-mappings>

    <message-resources parameter="ApplicationResources"/>


    <plug-in className="org.apache.struts.validator.ValidatorPlugIn">
    <set-property
    property="pathnames"
    value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml"/>
    </plug-in>


    <plug-in
    className="org.springframework.web.struts.ContextLoaderPlugIn">
    <set-property property="contextConfigLocation" value="/WEB-INF/beans.xml"/>
    </plug-in>


    </struts-config>


    清單 5 是一個典型的 struts-config.xml 文件,只有一個小小的差別。它注冊 Spring 代理類的名稱,而不是聲明動作的類名,如(1)處所示。DelegatingActionProxy 類使用動作映射名稱查找 Spring 環(huán)境中的動作。這就是我們使用 ContextLoaderPlugIn 聲明的環(huán)境。

    將一個 Struts 動作注冊為一個 Spring bean 是非常直觀的,如清單 6 所示。我利用動作映射使用 <bean> 標記的名稱屬性(在這個例子中是 "/searchSubmit")簡單地創(chuàng)建了一個 bean。這個動作的 JavaBean 屬性像任何 Spring bean 一樣被填充:


    清單 6. 在 Spring 環(huán)境中注冊一個 Struts 動作

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
    "http://www.springframework.org/dtd/spring-beans.dtd">

    <beans>
    <bean id="bookService" class="ca.nexcel.books.business.BookServiceImpl"/>

    <bean name="/searchSubmit"
    class="ca.nexcel.books.actions.SearchSubmit">
    <property name="bookService">
    <ref bean="bookService"/>
    </property>
    </bean>

    </beans>






    動作委托的優(yōu)點

    動作委托解決方法是這三種方法中最好的。Struts 動作不了解 Spring,不對代碼作任何改變就可用于非 Spring 應用程序中。RequestProcessor 的改變不會影響它,并且它可以利用 Spring AOP 特性的優(yōu)點。

    動作委托的優(yōu)點不止如此。一旦讓 Spring 控制您的 Struts 動作,您就可以使用 Spring 給動作補充更強的活力。例如,沒有 Spring 的話,所有的 Struts 動作都必須是線程安全的。如果您設置 <bean> 標記的 singleton 屬性為“false”,那么不管用何種方法,您的應用程序都將在每一個請求上有一個新生成的動作對象。您可能不需要這種特性,但是把它放在您的工具箱中也 很好。您也可以利用 Spring 的生命周期方法。例如,當實例化 Struts 動作時,<bean> 標記的 init-method 屬性被用于運行一個方法。類似地,在從容器中刪除 bean 之前,destroy-method 屬性執(zhí)行一個方法。這些方法是管理昂貴對象的好辦法,它們以一種與 Servlet 生命周期相同的方式進行管理。





    攔截 Struts

    前 面提到過,通過將 Struts 動作委托給 Spring 框架而整合 Struts 和 Spring 的一個主要的優(yōu)點是:您可以將 Spring 的 AOP 攔截器應用于您的 Struts 動作。通過將 Spring 攔截器應用于 Struts 動作,您可以用最小的代價處理橫切關注點。

    雖然 Spring 提供很多內(nèi)置攔截器,但是我將向您展示如何創(chuàng)建自己的攔截器并把它應用于一個 Struts 動作。為了使用攔截器,您需要做三件事:

    1. 創(chuàng)建攔截器。
    2. 注冊攔截器。
    3. 聲明在何處攔截代碼。

    這看起來非常簡單的幾句話卻非常強大。例如,在清單 7 中,我為 Struts 動作創(chuàng)建了一個日志記錄攔截器。 這個攔截器在每個方法調(diào)用之前打印一句話:


    清單 7. 一個簡單的日志記錄攔截器

    package ca.nexcel.books.interceptors;

    import org.springframework.aop.MethodBeforeAdvice;

    import java.lang.reflect.Method;

    public class LoggingInterceptor implements MethodBeforeAdvice {

    public void before(Method method, Object[] objects, Object o) throws Throwable {
    System.out.println("logging before!");
    }
    }


    這個攔截器非常簡單。before() 方法在攔截點中每個方法之前運行。在本例中,它打印出一句話,其實它可以做您想做的任何事。下一步就是在 Spring 配置文件中注冊這個攔截器,如清單 8 所示:


    清單 8. 在 Spring 配置文件中注冊攔截器

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
    "http://www.springframework.org/dtd/spring-beans.dtd">

    <beans>
    <bean id="bookService" class="ca.nexcel.books.business.BookServiceImpl"/>

    <bean name="/searchSubmit"
    class="ca.nexcel.books.actions.SearchSubmit">
    <property name="bookService">
    <ref bean="bookService"/>
    </property>
    </bean>

    <!-- Interceptors -->
    <bean name="logger"
    class="ca.nexcel.books.interceptors.LoggingInterceptor"/> |(1)

    <!-- AutoProxies -->
    <bean name="loggingAutoProxy"
    class="org.springframework.aop.framework.autoproxy.
    BeanNameAutoProxyCreator"> |(2)
    <property name="beanNames">
    <value>/searchSubmit</valuesgt; |(3)
    </property>
    <property name="interceptorNames">
    <list>
    <value>logger</value> |(4)
    </list>
    </property>
    </bean>

    </beans>


    您可能已經(jīng)注意到了,清單 8 擴展了 清單 6 中所示的應用程序以包含一個攔截器。具體細節(jié)如下:

    • 在 (1) 處,我注冊了這個攔截器。
    • 在 (2) 處,我創(chuàng)建了一個 bean 名稱自動代理,它描述如何應用攔截器。還有其他的方法定義攔截點,但是這種方法常見而簡便。
    • 在 (3) 處,我將 Struts 動作注冊為將被攔截的 bean。如果您想要攔截其他的 Struts 動作,則只需要在 "beanNames" 下面創(chuàng)建附加的 <value> 標記。
    • 在 (4) 處,當攔截發(fā)生時,我執(zhí)行了在 (1) 處創(chuàng)建的攔截器 bean 的名稱。這里列出的所有攔截器都應用于“beanNames”。

    就是這樣。就像這個例子所展示的,將您的 Struts 動作置于 Spring 框架的控制之下,為處理您的 Struts 應用程序提供了一系列全新的選擇。在本例中,使用動作委托可以輕松地利用 Spring 攔截器提高 Struts 應用程序中的日志記錄能力。





    結束語

    在本文中,您已經(jīng)學習了將 Struts 動作整合到 Spring 框架中的三種竅門。使用 Spring 的 ActionSupport 來整合 Struts(第一種竅門中就是這樣做的)簡單而快捷,但是會將 Struts 動作與 Spring 框架耦合在一起。如果您需要將應用程序移植到一個不同的框架,則需要重寫代碼。第二種解決方法通過委托 RequestProcessor 巧妙地解開代碼的耦合,但是它的可擴展性不強,并且當 Struts 的 RequestProcessor 變成一系列命令時,這種方法就持續(xù)不了很長時間。第三種方法是這三種方法中最好的:將 Struts 動作委托給 Spring 框架可以使代碼解耦,從而使您可以在您的 Struts 應用程序中利用 Spring 的特性(比如日志記錄攔截器)。

    三種 Struts-Spring 整合竅門中的每一種都被實現(xiàn)成一個完整可用的應用程序。請參閱 下載 部分仔細研究它們。






    下載
    描述名字大小 下載方法
    ActionSupport sample codej-sr2-actionsupport.zip5 MB  FTP
    RequestProcessor sample codej-sr2-requestprocessor.zip5 MB  FTP
    Delegate sample codej-sr2-delegate.zip5 MB  FTP

    posted @ 2005-11-21 15:42 DenisLing 閱讀(1074) | 評論 (2)編輯 收藏

    僅列出標題  
    主站蜘蛛池模板: 亚洲国产综合自在线另类| 成人免费视频77777| 亚洲成a人无码亚洲成av无码 | 国产a v无码专区亚洲av | 亚洲色偷偷偷网站色偷一区| 久久久久免费看黄A片APP | 久久精品无码一区二区三区免费| 免费在线观看毛片| 亚洲一区二区三区国产精品无码| 一级毛片大全免费播放| 四虎在线播放免费永久视频| 亚洲日韩中文字幕| 国产99视频精品免费专区| 女人张开腿给人桶免费视频| 日韩精品成人无码专区免费| 两个人看的www免费| 色婷婷六月亚洲婷婷丁香| 日日麻批免费40分钟无码 | 久久精品国产99精品国产亚洲性色| 无码少妇精品一区二区免费动态| caoporm碰最新免费公开视频| 亚洲一区中文字幕在线电影网 | 国国内清清草原免费视频99| 永久免费不卡在线观看黄网站| 亚洲白色白色在线播放| 日本一道本高清免费| 免费做爰猛烈吃奶摸视频在线观看 | 国产久爱免费精品视频| 你是我的城池营垒免费观看完整版| 成人爽a毛片免费| 91青青青国产在观免费影视| 4虎永免费最新永久免费地址| 三年片在线观看免费大全| 日韩特黄特色大片免费视频| 深夜国产福利99亚洲视频| mm1313亚洲精品无码又大又粗| 亚洲区小说区激情区图片区| 亚洲第一区视频在线观看| 亚洲日韩在线中文字幕综合| a级毛片高清免费视频就| 日韩精品视频免费网址|