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

EJB 3.0的三大類型

申請(qǐng)免費(fèi)試用、咨詢電話:400-8352-114

文章來(lái)源:泛普軟件

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

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

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

會(huì)話bean

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

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

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

會(huì)話 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";

  }

}

實(shí)體bean

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

實(shí)體 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();}

  }

消息驅(qū)動(dòng)的bean

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

消息驅(qū)動(dòng)的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客戶端是訪問(wèn)bean的應(yīng)用程序。它不必位于客戶端層上,但可以是獨(dú)立的應(yīng)用程序、Java服務(wù)器頁(yè)面(JSP)、服務(wù)器小程序或者另一個(gè)EJB??蛻舳送ㄟ^(guò)bean的遠(yuǎn)程或本地接口來(lái)使用EJB的方法,遠(yuǎn)程還是本地取決于客戶端是在同一個(gè)JVM里面還是不同的JVM里面。這些接口定義了bean的方法,而bean類負(fù)責(zé)實(shí)際實(shí)現(xiàn)這些方法??蛻舳嗽L問(wèn)bean類的方法時(shí),容器就會(huì)為bean生成一個(gè)代理,名為遠(yuǎn)程或者本地對(duì)象。遠(yuǎn)程或者本地對(duì)象接收請(qǐng)求后,交給相應(yīng)的bean實(shí)例,并將結(jié)果返回給客戶端。想調(diào)用bean的方法,客戶端需要通過(guò)使用EJB部署描述符(deployment descriptor)里面定義的bean名稱來(lái)找到該bean。在以下的示例中,客戶端使用Context對(duì)象找到名為“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(); }

  }

鏈接:必要的準(zhǔn)備

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

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

處理好架構(gòu)問(wèn)題

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

不過(guò),使用本地實(shí)體不是目的,因?yàn)閷?shí)體還為部署人員提供了為實(shí)體聲明事務(wù)和安全需求的功能。EJB 3.0不允許任何這些屬性在實(shí)體層面進(jìn)行設(shè)定。相反,實(shí)體的運(yùn)行環(huán)境將由調(diào)用者來(lái)確定,所以所需的任何事務(wù)或者安全環(huán)境將由負(fù)責(zé)封閉的J2EE組件來(lái)安裝或者聲明。

CMP應(yīng)用程序

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

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

POJO應(yīng)用程序

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

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

采用標(biāo)準(zhǔn)特性

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

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

查詢語(yǔ)言往往是造成遷移問(wèn)題的根源,因?yàn)椴痪帉?xiě)實(shí)質(zhì)性或者窮舉性的轉(zhuǎn)換分析工具,就很難實(shí)現(xiàn)自動(dòng)轉(zhuǎn)換。EJB查詢語(yǔ)言這種合理、有效的方法可對(duì)關(guān)系查詢語(yǔ)言進(jìn)行抽象處理,將受益于新增的幾項(xiàng)特性?,F(xiàn)有的EJB查詢語(yǔ)言仍可以適用,不過(guò)EJB查詢語(yǔ)言方面的更多構(gòu)件和功能將進(jìn)一步改進(jìn)查詢語(yǔ)言。使用EJB查詢語(yǔ)言編寫(xiě)查詢將是明智之舉,因?yàn)椴樵冋Z(yǔ)言不會(huì)出現(xiàn)重大改變,除了功能上有所添加外。

繼承

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

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

樂(lè)觀鎖定

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

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

對(duì)象-關(guān)系映射

想編寫(xiě)面向?qū)ο蟮腏ava程序,卻把數(shù)據(jù)保存在關(guān)系數(shù)據(jù)庫(kù)里面,這在以前是困擾應(yīng)用程序開(kāi)發(fā)的一個(gè)重大問(wèn)題。

決定把用于對(duì)象關(guān)系映射的標(biāo)準(zhǔn)化元數(shù)據(jù)和語(yǔ)義添加到EJB 3.0內(nèi),這向?qū)崿F(xiàn)下列功能邁出了一大步:讓?xiě)?yīng)用程序能夠靈活地把應(yīng)用程序放在不同數(shù)據(jù)庫(kù)上面運(yùn)行,甚至可以使用不同的持久性框架來(lái)進(jìn)行運(yùn)行。對(duì)象-關(guān)系映射標(biāo)準(zhǔn)的第一個(gè)階段將包括如今人們用來(lái)映射域模型的幾種最流行的映射方法,譬如數(shù)據(jù)轉(zhuǎn)換和一對(duì)一及多對(duì)多關(guān)系等。隨后還會(huì)添加“高級(jí)”映射方法。 (CCW)

 

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

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

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

咨詢:400-8352-114

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

QQ在線咨詢

泛普南昌OA信息化其他應(yīng)用

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