posts - 78, comments - 34, trackbacks - 0, articles - 1
            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

          2010-01-21 傳智播客—EJB

          Posted on 2010-01-22 11:40 長城 閱讀(347) 評(píng)論(0)  編輯  收藏

          EJB3的功能很是強(qiáng)大,但中小企業(yè)很少使用它做開發(fā),一般應(yīng)用SSH足以應(yīng)付。JAVAEE是做什么的?她是分布式企業(yè)級(jí)應(yīng)用的規(guī)范,那EJB就是為實(shí)現(xiàn)這樣的應(yīng)用而開發(fā)的。

          什么是分布式應(yīng)用?聽著名字很大。比如咱們的在線支付系統(tǒng),淘寶、china-pubamazon等都支持支付寶在線支付。難道它們分別都要將支付寶模塊放在自己的服務(wù)器上?完全沒必要。支付寶模塊單獨(dú)放在一個(gè)服務(wù)器上,其他服務(wù)器使用(調(diào)用)那一個(gè)服務(wù)器上的支付寶就可以了。在現(xiàn)實(shí)應(yīng)用中還有一些類似的將某一應(yīng)用模塊單獨(dú)取出放到另一個(gè)服務(wù)器上,供其他應(yīng)用使用。這就是分布式應(yīng)用了。(分布在不同的服務(wù)器上的應(yīng)用)

          一、JAVAEE回顧

          JAVAEE到底是什么呢?一圖更清(JavaEE5.0):

          wps_clip_image-9153

          昨天我們實(shí)現(xiàn)的EJB組件接口使用的是“@Local”注解,此注解只提供給本地調(diào)用。外部機(jī)器無法訪問。因?yàn)橥獠坑脩襞c本地不在同一個(gè)虛擬機(jī)中。我們編寫的EJB組件不主要是給外部用戶訪問而使用分布試應(yīng)用嗎?正是。所以為了讓外部機(jī)器可以使用,我們需要將“@Local”注解修改為“@Remote”注解。在外部調(diào)用遠(yuǎn)程的EJB組件時(shí),應(yīng)該這樣使用:

          InitialContext ctx = new InitialContext();

          HelloWorld hw = (HelloWorld)ctx.lookup("HelloWorldBean/remote");

          String str = hw.sayHello("changcheng");

          二、EJB3中的EntityBean

          EJB3中的EntityBean就是POJOPlain old java object+注解,這方面的知識(shí)我們已經(jīng)在JPA中學(xué)習(xí)了。

          三、EJB3中的SessionBean

          SessionBean分為有狀態(tài)SessionBeanStateFulSessionBean-sfsb)和無狀態(tài)SessionBeanStateLessSessionBean-slsb)。

          1.StateLessSessionBean

          我們?cè)谥笆亲龅木毩?xí)中,一般都有一個(gè)DAO層。DAO層不記錄用戶的狀態(tài),所以我們?cè)谑褂?/font>EJB開發(fā)時(shí),可以直接將DAO層定義為無狀態(tài)Bean

          如何定義無狀態(tài)Bean,我們?cè)谧蛱斓木毩?xí)中使用的就是無狀態(tài)Bean。直接在類上添加“@Stateless”注解,即可將類定義為無狀態(tài)的Bean

          每次產(chǎn)生一個(gè)新的會(huì)話,EJB容器需要為會(huì)話創(chuàng)建相關(guān)的無狀態(tài)Bean對(duì)象,無疑這會(huì)為服務(wù)器帶來極大的資源開銷。我們?cè)趯W(xué)習(xí)JDBC時(shí),使用了線程池專門用來處理用戶與數(shù)據(jù)庫的連接。因?yàn)闊o狀態(tài)Bean不記錄用戶的狀態(tài),所以EJB3中也定義了無狀態(tài)的Bean池。這樣大大節(jié)省了用戶訪問的時(shí)間與服務(wù)器資源的開銷。

          無狀態(tài)Bean具有兩個(gè)事件,創(chuàng)建后和銷毀前。我們?cè)诜椒ㄉ咸砑印?/font>@PostConstruct”注解,此方法將在無狀態(tài)Bean創(chuàng)建后調(diào)用,我們?cè)诜椒ㄉ咸砑印?/font>@PreDestroy”注解,此方法將在無狀態(tài)Bean銷毀后被調(diào)用。

          2.StateFulSessionBean

          有狀態(tài)Bean的典型案例是購物車,購物車需要記錄用戶購買的商品,所以它是有狀態(tài)的Bean。我們知道無狀態(tài)BeanBean池,那有狀態(tài)Bean可否有Bean池呢?當(dāng)然不可以。所以有狀態(tài)Bean會(huì)給服務(wù)器帶來極大的負(fù)擔(dān),能不用有狀態(tài)Bean就不要使用有狀態(tài)Bean

          EJB3中也盡量減少有狀態(tài)Bean所帶來的負(fù)載,所以EJB3為有狀態(tài)Bean添加了鈍化和激活的功能。比如用戶在超市購物,用戶剛進(jìn)入超市時(shí)推起購物車(CartBean對(duì)象,這個(gè)有狀態(tài)Bean被創(chuàng)建)。當(dāng)用戶選擇商品并謝謝購物車時(shí)(向CartBean對(duì)象添加狀態(tài))。突然用戶有急事要離開一會(huì),工作人員將購物車推到“等候區(qū)”(CartBean對(duì)象被鈍化)。用戶處理完事物之后回來繼續(xù)購物,到“等候區(qū)”推出自己的購物車(CartBean對(duì)象被激活)。用戶結(jié)賬工取消購物時(shí)(CartBean對(duì)象被刪除)。

          EJB3中正是使用方法減少頻繁創(chuàng)建有狀態(tài)Bean所給服務(wù)器帶來的負(fù)擔(dān),同時(shí)也為用戶提供了方便。

          EJB3中有狀態(tài)Bean的事件:

          1).有狀態(tài)Bean被創(chuàng)建后:在某一方法上添加“@PostConstruct”注解,有狀態(tài)Bean被創(chuàng)建后會(huì)調(diào)用此方法。

          2).有狀態(tài)Bean被鈍化:在某一方法上添加“@PrePassivate”注解,調(diào)用此方法后,有狀態(tài)Bean被鈍化。EJB3容器會(huì)將此Bean序列化后,保存到硬盤上,并從內(nèi)存中刪除。有狀態(tài)Bean需要實(shí)現(xiàn)“Serializable”接口。

          3).有狀態(tài)Bean被激活:在某一方法上添加“@PostActivate”注解,調(diào)用此方法后,有狀態(tài)Bean被激活。EJB3容器會(huì)將此Bean反序列化后,放到內(nèi)存中,并刪除硬盤上的內(nèi)容。

          4).有狀態(tài)Bean被銷毀前:在某一方法上添加“@PreDestroy”注解,無狀態(tài)Bean被銷毀前會(huì)調(diào)用此方法。

          5).有狀態(tài)Bean被刪除:在某一方法上添加“@Remove”注解,調(diào)用此方法后,通知EJB3容器刪除有狀態(tài)Bean。如果不添加“@Remove”注解,客戶端將沒有任何方式告訴服務(wù)器終止會(huì)話,結(jié)果將導(dǎo)致SFSB在超時(shí)后進(jìn)行鈍化至磁盤,再次超時(shí)后將對(duì)象銷毀。在高并發(fā)的系統(tǒng)當(dāng)中,無疑會(huì)有嚴(yán)重的性能問題。內(nèi)存開銷會(huì)居高不下,更不要提占用cpu和磁盤空間了。

          四、EJB3中的消息驅(qū)動(dòng)Bean

          EJB3中的消息驅(qū)動(dòng)分為隊(duì)列消息(queue)和主題消息(Topic),是一種異步消息驅(qū)動(dòng)。

          1.隊(duì)列消息

          發(fā)送消息:

          import javax.jms.*;

          import javax.naming.InitialContext;

          /**

           * 隊(duì)列消息驅(qū)動(dòng)bean

           */

          public class MDBQueueApp {

          public static void main(String[] args) throws Exception {

          InitialContext ctx = new InitialContext();

          //通過JNDI查找隊(duì)列連接工廠,EJB自身包含的。

          QueueConnectionFactory qcf = (QueueConnectionFactory) ctx.lookup("QueueConnectionFactory");

          //通過連接工廠創(chuàng)建隊(duì)列連接

          QueueConnection qc = qcf.createQueueConnection();

          //通過隊(duì)列連接創(chuàng)建隊(duì)列會(huì)話

          QueueSession qs = qc.createQueueSession(false,Session.AUTO_ACKNOWLEDGE);

          //通過JNDI查找可用隊(duì)列,EJB3自身包含的。

          Queue queue = (Queue) ctx.lookup("queue/testQueue");

          //通過隊(duì)列會(huì)話創(chuàng)建到指定隊(duì)列的消息生產(chǎn)者

          MessageProducer mp = qs.createProducer(queue);

          //通過隊(duì)列回話創(chuàng)建文本消息

          TextMessage msg = qs.createTextMessage();

          msg.setText("Hi,你好嗎?隊(duì)列消息");

          //通過消息的生產(chǎn)者發(fā)送消息

          mp.send(msg);

          //釋放資源

          qs.close();

          qc.close();

          System.out.println("隊(duì)列消息發(fā)送完畢!");

          }

          }

          接收消息:

          import javax.ejb.*;

          import javax.jms.*;

          @MessageDriven(activationConfig={@ActivationConfigProperty(propertyName="destinationType",propertyValue="javax.jms.Queue"),@ActivationConfigProperty(propertyName="destination",propertyValue="queue/testQueue")})

          public class MyQueueMDB implements MessageListener {

          public void onMessage(Message arg0) {

          if(arg0 instanceof TextMessage){

          try {

          System.out.println("收到消息隊(duì)列消息 : " + ((TextMessage)arg0).getText());

          System.out.println("I'm fine,Thank you!");

          } catch (Exception e) {

          e.printStackTrace();

          }

          }

          }

          }

          隊(duì)列消息只能被一個(gè)接收都接收到,隊(duì)列消息一旦被某個(gè)接收者接收到后,消息將從隊(duì)列中消失。所以其他接收同一隊(duì)列消息的接收者無法收到。這個(gè)第一個(gè)接收到隊(duì)列消息的接收者是最后一次被添加的接收者。

          2.主題消息

          發(fā)送消息:

          import javax.jms.*;

          import javax.naming.InitialContext;

          /**

           * 主題消息驅(qū)動(dòng)bean

           */

          public class MDBAppTopic {

          public static void main(String[] args) throws Exception {

          InitialContext ctx = new InitialContext();

          //通過JNDI查找主題連接工廠,EJB3自身包含的。

          TopicConnectionFactory tcf = (TopicConnectionFactory) ctx.lookup("TopicConnectionFactory");

          //通過連接工廠創(chuàng)建主題連接

          TopicConnection tc = tcf.createTopicConnection();

          //通過主題連接創(chuàng)建主題會(huì)話

          TopicSession ts = tc.createTopicSession(false,Session.AUTO_ACKNOWLEDGE);

          //通過JNDI查找可用主題,EJB3自身包含的。

          Topic topic = (Topic) ctx.lookup("topic/testTopic");

          //通過主題會(huì)話創(chuàng)建到指定主題的消息生產(chǎn)者

          MessageProducer mp = ts.createProducer(topic);

          //通過主題回話創(chuàng)建文本消息

          TextMessage msg = ts.createTextMessage();

          msg.setText("Hi,你好嗎?(主題消息)");

          //通過消息的生產(chǎn)者發(fā)送消息

          mp.send(msg);

          //釋放資源

          ts.close();

          tc.close();

          System.out.println("主題消息發(fā)送完畢!");

          }

          }

          接收消息:

          import javax.ejb.*;

          import javax.jms.*;

          @MessageDriven(activationConfig={@ActivationConfigProperty(propertyName="destinationType",propertyValue="javax.jms.Topic"),@ActivationConfigProperty(propertyName="destination",propertyValue="topic/testTopic")})

          public class MyTopicMDB implements MessageListener {

          public void onMessage(Message arg0) {

          if(arg0 instanceof TextMessage){

          try {

          System.out.println("收到主題消息 : " + ((TextMessage)arg0).getText());

          System.out.println("我很好,謝謝!");

          } catch (Exception e) {

          e.printStackTrace();

          }

          }

          }

          }

          主題消息是一種共享模式,相當(dāng)于群。每個(gè)消息被當(dāng)做主題,群內(nèi)的所有成員都可以收到。

          五、ANT

          我們編寫EJB組件和WEB應(yīng)用時(shí),需要手動(dòng)打成JARWAR包并放置到JBOSSdeploy目錄中。這顯然是不理想的操作方式,我們每測試一個(gè)功能都這樣做嗎?ANT可以幫助我們解決這個(gè)問題。

          當(dāng)一個(gè)代碼項(xiàng)目大了以后,每次重新編譯,打包,測試等都會(huì)變得非常復(fù)雜而且重復(fù),因此c語言中有make腳本來幫助這些工作的批量完成。在Java 中應(yīng)用是平臺(tái)無關(guān)性的,當(dāng)然不會(huì)用平臺(tái)相關(guān)的make腳本來完成這些批處理任務(wù)了,ANT本身就是這樣一個(gè)流程腳本引擎,用于自動(dòng)化調(diào)用程序完成項(xiàng)目的編譯,打包,測試等。除了基于JAVA是平臺(tái)無關(guān)的外,腳本的格式是基于XML的,比make腳本來說還要好維護(hù)一些。 

          ANT IN ACTION 2)》是一本專門調(diào)解ANT的書籍,在此就不多總結(jié)了。


          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 瑞安市| 河东区| 麻城市| 宁明县| 清镇市| 江川县| 江阴市| 洛南县| 从化市| 白水县| 花莲县| 卓资县| 泗洪县| 二手房| 南安市| 咸宁市| 汉寿县| 商水县| 阿克| 吴旗县| 彭山县| 伊川县| 蓝田县| 彭阳县| 浦县| 怀集县| 宽甸| 延津县| 无棣县| 漳州市| 福泉市| 赤水市| 溧水县| 鄂州市| 巴青县| 额济纳旗| 商水县| 石首市| 临桂县| 韶山市| 十堰市|