監(jiān)理公司管理系統(tǒng) | 工程企業(yè)管理系統(tǒng) | OA系統(tǒng) | ERP系統(tǒng) | 造價咨詢管理系統(tǒng) | 工程設計管理系統(tǒng) | 簽約案例 | 購買價格 | 在線試用 | 手機APP | 產品資料
X 關閉

EJB 3.0的三大類型

申請免費試用、咨詢電話:400-8352-114

文章來源:泛普軟件

無論你創(chuàng)建bean會話是為了執(zhí)行特定任務,還是把表映射到實體bean以更新數(shù)據(jù),都可以使用普通的Java對象和接口來完成這些工作,并且可以通過在業(yè)務方法中使用注釋,把方法提供給客戶端。

Enterprise JavaBean (EJB) 是可重用的、可移植的 J2EE 組件。EJB 由封裝業(yè)務邏輯的方法組成。譬如說,EJB 可能有這樣的業(yè)務邏輯:包含了更新數(shù)據(jù)庫中客戶數(shù)據(jù)的方法。眾多遠程和本地客戶端可以調用該方法。另外,EJB 在容器里面運行,這樣開發(fā)人員只要關注bean里面的業(yè)務邏輯,不必擔心復雜、容易出錯的問題,譬如事務支持、安全性和遠程對象訪問等。EJB 作為普通Java對象(POJO)的形式來開發(fā),開發(fā)人員可以使用元數(shù)據(jù)注釋(metadata annotations)來指定容器如何管理這些bean。

EJB 包括三種主要類型:會話 bean、實體 bean和消息驅動的bean。會話bean執(zhí)行獨立的、解除耦合的任務,譬如檢查客戶的信用記錄。實體bean是一個復雜的業(yè)務實體,它代表數(shù)據(jù)庫中存在的業(yè)務對象。消息驅動的bean用于接收異步JMS 消息。下面,讓我們進一步研究EJB 3.0規(guī)范中的這些類型。

會話bean

會話bean通常代表業(yè)務流程里面的操作,譬如“處理訂單”??筛鶕?jù)對話狀態(tài)的保持性,即有狀態(tài)和無狀態(tài)對會話bean進行分類。

無狀態(tài)的會話 bean沒有內部狀態(tài)。它們不跟蹤記錄從一個方法調用傳遞到另一個方法調用的信息。因此,每次調用無狀態(tài)的業(yè)務方法都獨立于前一次調用,譬如計算稅款或者運費。用某個應稅值調用計算稅款的方法時,對稅款值進行計算并返回給調用方法,而不必保存調用者的內部狀態(tài)供以后調用。因為這些bean并不保持狀態(tài),所以容器對它們進行管理就很簡單??蛻舳苏埱鬅o狀態(tài)的bean實例時,可以從容器保持的無狀態(tài)的會話bean 實例池當中接收一個實例。另外,因為無狀態(tài)的會話 bean可以共享,所以容器可保持數(shù)量較少的實例為許多客戶端提供服務。想指定Java Bean作為無狀態(tài)的會話bean加以部署及管理,只需要為該bean添加注釋@Stateless。

有狀態(tài)的會話 bean在方法調用時可保持對話狀態(tài),譬如客戶的網上購物車。客戶開始網上購物時,可以從數(shù)據(jù)庫中檢索客戶的詳細信息??蛻敉徫镘嚴锩嫣砑由唐坊蛘邚睦锩鎰h除商品、下訂單等時調用的其他方法也可以使用這些詳細信息。不過,有狀態(tài)的會話bean是暫時性的,因為出現(xiàn)會話終止、系統(tǒng)崩潰或者網絡故障后,狀態(tài)不復存在。客戶端請求有狀態(tài)的會話bean實例時,就為該客戶端分配一個有狀態(tài)的實例,并為該客戶端保持該組件的狀態(tài)。要指定容器在某個方法完成后刪除有狀態(tài)的會話bean實例,只要為該方法添加注釋@Remove。

會話 bean示例如下:

import javax.ejb.Stateless.*;

  /*A simple stateless session bean implementing the incrementValue() method of the * CalculateEJB interface.*/

@Stateless(name="CalculateEJB")

public class CalculateEJBBean

implements CalculateEJB

{

int value = 0;

  public String incrementValue()

  {

value++;

   return "value incremented by 1";

  }

}

實體bean

實體bean是管理持久性數(shù)據(jù)的一個對象,有可能使用幾個相關的Java對象,并可以通過主鍵實現(xiàn)惟一性。通過添加@Entity注釋,可以把某類指定為實體bean。實體bean代表數(shù)據(jù)庫中的持久性數(shù)據(jù),如客戶表中的一行或者員工表中的一條員工記錄。實體bean還可以在多個客戶端之間共享。譬如說,某個員工實體bean可以由多個客戶端用于計算某員工的年薪或者更新員工地址。實體bean對象的特定字段可以成為持久性字段。實體bean中沒有被@Transient注釋標記的所有字段都被視為持久性字段。EJB 3.0的一個主要特性就是,能夠使用元數(shù)據(jù)注釋來創(chuàng)建包含對象/關系映射的實體bean。譬如說,想指定把實體bean的empId字段映射到 Employees表中的EMPNO屬性,就要使用@Table(name="Employees") 來注釋表名,使用 @Column(name="EMPNO") 來注釋字段,如下面的例子所示。另外,EJB 3.0 的一個特性是,在開發(fā)期間可以方便地測試實體bean,因為現(xiàn)在使用 Oracle 應用服務器實體測試工具,就可以在容器外面運行實體bean。

實體 bean示例如下:

  import javax.persistence.*;

  import java.util.ArrayList;

  import java.util.Collection;

  @Entity

  @Table(name = "EMPLOYEES")

  public class Employee implements java.io.Serializable

  {

   private int empId;

   private String eName;

   private double sal;

   @Id

   @Column(name="EMPNO", primaryKey=true)

   public int getEmpId()

    { return empId;}

   public void setEmpId(int empId)

    { this.empId = empId; }

   public String getEname()

    { return eName; }

   public void setEname(String eName)

    { this.eName = eName; }

   public double getSal()

    { return sal; }

   public void setSal(double sal)

    { this.sal = sal; }

   public String toString()

    {StringBuffer buf = new StringBuffer();

    buf.append("Class:")

    .append(this.getClass().getName()).append(" ::").append(" empId:").append(getEmpId()).append(" ename:").append(getEname()).append("sal:").append(getSal());

    return buf.toString();}

  }

消息驅動的bean

消息驅動的bean(MDB)為實現(xiàn)異步通信提供了一種比使用直接的Java消息服務(JMS)更簡單的方法。MDB用于接收異步JMS消息。容器處理JMS隊列和主題所需的大部分設置進程。它把所有消息發(fā)送給相關的MDB。MDB允許J2EE應用程序發(fā)送異步消息,隨后這些消息由應用程序來處理。要把bean指定為MDB,需要實現(xiàn)javax.jms.MessageListener接口,并且用@MessageDriven注釋該bean。

消息驅動的bean示例如下:

  import javax.ejb.MessageDriven;

  import javax.ejb.ActivationConfigProperty;

  import javax.ejb.Inject;

  import javax.jms.*;

  import java.util.*;

  import javax.ejb.TimedObject;

  import javax.ejb.Timer;

  import javax.ejb.TimerService;

  @MessageDriven(

  activationConfig = {

  @ActivationConfigProperty(propertyName="connectionFactoryJndiName", propertyValue="jms/TopicConnectionFactory"),

  @ActivationConfigProperty(propertyName="destinationName", propertyValue="jms/myTopic"),

  @ActivationConfigProperty(propertyName="destinationType", propertyValue="javax.jms.Topic"),

  @ActivationConfigProperty(propertyName="messageSelector", propertyValue="RECIPIENT = 'MDB'") } )

  /** A simple Message-Driven Bean that listens to the configured JMS Queue or Topic and gets notified via an * invocation of it's onMessage() method when a message has been posted to the Queue or Topic.The bean

  * prints the contents of the message. */

  public class MessageLogger implements MessageListener, TimedObject

  {

   @Inject javax.ejb.MessageDrivenContext mc;

   public void onMessage(Message message)

   { System.out.println("onMessage() - " + message);

     try

     {

       String subject = message.getStringProperty("subject");

       String inmessage = message.getStringProperty("message");

       System.out.println("Message receivedntDate:" + new java.util.Date() + "ntSubject:" + subject + "ntMessage:" + inmessage + "n");

       System.out.println("Creating Timer a single event timer");

       TimerService ts = mc.getTimerService();

       Timer timer = ts.createTimer(30000, subject);

       System.out.println("Timer created by MDB at:" + new Date(System.currentTimeMillis()) +" with info:"+subject); }

   catch (Throwable ex)

   { ex.printStackTrace(); }

  }

   public void ejbTimeout(Timer timer)

   { System.out.println("EJB 3.0:Timer with MDB");

     System.out.println("ejbTimeout() called at:" + new Date(System.currentTimeMillis()));

     return; }

  }

使用 EJB 3.0

EJB客戶端是訪問bean的應用程序。它不必位于客戶端層上,但可以是獨立的應用程序、Java服務器頁面(JSP)、服務器小程序或者另一個EJB??蛻舳送ㄟ^bean的遠程或本地接口來使用EJB的方法,遠程還是本地取決于客戶端是在同一個JVM里面還是不同的JVM里面。這些接口定義了bean的方法,而bean類負責實際實現(xiàn)這些方法??蛻舳嗽L問bean類的方法時,容器就會為bean生成一個代理,名為遠程或者本地對象。遠程或者本地對象接收請求后,交給相應的bean實例,并將結果返回給客戶端。想調用bean的方法,客戶端需要通過使用EJB部署描述符(deployment descriptor)里面定義的bean名稱來找到該bean。在以下的示例中,客戶端使用Context對象找到名為“Statelessejb”的bean。

EJB 客戶端示例如下:

  import javax.naming.Context;

  import javax.naming.InitialContext;

  /* A simple bean client which calls methods on a stateless session bean.*/

  public class CalculateejbClient

  {

    public static void main(String [] args)

   {

     Context context = new InitialContext();

     CalculateEJB myejb =(CalculateEJB)context.lookup("java:comp/env/ejb/CalculateEJB");

   myejb.incrementValue(); }

  }

鏈接:必要的準備

EJB 3.0極其重視開發(fā)的簡易性,并調整了模型。這絕非巧合,因為規(guī)范的主要設計者:Linda DeMichiel選擇了廣泛聽取外界的意見,并借鑒TopLink等產品所取得的經驗。這樣一來,這項規(guī)范就可以沿著已經由流行、得到公認的技術開辟出來的道路前進,而這些道路實際上成了業(yè)內事實上的最佳實踐。

那么,作為程序員的你,面對新的規(guī)范,該做哪些準備呢?

處理好架構問題

首先要確保你的架構可以利用持久性方面的標準及認可的設計模式。實際上,這可能需要改動你的應用程序,不過如果你期望應用程序能經得起時間的考驗,那么進行這種投入是值得的。使用會話外觀、數(shù)據(jù)訪問對象(DAO)層或者服務層總是好主意,不過在這里它們都至關重要。如果你的應用程序已經使用遠程實體構建而成——雖然這種做法并不常見,那么就需要重新設計架構。訪問持久性對象之前,應當先部署可遠程化服務層。如果要使用實體,它就應當完全是本地實體。

不過,使用本地實體不是目的,因為實體還為部署人員提供了為實體聲明事務和安全需求的功能。EJB 3.0不允許任何這些屬性在實體層面進行設定。相反,實體的運行環(huán)境將由調用者來確定,所以所需的任何事務或者安全環(huán)境將由負責封閉的J2EE組件來安裝或者聲明。

CMP應用程序

如果你已經是容器管理持久性(CMP)用戶,那么你可能迫不及待地想獲得新特性,希望拋棄無關的接口、不必要的bean代碼以及繁瑣的XML部署描述符,這些是與以前的實體bean開發(fā)相關的一些煩人問題。分別要擴展EJBObject和EJBLocalObject的遠程和本地接口再也不需要了;現(xiàn)在實體只要實現(xiàn)普通Java接口(POJI)即可,如果它們選擇這么做的話。

其次,你可能在想如何更容易地在容器中部署EJB,或者甚至根本不用部署,而是在獨立環(huán)境中的容器外面進行測試。因為實體是具體的普通Java對象(POJO),你就可以像一直以來創(chuàng)建Java對象的方式那樣,即使用new()來創(chuàng)建。

POJO應用程序

可以通過實體管理器(EntityManager)訪問大部分新的持久性API。實體管理器可以注入到會話bean里面,或者用Java命名和目錄接口(JNDI)進行查詢。實體管理器代表事務的持久性上下文。一旦發(fā)現(xiàn)操作單元或者實體管理器管理的對象在事務結束后“很臟”,就會被寫到外面的數(shù)據(jù)存儲區(qū)。

應用程序可以通過抽取含有操作單元/會話工件(artifact)的代碼,讓自己不受全面變化的影響。這樣一來,就可以通過可插入方式來獲得所用的實際會話。定義會話、然后允許包圍層把它與外界隔離開來,這類似EJB 3.0容器所采用的依賴注入范例(dependency injection paradigm)。應用程序中使用的所有資源應當采用這種模式。在EJB 3.0中,標準資源將由應用程序聲明,隨后在運行時被注入到bean里面。

采用標準特性

EJB 3.0的許多特性可以在TopLink存在已久的特性當中找到影子。只要使用這些特性,你就能夠擁有EJB 3.0的功能,雖然API還沒有完成。

查詢就是這樣一個方面,你現(xiàn)在可以開始使用EJB 3.0的特性。EJB 3.0查詢可以從實體管理器獲得,并且可以在上面執(zhí)行??梢栽谀阈枰苯硬樵僑LQ、并通過查詢返回對象的少數(shù)情況下,創(chuàng)建本地SQL查詢。

查詢語言往往是造成遷移問題的根源,因為不編寫實質性或者窮舉性的轉換分析工具,就很難實現(xiàn)自動轉換。EJB查詢語言這種合理、有效的方法可對關系查詢語言進行抽象處理,將受益于新增的幾項特性?,F(xiàn)有的EJB查詢語言仍可以適用,不過EJB查詢語言方面的更多構件和功能將進一步改進查詢語言。使用EJB查詢語言編寫查詢將是明智之舉,因為查詢語言不會出現(xiàn)重大改變,除了功能上有所添加外。

繼承

EJB 2.1從來沒有指定真正的、自然的繼承。實際上,只有在廠商不設置障礙的情況下才有可能實現(xiàn)繼承,不過仍很難定義及管理。EJB 3.0卻不會這樣。由于具體的Java對象能夠彼此繼承,也用不著定義約束繼承范圍的方法,所以你能夠創(chuàng)建任意深度及廣度的實體繼承層次。

目前可以通過TopLink Mapping Workbench或JDeveloper、映射Java對象的GUI工具以及用于映射對象的基于Java的API,獲得同樣的這種靈活性。現(xiàn)在你可以創(chuàng)建域模型(domain model),以遵守適合你應用程序的繼承策略,而不必等規(guī)范發(fā)布。

樂觀鎖定

TopLink支持的樂觀鎖定(optimistic locking)模型現(xiàn)在將被采用到EJB 3.0模型里面。這種機制對應用程序非常有用,不僅僅是因為在讀/寫訪問比通常為90:10的情況下,它可以大大提高性能;還因為它有助于獲得現(xiàn)代系統(tǒng)所需的那種可擴展架構。業(yè)界的眾多應用程序使用這種主要的鎖定范例,來獲得Web應用程序所需的可擴展性。只要使用簡單方法:為每個樂觀鎖定的對象采用數(shù)據(jù)庫列和對象版本字段,就很容易獲得可移植性。

這種鎖定帶來了另外的好處:能夠使用非連接模式的對象。只要把數(shù)據(jù)重新并入事務、然后通過樂觀鎖值驗證已改動的對象是不是失效副本,就很容易支持在離線狀態(tài)下改動數(shù)據(jù)和關系的功能。

對象-關系映射

想編寫面向對象的Java程序,卻把數(shù)據(jù)保存在關系數(shù)據(jù)庫里面,這在以前是困擾應用程序開發(fā)的一個重大問題。

決定把用于對象關系映射的標準化元數(shù)據(jù)和語義添加到EJB 3.0內,這向實現(xiàn)下列功能邁出了一大步:讓應用程序能夠靈活地把應用程序放在不同數(shù)據(jù)庫上面運行,甚至可以使用不同的持久性框架來進行運行。對象-關系映射標準的第一個階段將包括如今人們用來映射域模型的幾種最流行的映射方法,譬如數(shù)據(jù)轉換和一對一及多對多關系等。隨后還會添加“高級”映射方法。 (CCW)

 

發(fā)布:2007-04-22 10:00    編輯:泛普軟件 · xiaona    [打印此頁]    [關閉]
南昌OA系統(tǒng)
聯(lián)系方式

成都公司:成都市成華區(qū)建設南路160號1層9號

重慶公司:重慶市江北區(qū)紅旗河溝華創(chuàng)商務大廈18樓

咨詢:400-8352-114

加微信,免費獲取試用系統(tǒng)

QQ在線咨詢

泛普南昌OA信息化其他應用

南昌OA軟件 南昌OA新聞動態(tài) 南昌OA信息化 南昌OA快博 南昌OA行業(yè)資訊 南昌軟件開發(fā)公司 南昌門禁系統(tǒng) 南昌物業(yè)管理軟件 南昌倉庫管理軟件 南昌餐飲管理軟件 南昌網站建設公司