亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

EJB 倡導者: 使用何種 EJB 組件組裝來自服務的

系統 1672 0
EJB 倡導者對面向服務的體系結構從上至下進行了分析,以最終確定應該使用會話 EJB 組件還是實體 EJB 組件組裝服務返回的數據傳輸對象。
<!--START RESERVED FOR FUTURE USE INCLUDE FILES--><!-- include java script once we verify teams wants to use this and it will work on dbcs and cyrillic characters --> <!--END RESERVED FOR FUTURE USE INCLUDE FILES-->

在每個專欄中,EJB 倡導者提出要點,客戶和開發者采用獨特的前后銜接的對話框方式,在對某一感興趣的設計問題提議解決方案的過程中進行交流。其中忽略了任何確定性的細節,并且不提供“革新的”或專有的體系結構。有關詳細信息,請參閱 EJB 倡導者簡介

實體 EJB 組件在服務中的角色

前一篇專欄文章 中, 我們介紹了面向服務的體系結構的一些特征;例如,為了盡可能減少服務和其客戶機間頻繁的對話,服務必須為粗粒度的無狀態服務,而且必須正常組裝數據傳輸對 象 (DTO),此類對象會收集所有從客戶機應用程序返回的屬性。我們了解了設計良好的 EJB 方法如何展示這些特征(通過與會話 EJB 實例或實體 EJB Home 接口關聯)。不過,在本月,有位讀者詢問我們是否認為實體 EJB 組件也設計為無狀態服務。


問題:哪個數據傳輸對象由哪個實體返回?

親愛的 EJB 倡導者:

我已經讀過您最近的文章,對于數據傳輸對象 (DTO),我想提出一些自己的看法。我同意您所說的,數據傳輸對象在服務層(該層中需要各種粗粒度方法)非常重要,特別對于表示隱藏實現的服務的外觀,尤其是遠程外觀(因為遠程調用的開銷要比本地調用大得多)更是如此。

此 外,推薦的代碼看起來非常合理,并得到了良好封裝,能夠讓您要求實體 EJB 組件“給我一個您自己的 DTO”。不過有一個問題,對于兩種不同的用例,一種可能需要給定實體 EJB 組件的某些屬性,而另一種則可能需要不同的屬性,因此會需要兩個 DTO 類。那么,getDTO() 方法應該返回哪個 DTO 類型呢?

還有另一個問題。不同的用例可能需要由 相同類型或不同類型(客戶、延期交貨訂單、訂單中的產品)的多個實例組成的 DTO。這種情況下,需要在哪個實體 EJB 中實現該復合功能?

在 會話外觀中,似乎不能避免對實體 EJB 組件使用單個 getter(和 setter)。將組裝 DTO 的邏輯放入到會話 Bean 中(或者,按照我喜歡的方式,放入會話使用的 Helper 類中)的好處之一就是,當由于某種原因(如添加另一個服務所需的新屬性)需要刪除或重新生成實體時,不用擔心自定義代碼發生不同步的現象。

我想,我真正想問的是:您在建議使用實體 EJB 組件的本地接口時,從實體 CMP 返回 DTO 是否是在“喊狼來了”?我理解您關于盡力減少各層之間的頻繁對話的觀點,但似乎您在以犧牲可維護性為代價來換取性能的提高。

請用這個名字稱呼我們,
Never Cry Wolf


從良好封裝技術獲得一項好處

親愛的 Never:

您提出了很好的觀點,非常值得加以說明。讓我們從上到下依次回答您提出的問題:

  1. 假設兩種用例需要不同的數據,getDTO() 方法應該返回哪個 DTO 類型?

    我的回答是:getDTO() 當然應該返回 DTO 的實例。認真一點講,您為 DTO 選擇的名稱應該清楚地指示它所返回的數據。如果兩種用例需要不同的數據集,DTO 類名稱應該指示這一點:可以為 UseCase1DTO 或 UseCase2DTO 之類的。因此接口中的兩個方法簽名將為:


    代碼段 1. DTO 方法的多個簽名
                    
    public UseCase1DTO getUseCase1DTO();
    public UseCase2DTO getUseCase2DTO();

    或者,更抽象一些:


    代碼段 2. 顯示抽象示例的更不易混淆的方式
                    
    public <DTO> get<DTO>();

    約 定的最后一個要點是:如果要讓 getDTO() 方法與實體關聯,一種方法就是為返回 <Entity>DTO 的實例的方法將保留此方法名稱,該 DTO 包含關聯的實體的所有非標量屬性(這些屬性的最大基數為 1)。您的團隊可能選擇使用另一個約定,只要確保一致性即可。

  2. 假設需要來自多個實體(如客戶、延期交貨訂單、訂單中的產品)的數據,哪個實體應“擁有” get<ComposedDTO>() 方法?

    要從定義實體 EJB 上的復合 DTO 方法的角度回答這個問題,就要涉及到面向對象的設計的最佳實踐。我們在專欄文章 使實體 EJB 組件滿足需求,第 2 部分 中簡單討論了 OO 委托。對實體的選擇取決于實體與要返回的數據之間的關系。通常,需要選擇可以根據需要委托到其他實體以組成完整結構的實體。在您所給出的具體例子中,您希 望 DTO 返回來自客戶、延期交貨訂單、訂單中的產品(由一個 Line Item 表示,其中包含數量和總數的鏈接屬性)的數據。讓我們暫時假設圖 1 中的類關系圖描述了業務對象及其相互關系。


    圖 1. 顯示實體及關系的示例類關系圖
    圖 1. 顯示實體及關系的示例類關系圖

    對 于您的示例,“擁有”復合 DTO 方法的實體理所當然應該是 Customer,因為它能夠委托到 Order,而后者能夠委托到 Line Item,Line Item 又能委托到 Product。對于 Customer 實體上的方法名稱,可以選擇與 getCustomerOpenOrderDetails() 類似的名稱:。

    關系圖上顯示的關系啟用了多個路徑,我們可以通過這些路徑檢索組成所有四個實體類型的信息的 DTO。例如:

    • 給定一個客戶,檢索延期交貨訂單的詳細信息(上面所描述的)。
    • 給定一個客戶,檢索所有相關訂單的詳細信息。
    • 給定一個訂單,檢索其客戶和詳細信息。
    • 給定一個行式項目,檢索其相關的產品,包含此行式項目的訂單和客戶。
    • 給定一個產品,檢索所有相關的訂單行式項目和客戶。

    擁有方法的實體在上面的“given a(n) <Entity>”子句中指示,它表示起始點,因此假設如下:任何與此方法關聯的服務外觀(或 EJB home 方法)都將采用能標識用于開始委托的一個或多個實體類型的參數。希望這能夠回答您的第二個問題。

  3. 當建議從實體 EJB 返回 DTO 的同時建議使用本地接口,是否是在“喊狼來了”(以犧牲可維護性為代價換取性能的提高)?

    在 EJB 1.x 的早期,我們也進行過與此類似的有趣的得失分析。我們發現對于從實體返回數據,存在兩種極端方法和一種中立方法,從而得到三種基本的訪問方式:

    1. 一次一個屬性
      從 表面上看,可維護性最好的方法就是完全避免 DTO,而采用一次從客戶機獲取一個屬性的方法。但這卻是以減少消息數目和大小為代價獲得可維護性。一般用例將以許多小消息結束,當涉及到遠程接口時,端 到端通信開銷會對響應時間和吞吐量造成很大的影響。另一個不足(正如您所提到的)就是,還破壞了封裝。破壞了封裝會對可維護性造成負面影響。例如,如果決 定將一組屬性構造到相關實體中,將需要更改使用這些屬性的每個客戶機!
    2. 一個大小適合所有 DTO
      另 一種極端的方法就是返回與在 DTO 中返回的目標實體關聯的所有非標量數據,正如我們在回答第一個問題時所討論的。在這種情況下,您最小化了遠程消息的數目,同時仍然具有相對的可維護性。只 對每個實體調用一次,并一次獲取所有能獲得的全部數據。這樣您只得為每個實體開發一個 DTO 和一個檢索方法。當然,折衷方案是 DTO 中包含的數據幾乎始終多于給定工作單元所需的數據,在通常具有很多屬性的實際實體中更是如此。因此,此方法對為每個工作單元從后端數據系統檢索和傳輸的數 據量有很大的影響。這種方法的好處在于,當每次添加或刪除屬性時,只需要修改 DTO 即可。而只有客戶機使用已刪除的屬性時才需要對其進行修改。
    3. 自定義 DTO
      中 立方法(EJB 倡導者想起了《金發姑娘與三只熊》的故事)就是對 DTO 結構進行定制,使其準確返回您所需要的數據。一次調用。大小合適。真不錯。但問題在于,您必須對用例進行仔細的分析,以獲得恰當的一組 DTO 和方法。當實現用例的新類時,必須創建一個新的 DTO,并調整 EJB 以對其進行檢索。

    當使用 EJB 1.x 實體時,選項 c 被認為是最好的,因為分布式對象應用程序設計主要就是為了盡可能減少調用(可能為遠程調用)的數量。選項 b 是一個不錯的折衷辦法,能獲得一定的可維護性。這樣一來,就變得更簡單了,再沒有煩人的 CMR,也不用考慮“依賴對象”(屬性的集群,實際表示“包含”在實體中的對象)以外的東西。

    但現在已經推出了具有本地接口 的 EJB 2.x 和 CMR,我曾想過選項 a 是不是最佳的方法(我們剛在專欄文章 Making entity EJB components perform, Part 1 (LINK) 中提到過這個問題)——但我們始終認為,出于同樣的性能原因(盡管它們可能不那么重要),使用選項 c 中描述的自定義 DTO 仍然是最好的。我們還指出,由于很多人都已經習慣了 EJB 1.x“最佳實踐”,比起對他們進行重新培訓而言,這更簡單(而且這也使轉換變得更容易)。

希望這會對您有所幫助,
您的 EJB 倡導者


舊話重提,可維護性問題

親愛的 EJB 倡導者:

我理解并同意您對前兩個問題的回答。這讓我受益非淺。關于您對我的第三個問題的分析,我的理解是,為什么您認為對于 EJB 1.x,從性能的角度而言,選項 c 最佳,但您并沒有真正回答如果使用 EJB 2.x 如何解決可怕的可維護性問題。

回顧一下您的回信中的簡單關系圖。有五種不同的“頂級”方法對來自所有四個實體的信息加以組合。您沒有提到與每個實體關聯的,處理委托的方法。讓我們看一看與從客戶獲取延遲交貨訂單關聯的方法:

  1. 給定一個訂單,返回該訂單和帶產品的行式項目。這將委托給:
  2. 給定一個行式項目,返回該行式項目和產品,這將委托給:
  3. 給定一個產品,返回其 DTO。

那么,存在不包括所有四個實體的組合。僅從客戶來看,就可以提出三種以上的方法:

  1. 只從客戶返回數據。
  2. 僅返回客戶和延期交貨訂單(不含詳細信息)。
  3. 返回客戶和所有相關的訂單(但也不含詳細信息)。

現在,將所有這些添加到從每個實體獲取部分屬性的排列中。總之,這種組合非常多,尤其在考慮到(如您自己所說)通常存在更多與每個實體關聯的屬性時,更是如此。

因此,我不甚明白的第三個問題是,您似乎以大量的可維護性為代價,獲得現在的少量性能改進。

先行謝過,但我仍然必須簽上這個名字:
Never Cry Wolf


數據傳輸對象與視圖關聯

親愛的 Never Cry Wolf:

開 個玩笑,現在是您在喊“狼來了”。您不大可能在自定義開發的應用程序中看到很多此類置換。為了理解我這樣講的原因,讓我們從頂層——用例著手。盡管本文不 是關于進行面向對象分析和設計的方法的完整教程,但我們仍將簡單了解一些主要構件,以說明排列的數量相對來說是有限的。

圖 1 的類關系圖中顯示的實體與訂單管理業務流程相關聯。該流程可以使用狀態轉換圖 (STD) 進行描述,如圖 2 中所示,其顯示了受管理的單個訂單的生命周期的各個階段。


圖 2. 顯示訂單的生命周期的示例狀態轉換圖
圖 2. 顯示訂單的生命周期的示例狀態轉換圖

順便說一下,僅供參考,圖 2 使用 UML Actor 表示法進行了擴展,以顯示在給定狀態中實例的所有者。我們使用這個簡單的擴展已經多年了,將此作為組織用例并將其綁定到業務流程的方法(事實上,我們喜歡開玩笑地稱用例關系圖就是一個尚未“孵出”的狀態轉換圖)。

我 們采用的另一個略微不同尋常的方法就是為生命周期模型中的每個狀態開發一個類關系圖,以顯示對保持在該狀態中的屬性和關系的約束。這些不斷更改的約束在不 考慮狀態的“單態”類關系圖中容易丟失。例如,圖 1 中的類關系圖顯示的是保持在圖 2 所示的生命周期的開放狀態中的關系和屬性。處于已提交狀態的訂單的類關系圖可能與圖 3 類似。


圖 3. 顯示處于已提交狀態的訂單的示例類關系圖
圖 3. 顯示處于已提交狀態的訂單的示例類關系圖

該 方法按照各個狀態提供獨立的類關系圖,說明了為什么圖 3 和圖 1 中的類名使用了 [] 來指示狀態,并將“動態”狀態轉換模型和“靜態”類關系圖綁在一起。通過比較圖 1 和圖 3,可以很容易發現隨著 Order 的狀態在業務流程中由開放進入已提交狀態(如圖 2 所示),其“形狀”發生了更改。圖 2 中的狀態顯示了行為的更改。

靜態模 型和動態模型相一起定義了面向服務的體系結構中完整的服務集。生命周期模型中的每個狀態都可以一對一地映射到會話 EJB 組件。STD 中的每個轉換都映射到與狀態關聯的會話 Bean 上的方法。關系模型中的每個類均可以映射一個實體 EJB 組件。關系圖中的關系自然映射到 CMR。因此對于開放和已提交兩種狀態,可以推斷出將有兩個會話 EJB,而這兩個會話 EJB 分別具有三四種更新方法。對于所顯示的兩個類關系圖,可以推斷出將有 15 個實體 EJB 組件,具有許多屬性和 CMR。

為了具體一些,讓我們以延期交貨訂單狀態為例進行說明。首先我們編寫一個純 Java 接口,可以在整個過程中重用此接口,如下所示:


代碼段 3. 顯示派生于 STD 的方法的純 Java 接口
            
public interface OpenOrder {
OrderKey open(CustomerKey cust)
throws CustomerNotFound, OrderAlreadyOpen;
int addLineItem(CustomerKey cust, ProductKey product, int qty)
throws CustomerNotFound, OrderNotOpen, InvalidQuantity;
void submit(CustomerKey cust)
throws CustomerNotFound, OrderNotOpen, OrderHasNoLineItems;
void cancel(CustomerKey cust)
throws CustomerNotFound, OrderNotOpen;
}

此接口可以在會話 EJB 接口和類似于以下的實現中重用:


代碼段 4. 會話 Bean 接口和實現類
            
public interface OpenOrderSession
extends javax.ejb.EJBLocalObject, OpenOrder;
public class OpenOrderSessionBean
implements javax.ejb.SessionBean
{
// implementations go here
}

如 果希望,您可以使用 EJB Home 方法代替會話 EJB。在這種情況下,Customer 實體就成了業務邏輯理所當然的“網關”,因為它表示的是在該狀態中驅動業務流程的 Actor。在這種情況下,可以采用上面處理會話的方式僅擴展同一個 OpenOrder 接口,如以下代碼段所示:


代碼段 5. 重用 OpenOrder 接口的 Customer 實體 Home 接口
            
public interface CustomerHome
extends javax.ejb.EJBLocalHome, OpenOrder
{
// other Home methods like findByPrimaryKey() and create()
}

無論選擇哪種方法,這些模型和映射都能提供實現更新方法所需的組件。如果要一一提供您的分析中列舉的每種排列,則也可以將這些動態和靜態的模型用于派生所有的讀取方法。但我們發現,最好從交付支持調用業務流程函數所需的數據的用戶界面 (UI) 屏幕流派生這些讀取方法。

對 于為屏幕流編寫文檔,我們也希望使用狀態轉換圖。可以將屏幕流 STD 看作是捕獲在業務流程模型中擁有狀態的 Actor 的典型“會話”的生命周期。其中的狀態顯示屏幕和彈出對話框,而轉換顯示用戶啟動的事件。為了加以說明,圖 4 演示了客戶的一個屏幕流,顯示它如何與訂單管理流程進行交互。


圖 4. 客戶訂單管理會話的示例屏幕流
圖 4. 客戶訂單管理會話的示例屏幕流

模型間的交互(如果有)在轉換上的 {} 內指定,顯示對業務流程調用轉換時的副作用。某些事件(如提交)會進入一個確認對話狀態。只有用戶觸發了“OK”,才會實際出現提交訂單的副作用。這些確認狀態用斜體表示。

另 一個用斜體顯示的狀態就是“Home”狀態,該狀態表示角色(本例中為 Customer)如何啟動和結束其會話。還有一個用斜體顯示的特殊狀態與業務流程相關聯——因為給定的 Actor 可能與多個流程交互。這兩個狀態都很特殊,因為它們只進行導航(它們通常以菜單或選項卡的形式出現,具體取決于 UI 的樣式)。

其 他的狀態都表示“實際”的屏幕(或屏幕的一部分;由于這已經涉及到一般 J2EE 最佳實踐,所以我們將在另一篇文章中專門就此進行討論)。對于每個屏幕(不管是否為特殊屏幕),都可以使用類關系圖捕獲該狀態的可見數據,類似于和業務流 程關聯的類關系圖顯示與狀態關聯的持久數據的方式。圖 5 顯示除確認狀態之外的所有狀態的組合類關系圖。


圖 5. 顯示會話的可見數據的示例類關系圖
圖 5. 顯示會話的可見數據的示例類關系圖

現 在我們就能理解為什么不會有很多 DTO 和相關方法的原因了。圖 5 顯示了七個包含內容(關系計數)的 DTO。這些 DTO 非常直接地映射到 Java 類。圖 4 所示的屏幕流上的到某個狀態的轉換映射到 OpenOrder 上的其他方法。它們所返回的 DTO 在圖 5 的類關系圖中進行了描述。我們要使用的約定是 <TargetState>Data(而非 DTO)。此方法的參數作為與轉換關聯的數據流顯示;其名稱將成為方法名的一部分。代碼段 6 顯示了某些示例:


代碼段 6. 某些從 UI 派生的只讀方法
            
CustomerHomeData getCustomerHomeData(CustomerKey cust)
throws CustomerNotFound;
ProductCatalogData getProductData(CustomerKey cust)
throws CustomerNotFound;
ProductCatalogData getNextProductData(
CustomerKey cust,
ProductKey last
)
throws CustomerNotFound, ProductNotFound;
ProductCatalogData getPreviousProductData(
CustomerKey cust,
ProductKey first
)
throws CustomerNotFound, ProductNotFound;
OrderDetailsData getOpenOrderDetailData(
CustomerKey cust,
)
throws CustomerNotFound, OrderNotFound;
OrderDetailsData getOrderDetailData(
OrderKey order,
)
throws OrderNotFound;
OrderStatusData getOrderStatusData(
CustomerKey cust,
)
throws CustomerNotFound;

正 如您所看到的,只讀方法非常少。“根”DTO 的數目甚至更少,因為這些 DTO 被重用。最糟糕的情況下,此例中也僅需八個 DTO 支持業務流程。而且,即使在實體 EJB 組件中進行 OO 委托以加載完整的結構,get<DTO>() 方法的總數仍將相對較少。

很抱歉,為了回答一個相對簡單的問題,我講了這么一大堆關于常規 OO 分析和設計技術的話題,但我仍然認為在實際操作中,通過返回需要的數據結構所帶來的封裝優勢會超過相關維護問題的困擾。

您同意嗎?

好,就此打住,
您的 EJB 倡導者 .




舊話重提,性能問題

親愛的 EJB 倡導者:

您進行面向對象的分析和將工作成果映射到 EJB 組件的方式很有意思。您的方法讓我相信可維護性問題并非想象的那樣糟。但我還有一個問題想請教。

我 仔細考慮之后,得出了一個完全不同的問題:如果調用 CMP 的 get<attribute>() 方法完全沒有性能損失,您是否仍然會建議會話外觀、DTO 裝配器或實體 Home 方法對實體使用 get<DTO>() 方法,而不直接一次性從相關實體獲得其所需的屬性?

例如,以圖 5 中的 DetailItemData DTO 為例。我認為,如果我按照您的建議使用 OO 委托,LineItem 實體將具有一個 getDetailItemData() 方法。此方法將按照 CMR 的指引獲得對 Product 的引用。您建議不對 Product 調用 getDescription() 和 getPrice(),而是創建一個新的 ProductDescriptionAndPriceData 對象,并對 Product 調用 getProductDescriptionAndPriceData()。然后我將從此結構中復制字段,并將這些字段和 productId 與 quantity(以及計算得到的量)一并復制到 DetailItemData 結構中。

我覺得這個方法真的很多余,除非性能真的有那么糟糕。

盼復,
Never Cry Wolf


相信您的直覺,但想進行驗證

親愛的 Never Cry Wolf:

您堅持不懈(沒有別的意思)的詢問真的讓 EJB 倡導者不禁懷疑自己倡導使用 EJB 的力度是否不夠。

我 必須承認,如果對本地實體 EJB 組件使用 get<attribute>() 方法,沒有任何性能問題,您所采用的在外觀或實體 Home 方法或已委托的方法中組裝所需數據的方法更具吸引力。這個方法在生成時要編譯的組件數量更少,運行時要回收的垃圾也更少,因此,我很高興您相信了您的直 覺,認為真正的問題并沒有得到回答。我們之間的這幾番交流表明,有時候必須反復多次才能徹底了解問題的實質。

另一方面,我也曾有 個直覺,認為本地方法調用的性能影響仍然很可觀。但我沒有采用任何有意義的方式進行測試,以驗證這個想法,而是相信那句格言“if it ain't broke, don't fix it”(東西還沒壞,就別急著去修它)——不僅是因為進行性能測試非常麻煩,而且也由于修改所有關于最佳實踐的演示材料和現有示例比這更麻煩。

這句格言對于“早期的”應用程序非常合理,但能驗證我原來的直覺則更好,因為新開發項目可以在適當的情況下選擇適當的方法。

因 此,我讓一個團隊進行了性能測試,結果我很驚喜地發現,只要客戶機和實體均位于同一個全局事務范圍內,“客戶機”通過本地接口調用本地 get<Attribute>() 方法和讓實體 Bean 實現調用自身抽象的 get<Attribute>() 方法,這兩種方式之間并沒有明顯的區別。

有了這個新數據后,我非常高興地對我的方法進行了修改,如果尚沒有提供信息的現有 get<DTO>() 方法,則直接使用 get<Attribute>() 方法組裝所需的數據。這適合于實體 EJB、實體 Home 方法、會話外觀或(如您所稱) DTO 裝配器類上的已委托的方法。

我還十分高興地發現,居然有人比我還更像一個 EJB 倡導者!如果有機會見面的話,我一定會請您吃飯。

好,就此打住,
您的 EJB 倡導者 .



結束語

下面是從以上討論中得出的一些有意義的原則:

  • 您的分析工作成果應該同時涵蓋業務域和用戶界面的動態和靜態方面。
  • 系統地將您的分析工作成果映射到適當的 EJB 組件和 DTO。
  • 會話 Bean 非常適合實現與業務流程(更新)或屏幕流(讀取)中的狀態關聯的轉換。
  • 當與表示擁有一個或多個業務流程中的狀態的 Actor 的“網關”對象關聯時,實體 Bean Home 方法是最好的選擇。
  • 在兩種情況下,都要盡可能利用與網關對象關聯的 CMR,并根據需要使用 get<DTO>(OO 委托)或 get<Attributes>(過程型組裝),以獲取要返回的數據。這很大程度上取決于您是否已經擁有適當的 DTO。
  • 最后,EJB 倡導者愿意承認自己錯了。只是要認識到自己的錯誤可能還需要一些時間。

我們相信您還能夠找到更多的類似問題。在下一篇專欄文章推出之前,這就夠您忙活的了。


致謝

在此特別感謝 Bobby Woolf,他為本文提供了重要的建議和資料。請訪問 Bobby 的博客來了解 J2EE in Practice



參考資料



關于作者

作者照片

Geoff Hambrick 來自 Texas 的 Round Rock(在 Austin 附近),是 IBM Software Services for WebSphere Enablement Team 的首席顧問。Enablement Team 通常通過深層技術簡報及短期概念驗證為售前流程提供支持。Geoff 于 2004 年 3 月被選為 IBM 的杰出工程師 (Distinguished Engineer),他的工作是創建并傳播用于開發 IBM WebSphere A

EJB 倡導者: 使用何種 EJB 組件組裝來自服務的數據


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 久久精品亚洲综合一品 | 人人干操 | 久久一本久综合久久爱 | 久草经典视频 | 免费网站啪啪大全 | 久久夜色精品国产欧美 | 四虎4hu永久免费视频大全 | 日韩特级毛片 | 国产精品日韩欧美久久综合 | 亚洲高清视频在线观看 | 一区精品在线 | 亚洲酒色1314狠狠做 | 99在线视频免费 | 精品国产日韩亚洲一区在线 | 国产成人精品免费视频 | 五月色婷婷综合激情免费视频 | 国产精品怡红院永久免费 | 俄罗斯三级毛片 | 国产做爰免费视频观看 | 涩涩99| 99999久爱视频在线观看 | 国产精品一国产精品免费 | 欧美japanese孕交 | jzz欧美 | 久久老色鬼天天综合网观看 | 老司机午夜在线视频免费 | 国产只有精品 | 日韩中文字幕高清在线专区 | 国产成人刺激视频在线观看 | 欧美大狠狠大臿蕉香蕉大视频 | 一级做a爱片特黄在线观看 一级做a爱片特黄在线观看免费看 | 四虎影视com88| 99视频在线观看高清 | 99久久久久国产 | 久久久免费精品视频 | 天天干亚洲 | 天天操一操 | 色婷婷中文字幕 | 26uuu在线 | 国产精品视频偷伦精品视频 | 日韩视频免费在线播放 |