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

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

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

    PetStore 中EJB 的設計模式[長]

    PetStore 中EJB 的設計模式
    1/1
    目錄..............................................................................................................................................1
    PetStore 中EJB 的設計模式............................................................................................................3
    1. 概述..........................................................................................................................................3
    2. 模式分類..................................................................................................................................4
    2.1. Data Access Object 模式..........................................................................................4
    2.1.1. 意圖...................................................................................................................4
    2.1.2. 動機...................................................................................................................4
    2.1.3. 結構...................................................................................................................5
    2.1.4. PetStore 的例子................................................................................................6
    2.1.4.1 概述...................................................................................................6
    2.1.4.2 CatalogEJB................................................................................................8
    2.1.4.3 CatalogDAO..............................................................................................9
    2.1.4.4 CatalogDAOImpl ......................................................................................9
    2.1.4.5 CatalogDAOFactory................................................................................10
    2.1.5. GOF 模式關系................................................................................................10
    2.1.4.6 Bridge 模式.............................................................................................10
    2.1.4.7 Adapter 模式...........................................................................................11
    2.2. Value Object 模式...................................................................................................11
    2.2.1. 意圖.................................................................................................................11
    2.2.2. 動機.................................................................................................................13
    2.2.3. 結構.................................................................................................................14
    2.2.4. PerStore 的例子..............................................................................................14
    2.3. Session Fa?ade 模式...............................................................................................16
    2.3.1. 意圖.................................................................................................................16
    2.3.2. 動機.................................................................................................................16
    2.3.3. 結構.................................................................................................................17
    2.3.4. PetStore 中的例子..........................................................................................18
    2.1.4.8 概述.................................................................................................18
    2.1.4.9 ShoppingClientFacadeLocalEJB.............................................................18
    2.3.5. GOF 中Facde 模式........................................................................................19
    2.4. Fast-Lane Reader 模式...........................................................................................20
    2.4.1. 意圖.................................................................................................................20
    2.4.2. 動機.................................................................................................................20
    2.4.3. 結構.................................................................................................................21
    2.4.4. PetStore 中的例子..........................................................................................21
    PetStore 中EJB 的設計模式
    2/2
    2.1.4.10 CatalogDAO....................................................................................21
    2.1.4.11 CatalogWebImpl..............................................................................21
    2.1.4.12 ProductListTag ................................................................................22
    2.5. Page-by-Page Iterator 模式.....................................................................................23
    2.5.1. 意圖.................................................................................................................23
    2.5.2. 動機.................................................................................................................24
    2.5.3. 結構.................................................................................................................25
    2.5.4. PetStore 的例子..............................................................................................25
    2.1.4.13 CatalogDAOImp .............................................................................25
    2.1.4.14 ProductItemListTag.........................................................................26
    2.5.5. GOF 的Iterator 模式......................................................................................27
    2.6. ServiceLocator 模式...............................................................................................27
    2.6.1. 意圖.................................................................................................................28
    2.6.2. 動機.................................................................................................................28
    2.6.3. 結構.................................................................................................................28
    2.6.4. PetStore 中的例子..........................................................................................29
    2.1.4.15 ServiceLocatorImpl.........................................................................29
    2.1.4.16 我們項目的例子.............................................................................30
    2.6.5. GOF 模式........................................................................................................32
    2.1.4.17 Singleton 模式................................................................................32
    2.7. Local 模式...............................................................................................................33
    2.7.1. 意圖.................................................................................................................33
    2.7.2. 動機.................................................................................................................33
    2.7.3. 結構.................................................................................................................33
    2.7.4. PetStore 例子..................................................................................................35
    2.8. CMR 模式...............................................................................................................35
    2.8.1. 意圖.................................................................................................................35
    2.8.2. 動機.................................................................................................................35
    2.8.3. 結構.................................................................................................................35
    2.8.4. PetStore 中的例子..........................................................................................36
    2.9. 業務代表模式.........................................................................................................37
    2.9.1. 意圖.................................................................................................................38
    2.9.2. 動機.................................................................................................................38
    2.9.3. 結構.................................................................................................................39
    2.9.4. PetStore 中的例子..........................................................................................39
    2.9.5. GOF 模式........................................................................................................41
    2.1.4.18 Proxy 模式......................................................................................41
    3. EJB 模式關系.........................................................................................................................42
    4. 相關的資料.............................................................................................................................43
    5. 總結........................................................................................................................................43
    PetStore 中EJB 的設計模式
    3/3
    PetStore 中EJB 的設計模式
    Liubing (bliu76@yeah.net)
    1. 概述
    通過分析數據模型,和實際操作PetStore 我們大概對它的數據模型有所了解。現在開始
    分析系統EJB 層的設計模式。首先什么是模式?看Gof 的《設計模式》的定義,就是對被
    用來在特定場景下解決一般設計問題的類和相互通信的對象描述。唉!太深沉了。一頭霧水。
    其實,就是一些經驗,并且經過科學整理,可以在某種場合下反復使用,解決一些問題。當
    然在《設計模式》一書羅列出23 中模式,并且進行了詳細描述。今天我們所說的模式,是
    PetStore 中的EJB 設計經驗。
    關于設計模式,我有很多感觸,Gof 的書我不知看了多少遍,可總是不太明白,我幾年
    沒有使用C++了,里面的例子,看著很不爽。板橋先生網上的例子很簡單明了,但是經過一
    段時間的學習,有點不盡興的感覺。于是又看了其他的幾本書,心中有了一些感覺,可是實
    際寫代碼很難用上,并且現在項目使用J2EE,于是我決定分析PetStore 源碼,看看這些牛
    人是怎樣使用模式的。在我們的項目開發中也照葫蘆畫瓢,使用一把。
    關于PetStore 的模式,SUN 的站點列出了以下幾種模式,當然其中的FrontController 屬
    于Web 層的。
    Pattern Intent
    Data Access
    Object
    Decouple business logic from data access logic and adapt the resource being
    accessed, so that the type of resource can change easily and independently.
    Fast-Lane
    Reader
    Accelerate read-only data access by not using enterprise beans.
    Front Controller
    Centralize view management (navigation, templating, security, etc.) for a Web
    application in a single object that handles incoming client requests.
    Page-by-Page
    Iterator
    Efficiently access a large, remote list by retrieving its elements one sublist of
    value objects at a time.
    Session Facade Provide a unified, workflow-oriented interface to a set of enterprise beans.
    Value Object
    Efficiently transfer remote, fine-grained data by sending a coarse-grained
    view of the data.
    在《J2EE 核心模式》一書中列出了以下幾種模式,當然包括了以上的幾種模式。這本書不
    錯,可惜翻譯的很次。
    業務代表
    值對象
    值對象組裝器
    PetStore 中EJB 的設計模式
    4/4
    值對象列表
    會話外觀
    服務器定位
    數據訪問對象
    服務激發器
    我們首先知道EJB 層有這些模式,我把這些模式簡單介紹一下,包括它的意圖,動機,
    結構,然后看在PetStore 中使用了那些,又是怎樣使用的。我想把我所理解的寫出,如果不
    對的地方,請大家指出。
    2. 模式分類
    2.1. Data Access Object 模式
    這個模式SUN 上有詳細的描述,并且《程序員 6 期》中有板橋先生的一遍文章介紹了它。
    這模式使用了GoF 中Bridge 和Adapter 模式。如果大家不熟悉,最好看下Gof 的介紹,現
    在我感覺GoF 的書當作一個模式參考手冊比較不錯。一般剛開始就看這本,很難看懂,這
    樣就打消了大家的積極性,這年頭,有學習上進的想法就很不錯了。在被人打擊,太不好了。
    2.1.1. 意圖
    Decouple business logic from data access logic and adapt the resource being accessed, so that
    the type of resource can change easily and independently.(算了我不翻譯了,實際就是分離業
    務邏輯和數據讀取,把數據的讀取寫到了DAO 中。這樣增強了系統的靈活性。如果你看過
    GoF 的書,這個口號你一定記憶有心(針對接口編程,而不是針對實現編程),當然了老米
    的態度決定一切也很有哲理。設計模式就是把調用與實現分離,如果你感覺,很羅嗦被分的
    亂七八糟,實現一個東西要好多類和接口,這樣你就對設計模式有了一定的了解了。)
    2.1.2. 動機
    These problems can be avoided by removing data access logic from
    enterprise beans and abstracting data access functionality into a
    separate interface. Enterprise beans carry out their business logic
    in terms of operations on that interface, which is implemented by a
    data access object (DAO) appropriate for the type of resource being
    used. (就是業務邏輯中不負責數據的存取,把它放到DAO 中,這些數據的
    格式,提供商一旦發生改變,只需修改DAO 即可)
    For example, the Java Pet Store application's OrderEJB component
    accesses a database through its associated OrderDAO class, which knows
    how to perform load, save, and find operations on order data in the
    PetStore 中EJB 的設計模式
    5/5
    persistent store. Because the bean delegates its persistence-related
    tasks to the DAO, it can concentrate on implementing business methods.
    At deployment time, the application administrator configures the
    implementation of OrderDAO to be one of OrderDAOCS, OrderDAOOracle, or
    OrderDAOSybase, depending on whether an Cloudscape, Oracle, or Sybase
    database is used. No matter what choice is made, the OrderEJB is
    unaffected, because it is programmed to an interface, not to an
    implementation.(很簡單,我就不翻譯了吧,要不就被我糟蹋原意了)。
    不過我現在使用的是JB6.0+Weblogic6。1 開發bmp,我們大多使用了JB 的
    向導,它自動生成了代碼,可是它沒有實現這種模式.在SessionBean 中我們
    封裝了JDBC 的數據讀取,有點向這種模式。
    2.1.3. 結構
    它使用了GOF 中的Bridge 和Adapter 模式。整個結構圖如下:
    大家可能看明白,其實就是在BusinessObject 中提供了業務邏輯方法,假如它必須要讀取
    數據,但是這個數據可能存在Oracle 數據庫中,又有可能存在excel 文件中,也許存在XML
    文件中,如果我們在這個方法中直接讀取數據,那就要寫這樣的語句
    switch (DATA_TYPE){
    case ORACLE:
    通過JDBC 讀取Oracle 數據
    break;
    case Excel:
    通過專門的API 進行讀取,Excel 文件
    PetStore 中EJB 的設計模式
    6/6
    break;
    case XML
    通過JDOM 進行,分析XML 文件;
    break;
    }
    這樣,業務邏輯中到處是數據的讀取,并且修改程序,很麻煩。于是這些牛人,想出一
    個使用接口DAO(就是DataAccessObject),它什么具體的事都不做,就申明幾個方法,在
    業務邏輯類中,只管調用它就行了,好像在說我能做什么,不要管我怎樣做,就想我們的銷
    售接項目一樣,說我們公司什么事都可以做。但是項目接下以后,就由我們這些命苦的開發
    人員來實現。最后也就是DAOImplementor 根據數據的不同有不同的具體類來讀取(它有可
    能是DAOImplementor_ORACLE 類實現讀取Oracle 數據庫,DAOImplementor_EXCEL,
    實現通過API 讀取Excel 文件,DAOImplementor_XML 實現讀取XML 文件)。這樣你可,
    在業務邏輯類中,不負責數據的讀取,只關注業務邏輯的實現,它只需調用DAO 獲得數據,
    真正實現數據的讀取是DAOImplementor_ORACLE 這樣的類。
    我解釋的不知你是否明白,反正我是知道了。多看幾次就明白了,其實很簡單。
    2.1.4. PetStore 的例子
    2.1.4.1 概述
    首先我們看UML 圖,這是PetStore 自帶UML 圖,我用Rose 畫還需要時間,他們使用
    了一種叫ARGOUML 的工具,你可以下載,是免費的感覺遠不如Rose.
    PetStore 中EJB 的設計模式
    7/7
    這其中使用了GoF 的工場模式,也是簡單工場模式,它負責使用那個具體實現類,好像
    大家都可以干這活,它來選擇到底由誰來做,就是我們的人力資源的。
    我們在仔細分析一下,就是在CatalogEJB 類中有一些業務邏輯,如getProduct,它來取
    某項分類的產品,這樣也許讀取數據庫,也有可能讀取XML文件,于是它就調用CatalogDAO
    的方法,來實現,但是CatalogEJB 并不知道數據到底存在那里,它只管讀就行了。可是
    CatalogDAO 也只是聲明這個方法,真正辛苦干事情的就是CatalogDAOImpl,它負責讀取數
    據庫。我們不要忘記,在CatalogEJB 有個方法,它調用了工場,它來確定又誰來做。
    唉,下面是我使用Rose 的逆向工程,獲得的UML 圖。
    PetStore 中EJB 的設計模式
    8/8
    CatalogDAOFactory
    getDAO()
    (from dao)
    CatalogDAOImpl
    getDataSource()
    getCategory()
    getCategories()
    getProduct()
    getProducts()
    getItem()
    getItems()
    searchItems()
    (f rom dao )
    CatalogEJB
    ejbCreate()
    setSessionContext()
    ejbRemove()
    ejbActivate()
    ejbPassivate()
    destroy()
    getCategory()
    getCategories()
    getProducts()
    getProduct()
    getItems()
    getItem()
    searchItems()
    <<EJBSession>>
    CatalogDAO
    getCategory()
    getCategories()
    getProduct()
    getProducts()
    getItem()
    getItems()
    searchItems()
    (from dao)
    CatalogLocalHome
    create()
    (f ro m ej b)
    2.1.4.2 CatalogEJB
    public class CatalogEJB implements SessionBean {
    //那個光說話,不做是的家伙,真正做事CatalogDAOImpl 類,CatalogEJB 不知道,
    其實現實生活中就有這種事情
    protected CatalogDAO dao;
    public void ejbCreate() {
    try {
    //使用工程模式,產生DAO
    dao = CatalogDAOFactory.getDAO();
    } catch (CatalogDAOSysException se) {
    }
    }
    PetStore 中EJB 的設計模式
    9/9
    //獲得產品信息
    public Page getProducts(String categoryID, int start, int count, Locale l) {
    try {
    //調用DAO,實現業務邏輯
    return dao.getProducts(categoryID, start, count, l);
    }
    catch (CatalogDAOSysException se) {
    throw new EJBException(se.getMessage());
    }
    }
    2.1.4.3 CatalogDAO
    public interface CatalogDAO {
    //聲明能力
    public Page getProducts(String categoryID, int start, int count, Locale l)
    throws CatalogDAOSysException;
    }
    2.1.4.4 CatalogDAOImpl
    DAOpublic class CatalogDAOImpl implements CatalogDAO {
    public Page getProducts(String categoryID, int start, int count, Locale l){
    try {
    c = getDataSource().getConnection();
    ps = c.prepareStatement("select a.productid, name, descn "
    + "from (product a join "
    + "product_details b on "
    + "a.productid=b.productid) "
    + "where locale = ? "
    + "and a.catid = ? "
    + "order by name",
    ResultSet.TYPE_SCROLL_INSENSITIVE,
    ResultSet.CONCUR_READ_ONLY);
    ps.setString(1, l.toString());
    ps.setString(2, categoryID);
    rs = ps.executeQuery();
    //讀取數據庫
    rs.close();
    ps.close();
    }
    catch (SQLException se) {
    PetStore 中EJB 的設計模式
    10/10
    }
    }
    2.1.4.5 CatalogDAOFactory
    public class CatalogDAOFactory {
    public static CatalogDAO getDAO() throws CatalogDAOSysException {
    CatalogDAO catDao = null;
    try {
    //依據系統配置的信息,產生一個實現類
    catDao = (CatalogDAO) Class.forName(className).newInstance();
    } catch (NamingException ne) {
    } catch (Exception se) {
    }
    return catDao;
    }
    }
    2.1.5. GOF 模式關系
    我可以簡單解釋以下。
    2.1.4.6 Bridge 模式
    結構
    意圖:將抽象部分與它的實現部分分離,使它們都可以獨立地變化。
    適用性
    PetStore 中EJB 的設計模式
    11/11
    ? 你不希望在抽象和它的實現部分之間有一個固定的綁定關系。例如這種情況可能是
    因為,在程序運行時刻實現部分應可以被選擇或者切換。
    ? 類的抽象以及它的實現都應該可以通過生成子類的方法加以擴充。這時B r i d g e 模
    式使你可以對不同的抽象接口和實現部分進行組合,并分別對它們進行擴充。
    ? 對一個抽象的實現部分的修改應對客戶不產生影響,即客戶的代碼不必重新編譯。
    2.1.4.7 Adapter 模式
    它有兩種方式實現。比較簡單,我就不多說了。
    2.2. Value Object 模式
    值對象模式,在SUN 的站點上有詳細的描述,并且《J2EE 核心模式》上也有詳細描述,
    其實這種模式,我們每天都在使用,目的就是減少網絡流量,提高效率,許多書上叫做的粗
    粒度。和這種模式相關的還有復合實體,值對象組裝器,值列表處理器。
    我感覺在項目開發中有一個人負責系統的全部entityBean,為每個entityBean 建立值對
    象,并且建立他們之間的關系。其他的開發人員只管調用就行了,如果數據庫修改,它來修
    改。這種方式,我建議大家使用。
    2.2.1. 意圖
    Efficiently transfer remote, fine-grained data by sending a
    coarse-grained view of the data.
    我們知道EJB 的調用使用了遠程方法,它的效率一般要遠低于本地方法的
    調用,這樣我們要讀取一個對象,如果使用他的getXX 方法就多次調用了遠
    程,效率很低,如果一次性讀到值對象,這就減少了遠程調用。
    我們在實際開發中,一般為每個EntityBean 建一個值對象,并且在
    entityBean 中的Home 接口中,增加一個create 方法,參數就是值對象. 并
    且在接口中增加setData 和getData 方法。
    ?? Home 接口
    public interface TAccountAcptRemoteHome extends javax.ejb.EJBHome
    {
    //在創建時,使用值對象,如果修改數據結構,接口不需改變,只修改
    屬性就行了
    public TAccountAcptRemote create(TAccountAcptModel data)
    throws CreateException, RemoteException;
    PetStore 中EJB 的設計模式
    12/12
    }
    ?? 聲明接口(遠程或本地接口)
    public interface TAccountAcptRemote extends javax.ejb.EJBObject {
    //通過這個接口,一次性獲得值對象,不需分別使用getXX,減少網絡
    調用次數,提高效率
    public TAccountAcptModel getData() throws RemoteException;
    public void getData(TaccountAcptModel data) throws
    RemoteException;
    }
    ?? 值對象
    public class TAccountAcptModel implements java.io.Serializable {
    public java.lang.String acceptId ;
    public java.lang.String accountId ;
    public java.lang.String ownerId ;
    public java.lang.String accountName;
    public java.lang.String accountAddr;
    public java.lang.String accountZip ;
    public java.lang.String bankId ;
    public java.lang.String account ;
    public java.lang.String payTypeId ;
    public java.lang.String state ;
    public java.lang.String postMode ;
    public java.lang.String postAddr ;
    public java.lang.String postZip ;
    PetStore 中EJB 的設計模式
    13/13
    public java.lang.String postMan ;
    public java.math.BigDecimal preSum ;
    public java.sql.Date createDate ;
    public java.sql.Date unsignDate ;
    }
    2.2.2. 動機
    Some entities have a set of attributes that are always used together.
    In the Java Pet Store application, the contact information of a
    customer (city, state, zip code, etc.) is an example of one such group.
    Suppose that in total, a customer's contact information is composed
    of 15 individual attributes, each accessible by a corresponding getXXX
    method in CustomerEJB. Then, every time a customer's contact information
    is requested, 15 remote getXXX calls will be invoked on the CustomerEJB,
    one for each attribute. This will incur heavy costs in network traffic
    and EJB container resource usage.
    The Java Pet Store application reduces these costs by adopting a
    coarse-grained view of the fine-grained contact information. It
    aggregates the contact information-related attributes of the
    CustomerEJB into an instance of ContactInformation. This instance, or value
    object, is then serialized and sent over the network to a requesting
    client, where the object is deserialized. Subsequent read accesses go
    through the value object rather than the remote entity object. Since
    these accesses are local, they require no server communication and use
    fewer resources.
    PetStore 中EJB 的設計模式
    14/14
    2.2.3. 結構
    EnterpriseBean 業務對象,實現了業務邏輯
    ValueObject 實現了串行化值對象。
    2.2.4. PerStore 的例子
    PetStore 中存在大量的例子,基本上每個EJB 中都可以找到它的蹤影。
    PetStore 中EJB 的設計模式
    15/15
    ?? 如值對象ProfileInfo(一定要實現Serializable 接口,就是串行化)
    public class ProfileInfo implements java.io.Serializable {
    private String defaultPreferredLanguage = null;
    private String defaultFavoriteCategory = null;
    private boolean defaultMyListPreference = false;
    private boolean defaultBannerPreference = false;
    public ProfileInfo( String defaultPreferredLanguage,
    String defaultFavoriteCategory,
    boolean defaultMyListPreference,
    boolean defaultBannerPreference) {
    this.defaultPreferredLanguage = defaultPreferredLanguage;
    this.defaultFavoriteCategory = defaultFavoriteCategory;
    this.defaultMyListPreference = defaultMyListPreference;
    this.defaultBannerPreference = defaultBannerPreference;
    }
    public String getPreferredLanguage() {
    return defaultPreferredLanguage;
    }
    public String getFavoriteCategory() {
    return defaultFavoriteCategory;
    }
    public boolean getBannerPreference() {
    return defaultBannerPreference;
    }
    public boolean getMyListPreference() {
    return defaultMyListPreference;
    }
    }
    ?? 使用類,提高調用粗粒度,使用值對象
    public abstract class CustomerEJB implements javax.ejb.EntityBean {
    //一次調用,獲得值對象,提高效率
    public abstract ProfileLocal getProfile();
    //設置值對象
    public abstract void setProfile(ProfileLocal profile);
    }
    PetStore 中EJB 的設計模式
    16/16
    2.3. Session Fa?ade 模式
    眾所周知在Gof 中有Fa?ade(外觀)模式,我們只是把這種模式應用到EJB 中罷了。它
    的目的其實很明顯,就是給子系統提供一個一致的接口,這樣使系統業務邏輯集中,
    使系統的業務邏輯和調用部分松耦合。現在我是一般這些使用的,首先定義一些
    EntityBean,和一些實現業務邏輯的SessionBean,然后在把這些業務邏輯封裝成
    SessionBean 供web 層調用,一般在調用層不負責事務的管理,一個業務邏輯就是一個
    獨立的事務。在Web 層其實只需獲得畫面的數據,和簡單的校驗,然后直接提交到
    EJB 層,進行處理,這樣使Web 的功能很簡單。
    2.3.1. 意圖
    Provide a unified, workflow-oriented interface to a set of enterprise
    beans.
    把SessionBean 用作Fa?ade 以封裝參與業務的多個對象,提供給用戶統一的粗粒度訪問。
    簡單一些,就是盡可能把事情放在EJB 層來做,接口越簡單越好,最好調用層不負責事務,
    一次調用就是一次事務,累死EJB。
    2.3.2. 動機
    這些是抄J2ee 核心模式的內容,顯得深沉一些。
    ?? 通過隱藏了業務組件之間所有的復雜交互活動,向客戶提供一個簡單的接口
    ?? 減少通過網絡并跨越服務層被直接暴露給客戶端的業務對象數目
    ?? 向客戶隱藏業務組件之間的交互和相互
    在下圖大家應該能夠看明白一些,Client 如果處理一件事情,需要調用SessionBean1,
    和兩個實體Bean,這樣客戶端要負責事務,并且多次網絡調用,降低的效率。系統一定修改,
    兩側都要大修。你應該認為不爽吧。
    如果我們把這些業務邏輯封裝在SessionFacade 里面,這樣調用很簡單,實際遠程調用
    只需一次,接口也很簡單。
    PetStore 中EJB 的設計模式
    17/17
    2.3.3. 結構
    我看下結構,其實就是在SessionFacade 中,封裝業務邏輯,簡化接口,大家應該一看就明
    白。
    PetStore 中EJB 的設計模式
    18/18
    2.3.4. PetStore 中的例子
    2.1.4.8 概述
    在PetStore 中就使用了這種模式,不過大家一般在開發中都可能使用這種模式,只是自己不
    知道罷了。
    2.1.4.9 ShoppingClientFacadeLocalEJB
    public class ShoppingClientFacadeLocalEJB implements SessionBean {
    /*
    * Asume that the customer userId has been set
    */
    //它封裝了調用客戶的EntityBean
    public CustomerLocal getCustomer() throws FinderException {
    if (userId == null) {
    throw new GeneralFailureException("ShoppingClientFacade: failed to look up
    name of customer: userId is not set" );
    }
    try {
    InitialContext ic = new InitialContext();
    Object o = ic.lookup("java:comp/env/ejb/local/Customer");
    CustomerLocalHome home =(CustomerLocalHome)o;
    customer = home.findByPrimaryKey(userId);
    } catch (javax.naming.NamingException nx) {
    throw new GeneralFailureException("ShoppingClientFacade: failed to look up
    name of customer: caught " + nx);
    }
    return customer;
    }
    //它封裝了產生客戶方法
    public CustomerLocal createCustomer(String userId) {
    try {
    InitialContext ic = new InitialContext();
    Object o = ic.lookup("java:comp/env/ejb/local/Customer");
    CustomerLocalHome home =(CustomerLocalHome)o;
    customer = home.create(userId);
    this.userId = userId;
    } catch (javax.ejb.CreateException ce) {
    throw new GeneralFailureException("ShoppingClientFacade: failed to create
    PetStore 中EJB 的設計模式
    19/19
    customer: caught " + ce);
    } catch (javax.naming.NamingException nx) {
    throw new GeneralFailureException("ShoppingClientFacade: failed to look up
    name of customer: caught " + nx);
    }
    return customer;
    }
    }
    2.3.5. GOF 中Facde 模式
    意圖
    為子系統中的一組接口提供一個一致的界面,F a c a d e 模式定義了一個高層接口,這個
    接口使得這一子系統更加容易使用。
    結構
    動機
    ? 當你要為一個復雜子系統提供一個簡單接口時。子系統往往因為不斷演化而變得越
    來越復雜。大多數模式使用時都會產生更多更小的類。這使得子系統更具可重用性,
    也更容易對子系統進行定制,但這也給那些不需要定制子系統的用戶帶來一些使用
    上的困難。F a c a d e 可以提供一個簡單的缺省視圖,這一視圖對大多數用戶來說已
    經足夠,而那些需要更多的可定制性的用戶可以越過f a c a d e 層。
    ? 客戶程序與抽象類的實現部分之間存在著很大的依賴性。引入f a c a d e 將這個子系
    統與客戶以及其他的子系統分離,可以提高子系統的獨立性和可移植性。
    ? 當你需要構建一個層次結構的子系統時,使用f a c a d e 模式定義子系統中每層的入
    口點。如果子系統之間是相互依賴的,你可以讓它們僅通過f a c a d e 進行通訊,從
    而簡化了它們之間的依賴關系。
    PetStore 中EJB 的設計模式
    20/20
    2.4. Fast-Lane Reader 模式
    我們都知道使用EJB 的效率低,但是在某些情況下效率很重要,這樣這些牛人就不使用
    EJB 而是直接使用DAO 來讀取數據庫,這樣避免使用EJB 的事務,串行化等。不過使用
    EJB 的效率,是個問題,目前我們的營業系統因客戶數量的巨大,效率很低,我最頭痛的就
    是這件事情,不知大家有沒有好的建議,我準備把我們系統中的查詢,報表統計改成不使用
    EJB,也是這種模式。
    2.4.1. 意圖
    Accelerate read-only data access by not using enterprise beans。提高只讀數據的讀取,而不使用
    EJB.
    2.4.2. 動機
    Sometimes it's more important to access a list of data efficiently,
    than that the data in the list be up-to-date. For example, when a user
    browses the Java Pet Store catalog, it's not crucial that what they
    see on the screen be entirely consistent with what's in the database.
    In the interests of usability, however, it is important that the
    catalog data be displayed quickly–and thus retrieved quickly.
    The Fast-Lane Reader pattern can accelerate the retrieval of large
    lists of items from a resource. Instead of going through an enterprise
    bean, an application accesses data more directly by going through a
    data access object. This way, the application avoids the overhead
    associated with using enterprise beans (remote method invocation,
    transaction management, data serialization, etc.).
    In the Java Pet Store application, when a user browses the catalog,
    items are loaded from the database through the CatalogDAO instead of
    the CatalogEJB component. The CatalogDAO is an example of a fast-lane
    reader, because it facilitates quicker read access.
    有些時候,高效地存取數據比獲得最新的數據更重要。在Java Pet Store 中,當一個用戶瀏覽商
    店的目錄時,屏幕與數據庫內容吻合不是至關緊要的,相反,迅速顯示和重新獲得非常重要。
    FLR 模式可以加速從資源中重新獲得大型的列數據項的速度,它不用EJB,而是更直接地通過
    DAO 來存取數據,從而消除EJB 的經常開支(例如遠程方法調用、事務管理和數據序列化等)。
    在Java Pet Store 這個例子中,當一個用戶瀏覽目錄時,通過CatalogDAO(而不是CatalogEJB)
    PetStore 中EJB 的設計模式
    21/21
    從數據庫加載數據項,而CatalogDAO 是一個Fast Lane Reader 的實例,使得讀訪問變得迅速
    與DAO 模式不同的是,FLR 是一個優化的模式,但不是要替代原有的訪問機制,而是作為補充
    使其完備。當你頻繁地只讀大型的列數據和不必存取最新的數據時,使用FLR 將是非常合適的。
    2.4.3. 結構
    客戶端直接調用FastLaneReader,而不是使用EJB 來獲得數據,當然EJB 接口仍然保留。
    2.4.4. PetStore 中的例子
    2.1.4.10 CatalogDAO
    定義數據的存取。使用了DAO 模式,
    public interface CatalogDAO {
    public Category getCategory(String categoryId, Locale locale) throws
    CatalogDAOSysException;
    public Product getProduct(String productId, Locale locale) throws
    CatalogDAOSysException;
    public Item getItem(String itemId, Locale locale) throws
    CatalogDAOSysException;
    }
    2.1.4.11 CatalogWebImpl
    客戶端直接,調用DAO,而不使用EJB,讀取產品信息
    public class CatalogWebImpl implements java.io.Serializable {
    protected CatalogDAO dao;
    PetStore 中EJB 的設計模式
    22/22
    public CatalogWebImpl() {
    try {
    //獲得DAO 對象
    dao = CatalogDAOFactory.getDAO();
    } catch (CatalogDAOSysException se) {
    throw new GeneralFailureException(se.getMessage());
    }
    }
    public Category getCategory(String categoryId, Locale locale) {
    try {
    //使用DAO,獲得數據,而不使用EJB
    return dao.getCategory(categoryId, locale);
    } catch (CatalogDAOSysException se) {
    throw new GeneralFailureException(se.getMessage());
    }
    }
    public Product getProduct(String productId, Locale locale) {
    try {
    //使用DAO,獲得數據,而不使用EJB
    return dao.getProduct(productId, locale);
    } catch (CatalogDAOSysException se) {
    throw new GeneralFailureException(se.getMessage());
    }
    }
    public Item getItem(String itemId, Locale locale) {
    try {
    //使用DAO,獲得數據,而不使用EJB
    return dao.getItem(itemId, locale);
    } catch (CatalogDAOSysException se) {
    throw new GeneralFailureException(se.getMessage());
    }
    }
    }
    2.1.4.12 ProductListTag
    定義一些TagLib 實現產品的列表,當然使用了CatalogWebImp,實際就是DAO,顯示出產品
    信息。
    public class ProductListTag extends ListTag {
    private String category = null;
    PetStore 中EJB 的設計模式
    23/23
    private boolean hasNext = false;
    protected void initParamPrefix() {
    paramPrefix = "productList_" + category + "_";
    }
    protected Collection findCollection() throws Exception {
    CatalogWebImpl catalog =
    (CatalogWebImpl)
    pageContext.getServletContext().getAttribute(WebKeys.CatalogModelKey);
    if (catalog == null) {
    return null;
    }
    Locale locale = JSPUtil.getLocale(pageContext.getSession());
    ListChunk prodList = null;
    Collection products = null;
    // 獲得產品列表
    prodList = catalog.getProducts(this.category, startIndex-1, numItems, locale);
    products = prodList.getCollection();
    if ((startIndex -1 + products.size()) < prodList.getTotalCount()) hasNext = true;
    else hasNext = false;
    return(products);
    }
    }
    2.5. Page-by-Page Iterator 模式
    在我們系統中一般有查詢,或者顯示信息列表。如在BBS 必須顯示貼之信息,但是我
    們并不是一次把版面的所有貼之全部取出。因為我們一般不會把整個版都看,這樣每次要讀
    到信息巨大,浪費了巨大的內存。
    2.5.1. 意圖
    Efficiently access a large, remote list by retrieving its elements one
    sublist of value objects at a time.
    為了提高遠程,大數據,而一次讀取值對象的部分對象。實際上就是不一次全部讀取,而是
    每次讀取其中的一部分。不過在實際開發中,如果數據量不大,并且都要顯示應該一次性讀
    取,不要使用這種模式,具體數據量多大才使用,需要結合實際情況。
    PetStore 中EJB 的設計模式
    24/24
    2.5.2. 動機
    Distributed database applications often require users to consider a
    long list of items, such as a catalog or a set of search results. In
    these situations, presenting the entire list at once is often
    unnecessary (the user isn't interested in all the items) or impossible
    (there isn't enough space for all the items).
    Furthermore, when retrieving a list of items, it would be very
    expensive to use entity beans. One cost comes from using remote finder
    methods to collect the requested beans; an additional, larger cost
    comes from making remote calls to each bean to get data for the user.
    These problems can be avoided by using a page-by-page iterator. Through
    such an iterator, a client object can traverse a large list, one sublist
    or page of value objects at a time; each page can be as big or as small
    as the client desires. Consequently, the application uses fewer
    resources to satisfy the client's immediate needs.
    In the Java Pet Store application, the JSP page product.jsp displays only
    a portion of an item list at any time, retrieving items from the
    page-by-page iterator ProductItemListTag. When the client wants to see
    the next or previous items in the list, product.jsp again calls on the
    iterator to retrieve these items.
    分布式數據庫的應用經常需要用戶考慮一長列數據項,例如一個目錄或一個搜索結果的集
    合。在這些情況下,立刻提供全列的數據經常不必要(用戶并不是對所有的數據項感興趣)
    或不可能(沒有足夠的空間)。此外,當重新獲得一列數據項時,使用Entity Bean 的代價
    將非常高昂,一個開銷來自于使用遠程探測器來收集Requested Bean,另外,更大的開銷
    來自對每個Bean 產生遠程調用以從用戶獲得數據。
    通過Iterator,客戶機對象能一下子重新獲得一個子列或者頁的values Object,每一頁都
    剛好滿足客戶機的需求,因此,程序使用較少的資源滿足了客戶機的立刻需求。
    在Java Pet Store 這個例子中,JSP 頁面product.jsp 任何時候只顯示一個數據列的一部
    分,從ProductItemListTag(Page-by-Page Iterator)重新獲得數據項,當客戶機希望看
    到列中的別的數據項,product.jsp 再次調用Iterator 重新獲得這些數據項,
    PetStore 中EJB 的設計模式
    25/25
    2.5.3. 結構
    實際上在Java 中使用Collection,就實現了GoF 中Iteraror 模式,一般從數據庫中讀取數據
    放入到Vector, , ArrayList 等中,然后就可義進行顯示。并且一般這種模式結合,
    ValueObject,Fast_Lane Reader 模式。
    2.5.4. PetStore 的例子
    2.1.4.13 CatalogDAOImp
    public class CatalogDAOImpl implements CatalogDAO {
    //一次讀取部分數據,開始值startIndex,總條數count
    public ListChunk getProducts(String categoryId, int startIndex,
    int count, Locale locale) throws CatalogDAOSysException {
    int localCount = 0 ;
    String qstr =
    "select productid, name, descn " +
    "from " +
    DatabaseNames.getTableName(DatabaseNames.PRODUCT_TABLE, locale) +
    " where category = " + "'" + categoryId + "' " + " order by name";
    Debug.println("Query String is:" + qstr);
    int num =
    getCount(DatabaseNames.getTableName(DatabaseNames.PRODUCT_TABLE,
    locale) + " where category = " + "'" + categoryId + "' ");
    ArrayList al = new ArrayList();
    Statement stmt = null;
    ResultSet rs = null;
    try {
    getDBConnection();
    stmt = dbConnection.createStatement();
    PetStore 中EJB 的設計模式
    26/26
    rs = stmt.executeQuery(qstr);
    HashMap table = new HashMap();
    // skip initial rows as specified by the startIndex parameter.
    while (startIndex-- > 0 && rs.next());
    // Now get data as requested.
    while (count-- > 0 && rs.next()) {
    int i = 1;
    String productid = rs.getString(i++).trim();
    String name = rs.getString(i++).trim();
    String descn = rs.getString(i++).trim();
    Product product = null;
    if (table.get(productid) == null) {
    product = new Product(productid, name, descn);
    table.put(productid, product);
    al.add(product);
    localCount++;
    }
    }
    } catch(SQLException se) {
    throw new CatalogDAOSysException("SQLException while getting " +
    "multiple products for cat " + categoryId + " : " +
    se.getMessage());
    } finally {
    closeResultSet(rs);
    closeStatement(stmt);
    closeConnection();
    }
    ListChunk rl = new ListChunk(num, al, startIndex, localCount);
    return rl;
    }
    2.1.4.14 ProductItemListTag
    public class ProductItemListTag extends ListTag {
    protected Collection findCollection() {
    CatalogWebImpl catalog =
    (CatalogWebImpl)
    pageContext.getServletContext().getAttribute(WebKeys.CatalogModelKey);
    if (catalog == null) {
    return null;
    }
    PetStore 中EJB 的設計模式
    27/27
    Locale locale = JSPUtil.getLocale(pageContext.getSession());
    ListChunk itemList = null;
    Collection items = null;
    //進行讀取部分數據
    itemList = catalog.getItems(productId, startIndex-1, numItems, locale);
    items = itemList.getCollection();
    if ((startIndex -1 + items.size()) < itemList.getTotalCount()) hasNext = true;
    else hasNext = false;
    return(items);
    }
    }
    2.5.5. GOF 的Iterator 模式
    意圖
    提供一種方法順序訪問一個聚合對象中各個元素, 而又不需暴露該對象的內部表示。
    結構
    動機
    ? 訪問一個聚合對象的內容而無需暴露它的內部表示。
    ? 支持對聚合對象的多種遍歷。
    ? 為遍歷不同的聚合結構提供一個統一的接口(即, 支持多態迭代)。
    2.6. ServiceLocator 模式
    這種模式在《J2EE 核心模式》有詳細描述,雖然在SUN 上沒有介紹,但在petstore1.3 版
    本中使用了它。
    PetStore 中EJB 的設計模式
    28/28
    2.6.1. 意圖
    我們使用這種模式來抽取所有的JNDI 使用,并且隱藏了Context 的初始化,Ejb 對象的
    LookUp,以及narrow。系統的所有客戶端使用統一代碼,來降低代碼的的復雜性,提供一
    致控制,并且使用緩存提高性能。
    2.6.2. 動機
    ?? 抽取復雜性
    通過封裝了查找,創建過程的復雜性,對系統的所有cilent,統一處理。
    ?? 向客戶端提供統一的服務訪問
    ?? 有利用添加新的業務組件
    ?? 提高網絡性能
    ?? 通過緩存提高性能
    2.6.3. 結構
    PetStore 中EJB 的設計模式
    29/29
    2.6.4. PetStore 中的例子
    2.1.4.15 ServiceLocatorImpl
    public class ServiceLocatorImpl implements ServiceLocator, java.io.Serializable {
    protected HttpSession session;
    protected WebClientController wcc;
    public ServiceLocatorImpl() { }
    //定位ejb
    public WebClientController getWebClientController() {
    WebClientController wcc =
    (WebClientController)session.getAttribute(WebKeys.WEB_CLIENT_CONTROLLER);
    if ( wcc == null ) {
    try {
    InitialContext ic = new InitialContext();
    String wccClassName = (String)
    ic.lookup(JNDINames.WEB_CLIENT_CONTROLLER_IMPL);
    wcc = (WebClientController)
    Beans.instantiate(this.getClass().getClassLoader(), wccClassName);
    wcc.init(session);
    } catch (Exception exc) {
    exc.printStackTrace();
    throw new RuntimeException ("Cannot create bean of class
    WebClientController");
    }
    session.setAttribute(WebKeys.WEB_CLIENT_CONTROLLER, wcc);
    }
    return wcc;
    }
    /**
    *
    * Create the WebClientController which in turn should create the
    * EJBClientController.
    *
    */
    public void sessionCreated(HttpSessionEvent se) {
    this.session = se.getSession();
    wcc = getWebClientController();
    this.session.setAttribute(WebKeys.SERVICE_LOCATOR, this);
    PetStore 中EJB 的設計模式
    30/30
    }
    /**
    *
    * Destroy the WebClientController which in turn should destroy the
    * EJBClientController.
    *
    */
    public void sessionDestroyed(HttpSessionEvent se) {
    if (wcc != null) wcc.destroy();
    wcc = null;
    }
    }
    2.1.4.16 我們項目的例子
    當初我們項目使用JB 開發,EJB 服務器有的使用了BAS4.5 和WebLogic6。1,這樣EJB
    定位,方法不一致,我們使用這種模式,這使用了GoF 中的Singleton 模式,這樣緩存context
    提高了效率。不需要每次都要getInitialContext。這個代碼對大家應該有用。
    public class ServiceLocator {
    private static ServiceLocator me;
    Context context = null;
    //系統服務器信息,如果改動只需,設置CURRENTSERVER
    private static String WEBLOGICSERVER="weblogic6.1";
    private static String BASSERVER="bas4.5";
    private static String CURRENTSERVER="weblogic6.1";
    //聯接EJB 服務器參數
    private final static String EJBSERVERURL="t3://localhost:7001";
    // AIX 服務器
    //private final static String EJBSERVERURL="t3://192.168.4.25:7001";
    //private final static String EJBUSERNAME="system";
    //private final static String EJBPASSWORD="password";
    //weblogic 的guest 用戶如果不刪除,可以使用null
    private final static String EJBUSERNAME=null;
    private final static String EJBPASSWORD=null;
    PetStore 中EJB 的設計模式
    31/31
    /**
    *初始化Context
    * @return
    * @throws Exception
    */
    private Context getInitialContext() throws Exception {
    String url = EJBSERVERURL;
    String user =EJBUSERNAME;
    String password =EJBPASSWORD;
    Properties properties = null;
    try {
    //當前服務器為Weblogic6.1 時
    if(CURRENTSERVER.equals(WEBLOGICSERVER)){
    properties = new Properties();
    properties.put(Context.INITIAL_CONTEXT_FACTORY,
    "weblogic.jndi.WLInitialContextFactory");
    properties.put(Context.PROVIDER_URL, url);
    if (user != null) {
    properties.put(Context.SECURITY_PRINCIPAL, user);
    properties.put(Context.SECURITY_CREDENTIALS, password == null ?
    "" : password);
    }
    return new InitialContext(properties);
    //當前服務器為BAS 時
    }else{
    return new InitialContext();
    }
    }
    catch(Exception e) {
    e.printStackTrace();
    System.out.println("Please make sure that the server is running.");
    throw e;
    }
    }
    private ServiceLocator() {
    try {
    context = getInitialContext();
    } catch(Exception e) {
    e.printStackTrace();
    }
    }
    PetStore 中EJB 的設計模式
    32/32
    /**
    *初始化ServiceLocator
    * @return
    */
    public static ServiceLocator getInstance() {
    if (me == null) {
    me = new ServiceLocator();
    }
    return me;
    }
    /**
    *根據JNDI 名字,取得EJB Home
    * @param name JDNI 名字
    * @param clazz Home class 名字
    * @return
    */
    public EJBHome getHome(String name, Class clazz) {
    try {
    Object objref = context.lookup(name);
    EJBHome home = (EJBHome)PortableRemoteObject.narrow(objref, clazz);
    return home;
    } catch(Exception e){
    e.printStackTrace();
    return null;
    }
    }
    }
    2.6.5. GOF 模式
    2.1.4.17 Singleton 模式
    實際在我們使用了這種模式,ServiceLocator 實例就使用這種模式,它只有一個實例,從而
    保證只初始Context 一次,提高了效率
    ?? 意圖
    保證一個類僅有一個實例,并提供一個訪問它的全局訪問點。
    ?? 適用性
    當類只能有一個實例而且客戶可以從一個眾所周知的訪問點訪問它時。
    當這個唯一實例應該是通過子類化可擴展的,并且客戶應該無需更改代碼就能使用一個
    擴展的實例時。
    PetStore 中EJB 的設計模式
    33/33
    ?? 結構
    2.7. Local 模式
    2.7.1. 意圖
    由于EJB 的效率低,如果部分EJB 僅是在內部使用(同一個java VM,),而不是遠程調用,
    就應該使用本地方法。如果你看過PetStore 的EJB 層,就會發現大部分都使用Local 方法。
    只有在提供Facde 的SessionBean 才使用遠程接口。這是在EJB2.0 才支持的,實際在我們
    的項目中開始是第一次使用EJB2.0,并沒有使用本地方法,后來使用本地方法,具體效率
    提高多少,我也不知道。其實在資料中一般不把它作為模式來講,但是我認為這是一種模式。
    大家在自己的項目中最好使用它。據說在weblogic 7.0 的web 層與ejb 容器共享一個JVM,
    所以可以使用本地方法,在兩層之間調用。
    2.7.2. 動機
    Local interfaces allow enterprise javabeans to work together within the same EJB container
    using different semantics and execution contexts. The EJBs are usually co-located within the same
    EJB container and ex ecute within the same Java Virtual Machine (JVM). This way, they do not
    use the network to communicate and avoid the over-head of a Java Remote Method
    Invocation-Internet Inter-ORB Protocol (RMI-IIOP) connection.
    2.7.3. 結構
    結構一般是,在遠程SessionBean 中調用本地接口EntityBean,結合Session Fa?ade 模式。
    PetStore 中EJB 的設計模式
    34/34
    ShoppingClientFacadeLocal
    (f rom ejb)
    AccountLocal
    getStatus()
    setStatus()
    getCreditCard()
    setCreditCard()
    getContactInfo()
    setContactInfo()
    (f rom ejb)
    CustomerLocal
    getUserId()
    getAccount()
    getProfile()
    (f rom ejb)
    ?? ShoppingClientFacadeLocalEJB,它是遠程方法,供遠程調用。
    public class ShoppingClientFacadeLocalEJB implements SessionBean {
    private ShoppingCartLocal cart = null;
    private CustomerLocal customer = null;
    /*
    * Asume that the customer userId has been set
    */
    //供遠程調用,內部使用本地方法
    public CustomerLocal getCustomer() throws FinderException {
    try {
    //使用本地調用,方法與遠程不同
    InitialContext ic = new InitialContext();
    Object o = ic.lookup("java:comp/env/ejb/local/Customer");
    //獲得本地接口
    CustomerLocalHome home =(CustomerLocalHome)o;
    customer = home.findByPrimaryKey(userId);
    } catch (javax.naming.NamingException nx) {
    PetStore 中EJB 的設計模式
    35/35
    throw new GeneralFailureException("ShoppingClientFacade: failed to look up
    name of customer: caught " + nx);
    }
    return customer;
    }
    }
    2.7.4. PetStore 例子
    在PetStore 中的EntityBean 都是使用的本地方法,在Session Facde 中調用本地接口。
    見上面的例子。
    2.8. CMR 模式
    其實這也不算一種模式,它是在EJB2。0 中新增的重要特征。在IBM 的DevelpoerWorks
    中有一篇教程介紹的非常詳細。在PetStore 的實體Bean 中,大量的使用了它。所以我把它
    作為一種模式,重點介紹它。在JB6.0 中建立這種關系非常容易,如果自己手寫的話,需要
    在web.xml 中增加關系。
    2.8.1. 意圖
    您不必編寫低級 JDBC 調用,并且不必編寫代碼來管理關系。它都內建在 EJB 框架中。關系
    的接口直接通過大多數 EJB 開發者已經很熟悉的流行的 java.util.Collection 和
    java.util.Set 構建。非常酷!
    2.8.2. 動機
    使系統簡潔,方便開發。具體的好處需你仔細體會。
    2.8.3. 結構
    實際就是建立我們的在數據庫中的關系。它包括1 對1,1 對多,多對多。我感覺最好大家
    好好學習IBM 站點上的那篇文章。下圖是使用JB6.0 建立的關系。
    PetStore 中EJB 的設計模式
    36/36
    2.8.4. PetStore 中的例子
    在petStore 例子
    public abstract class CustomerEJB implements javax.ejb.EntityBean {
    private EntityContext context = null;
    // getters and setters for CMP fields
    // CMR Fields
    public abstract AccountLocal getAccount();
    public abstract void setAccount(AccountLocal account);
    public abstract ProfileLocal getProfile();
    public abstract void setProfile(ProfileLocal profile);
    }
    ejb.jar
    <relationships>
    <ejb-relation>
    <ejb-relation-name>Customer-Account</ejb-relation-name>
    <ejb-relationship-role>
    PetStore 中EJB 的設計模式
    37/37
    <ejb-relationship-role-name>CustomerEJB</ejb-relationship-role-name>
    <multiplicity>One</multiplicity>
    <relationship-role-source>
    <ejb-name>CustomerEJB</ejb-name>
    </relationship-role-source>
    <cmr-field>
    <cmr-field-name>account</cmr-field-name>
    </cmr-field>
    </ejb-relationship-role>
    <ejb-relationship-role>
    <ejb-relationship-role-name>AccountEJB</ejb-relationship-role-name>
    <multiplicity>One</multiplicity>
    <cascade-delete />
    <relationship-role-source>
    <ejb-name>AccountEJB</ejb-name>
    </relationship-role-source>
    </ejb-relationship-role>
    </ejb-relation>
    <ejb-relation>
    <ejb-relation-name>Customer-Profile</ejb-relation-name>
    <ejb-relationship-role>
    <ejb-relationship-role-name>CustomerEJB</ejb-relationship-role-name>
    <multiplicity>One</multiplicity>
    <relationship-role-source>
    <ejb-name>CustomerEJB</ejb-name>
    </relationship-role-source>
    <cmr-field>
    <cmr-field-name>profile</cmr-field-name>
    </cmr-field>
    </ejb-relationship-role>
    <ejb-relationship-role>
    <ejb-relationship-role-name>ProfileEJB</ejb-relationship-role-name>
    <multiplicity>One</multiplicity>
    <cascade-delete />
    <relationship-role-source>
    <ejb-name>ProfileEJB</ejb-name>
    </relationship-role-source>
    </ejb-relationship-role>
    </ejb-relation>
    2.9. 業務代表模式
    其實這種模式,就是GOF 的proxy 模式在ejb 中的應用。在<<J2EE 核心模式>>一書有詳細
    PetStore 中EJB 的設計模式
    38/38
    介紹。在petStore 的1.2.1 版本的例子很明顯
    2.9.1. 意圖
    使用業務代表來降低web 層和ejb 層之間的耦合,它隱藏了業務邏輯調用的細節,如ejb
    的查找和訪問的細節。其實客戶端,首先調用業務代表,然后由他負責真正在調用ejb 層的
    服務,就是proxy.。這種模式在GOF 中有詳細的介紹,在JIVE 項目使用的也比較多。
    改模式一般結合Session Fa?ade 和ServiceLocator 模式使用,通常它和Session Fa?ade 模式
    存在一對一的關系,是因為如果在業務代表存在調用多個ejb,那么就會把這些關系轉移到
    session fa?ade 中。
    2.9.2. 動機
    1. 降低web 層和ejb 層之間耦合
    通過隱藏ejb 層的調用,如服務的查找等,由于只需要在業務代表一個地方進
    行變化的管理和維護,所以實現起來更加容易。
    2. 可以轉化ejb 層的異常
    業務代表可以把ejb 層的異常,轉化會web 層的異常,如在petStore1.2.1 中的
    例子把EstoreAppException 異常轉化為GeneralFailureException
    public class ShoppingClientControllerWebImpl implements java.io.Serializable {
    public synchronized ShoppingCart getShoppingCartEJB() {
    try {
    //com.sun.j2ee.blueprints.petstore.control.ejb.ShoppingClientController
    sccEjb;
    return sccEjb.getShoppingCart();
    } catch (EStoreAppException ce) {
    throw new GeneralFailureException(ce.getMessage());
    } catch (RemoteException re) {
    throw new GeneralFailureException(re.getMessage());
    }
    }
    }
    3. 實現失效恢復和線程同步
    如果遇到ejb 層服務的失效,業務代表可以自動恢復,而無需在調用處直接進
    行恢復,特別是在多處調用,每個處都需進行處理,而這樣可以集中在業務代
    表處進行處理。
    4. 向業務層提供更簡單的,統一的接口
    5. 提高系統性能
    業務代表可以向web 層提供請求的緩沖機制,提高性能。例如可以緩存遠程接
    口,而不需每次都進行查找遠程接口。
    PetStore 中EJB 的設計模式
    39/39
    6. 引入代理層
    業務代表被看作是在web 層和wjb 層之間的代理層,從而引入了復雜性,降低
    了靈活性。有些開發者,這樣增加了工作,同時它也帶來了某些好處。具體是
    否使用改模式,請開發人員進行衡量。(我們的項目就沒有使用)
    7. 隱藏遠程性
    2.9.3. 結構
    2.9.4. PetStore 中的例子
    在petStore1.2.1 中ShoppingClientControllerWebImpl 其實就是一個業務代表的例子。
    public class ShoppingClientControllerWebImpl implements java.io.Serializable {
    private com.sun.j2ee.blueprints.petstore.control.ejb.ShoppingClientController sccEjb;
    private HttpSession session;
    public ShoppingClientControllerWebImpl() {
    }
    /**
    * constructor for an HTTP client.
    * @param the HTTP session object for a client
    */
    public ShoppingClientControllerWebImpl(HttpSession session) {
    this.session = session;
    ModelManager mm =
    (ModelManager)session.getAttribute(WebKeys.ModelManagerKey);
    PetStore 中EJB 的設計模式
    40/40
    sccEjb = mm.getSCCEJB();
    }
    public synchronized ShoppingCart getShoppingCartEJB() {
    try {
    return sccEjb.getShoppingCart();
    } catch (EStoreAppException ce) {
    throw new GeneralFailureException(ce.getMessage());
    } catch (RemoteException re) {
    throw new GeneralFailureException(re.getMessage());
    }
    }
    public synchronized Customer getCustomerEJB() {
    try {
    return sccEjb.getCustomer();
    } catch (EStoreAppException fe) {
    throw new GeneralFailureException(fe.getMessage());
    } catch (RemoteException re) {
    throw new GeneralFailureException(re.getMessage());
    }
    }
    public synchronized ProfileMgr getProfileMgrEJB() {
    try {
    return sccEjb.getProfileMgr();
    } catch (EStoreAppException fe) {
    throw new GeneralFailureException(fe.getMessage());
    } catch (RemoteException re) {
    throw new GeneralFailureException(re.getMessage());
    }
    }
    public synchronized Collection handleEvent(EStoreEvent ese)
    throws EStoreEventException {
    try {
    return sccEjb.handleEvent(ese);
    } catch (RemoteException re) {
    throw new GeneralFailureException(re.getMessage());
    }
    }
    /**
    * frees up all the resources associated with this controller and
    PetStore 中EJB 的設計模式
    41/41
    * destroys itself.
    */
    public synchronized void remove() {
    // call ejb remove on self/shopping cart/etc.
    try {
    sccEjb.remove();
    } catch(RemoveException re){
    // ignore, after all its only a remove() call!
    Debug.print(re);
    } catch(RemoteException re){
    // ignore, after all its only a remove() call!
    Debug.print(re);
    }
    }
    }
    2.9.5. GOF 模式
    2.1.4.18 Proxy 模式
    ?? 意圖
    為其他對象提供一種代理以控制對這個對象的訪問。
    ?? 適用性
    ? 在需要用比較通用和復雜的對象指針代替簡單的指針的時候,使用P r o x y 模
    式。下面是一 些可以使用P r o x y 模式常見情況:
    1) 遠程代理(Remote Proxy )為一個對象在不同的地址空間提供局部代表。
    NEXTSTEP[Add94] 使用N X P r o x y 類實現了這一目的。Coplien[Cop92] 稱這種
    代理為“大使” (A m b a s s a d o r )。
    2 )虛代理(Virtual Proxy )根據需要創建開銷很大的對象。在動機一節描述的I m a
    g e P r o x y 就是這樣一種代理的例子。
    3) 保護代理(Protection Proxy )控制對原始對象的訪問。保護代理用于對象應該有
    不同 的訪問權限的時候。例如,在C h o i c e s 操作系統[ C I R M 9 3 ]中K e m e l P
    r o x i e s 為操作系統對象提供 了訪問保護。
    4 )智能指引(Smart Reference )取代了簡單的指針,它在訪問對象時執行一些附加
    操作。 它的典型用途包括:
    ? 對指向實際對象的引用計數,這樣當該對象沒有引用時,可以自動釋放它(也稱為S
    m a r tP o i n t e r s[ E d e 9 2 ] )。
    ? 當第一次引用一個持久對象時,將它裝入內存。
    ? 在訪問一個實際對象前,檢查是否已經鎖定了它,以確保其他對象不能改變它。
    結構
    PetStore 中EJB 的設計模式
    42/42
    3. EJB 模式關系
    正如Christopher Alexander 的評論,模式不是孤立存在的,需要其他模式的結合側更具
    有偉力。現在我們討論以上所羅列各種模式之間的關系。
    業務代表
    Session Facade
    ServiceLocator
    值對象組裝器
    Page-by-Page
    Iterator
    復合實體模式Value Object模式
    CRM模式Local模式DAO模式
    Fast-
    Lane
    Reader
    模式
    首先是在web 層與ejb 層的結合層(Proxy)由業務代表實現,它一般與SessionFacade
    是一對一的關系,當然它一般會使用ServiceLocator 模式,來查找和定位ejb。客戶端一般
    使用業務代表來調用業務邏輯,而不是直接進行調用。為了簡化接口,我們使用SessionFacade
    模式,來封裝復雜的業務邏輯,通過SessionFacade 模式來調用其他的ejb,一般其他被調用
    者,一般使用CRM 和Local 模式,這樣可以提高效率。為了提高接口的粗粒度,我們一般
    使用Value Object 模式,復合實體,以及值對象組裝器模式。有時接口的需要值對象的列表,
    我們又使用Page-By-Page 模式,來緩存大量的之對象。還有一種景況,就是為了提高效率,
    不使用ejb,而是直接連接數據庫,就是Fast-Lane-Reader。
    ? 業務代表模式
    ? ServiceLocator 模式
    ? SessionFacade 模式
    PetStore 中EJB 的設計模式
    43/43
    ? Value Object 模式
    ? Page-By-Page 模式
    ? 復合實體
    ? CRM 模式
    ?
    4. 相關的資料
    1. sun 站點
    2. IBM DevelpoerWorks
    3. 《J2EE 模式》
    4. 《設計模式-可復用面向對象的軟件的基礎》
    5. http://www.javaunion.org/http://www.chinajavaworld.com/ 站點的一些網友作品。
    5. 總結

    posted on 2007-03-09 02:17 金家寶 閱讀(444) 評論(0)  編輯  收藏 所屬分類: J2EE概念理論性文摘

    主站蜘蛛池模板: 亚洲图片在线观看| 免费看黄网站在线看 | 亚洲高清乱码午夜电影网| 免费一级毛片一级毛片aa| 日韩电影免费在线观看网站| 亚洲午夜电影在线观看| 一本色道久久88亚洲综合| 无码av免费一区二区三区试看| 亚洲精品乱码久久久久久蜜桃图片| 亚洲精品无码成人片在线观看| 最近中文字幕大全中文字幕免费| jizzjizz亚洲日本少妇| 亚洲av永久无码精品国产精品| 性一交一乱一视频免费看| a级毛片100部免费观看| 亚洲AV永久无码天堂影院| 亚洲AV综合色一区二区三区| 国产男女猛烈无遮档免费视频网站| 最好免费观看高清在线| 国产精品亚洲小说专区| 亚洲欧洲高清有无| 久久久久亚洲AV成人网人人软件 | 成人免费网站在线观看| 久久精品成人免费看| 国产AV无码专区亚洲AV麻豆丫| 亚洲视频欧洲视频| 国产亚洲av人片在线观看| 免费观看男人免费桶女人视频| 59pao成国产成视频永久免费| 无码毛片一区二区三区视频免费播放| 亚洲人成综合网站7777香蕉| 亚洲国产高清人在线| 国产亚洲精品无码拍拍拍色欲| 青青草国产免费久久久下载| 亚洲精品国产免费| 国产啪精品视频网站免费尤物| 麻豆安全免费网址入口| 亚洲大成色www永久网址| 久久久久亚洲av无码专区| 亚洲精品无码乱码成人| 亚洲一级黄色视频|