文章出處

上一篇已經知道了JMS的基本操作,今天來看一下ejb3中的一種重要bean:Message Drive Bean(mdb)

如果要不斷監聽一個隊列中的消息,通常我們需要寫一個監聽程序,這需要一定的開發量,而且如果要實現高并發處理,也不易擴展,而MDB則自動實現了該功能,簡單點講,MDB的應用部署到jboss后,能自動監聽目標隊列,一旦有消息接收,會觸發onMessage事件,開發人員可以在該事件處理中擴展自己的業務邏輯.

 

一、定義一個MDB

 1 package mdb;
 2 
 3 
 4 
 5 import javax.ejb.ActivationConfigProperty;
 6 import javax.ejb.MessageDriven;
 7 import javax.jms.JMSException;
 8 import javax.jms.Message;
 9 import javax.jms.MessageListener;
10 import javax.jms.TextMessage;
11 
12 import util.LoggerUtil;
13 
14 @MessageDriven(name = "HelloWorldQueueMDB", activationConfig = {
15         @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
16         @ActivationConfigProperty(propertyName = "destination", propertyValue = "jms/queue/mytest"),
17         @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge") })
18 public class HelloWorldMDB implements MessageListener {
19 
20     @Override
21     public void onMessage(Message msg) {
22         TextMessage txtMsg = null;
23         try {
24             if (msg instanceof TextMessage) {
25                 txtMsg = (TextMessage) msg;
26                 String msgContent = txtMsg.getText();
27                 LoggerUtil.info("Received Message from queue: " + msgContent);
28             } else {
29                 LoggerUtil.warning("Message of wrong type: "
30                         + txtMsg.getClass().getName());
31             }
32         } catch (JMSException e) {
33             throw new RuntimeException(e);
34         }
35 
36     }
37 
38 }
HelloWorldMDB

注意該類上的注解,它表明了要監聽哪個Queue(可以參考上一篇的內容,先在jboss中建好該queue),其它沒什么特別的,把它放一個dynamic web中,打成war包部署到jboss上,為演示效果,部署后,先不啟動該應用

附:pom.xml文件的內容

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 
 3 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 5     <modelVersion>4.0.0</modelVersion>
 6 
 7     <groupId>cnblogs</groupId>
 8     <artifactId>helloworld-mdb</artifactId>
 9     <version>0.0.1-SNAPSHOT</version>
10     <packaging>war</packaging>
11     <name>helloworld-mdb</name>
12 
13     <dependencyManagement>
14         <dependencies>
15             <dependency>
16                 <groupId>org.jboss.bom</groupId>
17                 <artifactId>jboss-javaee-6.0-with-tools</artifactId>
18                 <version>1.0.7.Final</version>
19                 <type>pom</type>
20                 <scope>import</scope>
21             </dependency>
22         </dependencies>
23     </dependencyManagement>
24 
25     <dependencies>
26         <dependency>
27             <groupId>org.jboss.spec.javax.jms</groupId>
28             <artifactId>jboss-jms-api_1.1_spec</artifactId>
29             <scope>provided</scope>
30         </dependency>
31         <dependency>
32             <groupId>org.jboss.spec.javax.ejb</groupId>
33             <artifactId>jboss-ejb-api_3.1_spec</artifactId>
34             <scope>provided</scope>
35         </dependency>
36     </dependencies>
37 
38 </project>
pom.xml

 

二、測試驗證

a) 可以參考上一篇JMS的內容,另建一個常規的project,向該隊列發送消息(注意:僅發送,不要接收,否則消息被收走了,MDB就收不到消息了)

 1 package jms;
 2 
 3 
 4 import java.util.Hashtable;
 5 
 6 import javax.jms.Connection;
 7 import javax.jms.ConnectionFactory;
 8 import javax.jms.Destination;
 9 import javax.jms.JMSException;
10 import javax.jms.MessageConsumer;
11 import javax.jms.MessageProducer;
12 import javax.jms.Session;
13 import javax.jms.TextMessage;
14 import javax.naming.Context;
15 import javax.naming.InitialContext;
16 import javax.naming.NamingException;
17 
18 public class App {
19 
20     public static void main(String[] args) throws NamingException, JMSException {
21 
22         final String lOOKUP_CONNECTION_FACTORY_NAME = "lookup.connectionfactory.name";
23         final String lOOKUP_DESTINATION_NAME = "lookup.destination.name";
24 
25         ConnectionFactory connectionFactory = null;
26         Connection connection = null;
27         Session session = null;
28         MessageProducer producer = null;
29         MessageConsumer consumer = null;
30         Destination destination = null;
31         TextMessage message = null;
32         Context context = null;
33 
34         try {
35             // 創建上下文(默認會從應用的classpath下加載jndi.properties做為環境參數)
36             context = new InitialContext();
37 
38             // 把環境參數取出來,后面會用到
39             Hashtable<String, String> env = (Hashtable<String, String>) context
40                     .getEnvironment();
41 
42             // 查找連接工廠
43             connectionFactory = (ConnectionFactory) context.lookup(env
44                     .get(lOOKUP_CONNECTION_FACTORY_NAME));
45 
46             // 查找目標隊列
47             destination = (Destination) context.lookup(env
48                     .get(lOOKUP_DESTINATION_NAME));
49 
50             // 創建連接
51             connection = connectionFactory.createConnection(
52                     env.get(Context.SECURITY_PRINCIPAL),
53                     env.get(Context.SECURITY_CREDENTIALS));
54 
55             // 創建會話
56             session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
57 
58             // 創建生產者(即發送者)
59             producer = session.createProducer(destination);
60 
61             // 創建消費者(即接收者)
62             consumer = session.createConsumer(destination);
63 
64             // 開始連接
65             connection.start();
66 
67             // 發送消息
68 
69             message = session.createTextMessage("HELLO,I AM GLAD TO SEE YOU!");
70 
71             producer.send(message);
72 
73             System.out.println("發送成功!");
74 
75     
76 
77         } catch (NamingException e) {
78             e.printStackTrace();
79         } catch (JMSException e) {
80             e.printStackTrace();
81         } finally {
82             // 釋放資源
83             if (context != null) {
84                 context.close();
85             }
86 
87             if (connection != null) {
88                 connection.close();
89             }
90 
91         }
92     }
93 
94 }
Send Message

b) 然后在jboss中,再把該應用啟用起來,觀察console窗口的輸出:

點擊查看原圖

 

三、xml方式配置MDB

剛才我們是用注解方式來配置MDB的,這種方式不需要xml配置文件,十分方便,但是也有缺點,配置與代碼緊耦合,如果以后要修改queue名稱,就得改代碼,重新編譯,所以jboss也提供了xml配置方式

方法:在META-INF(非web項目)或WEB-INF(web項目)放置一個名為jboss-ejb3.xml(這是固定名稱,不要修改!)

內容參考下面這樣:

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <jboss:ejb-jar xmlns:jboss="http://www.jboss.com/xml/ns/javaee"
 3     xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4     xmlns:c="urn:clustering:1.0"
 5     xsi:schemaLocation="http://www.jboss.com/xml/ns/javaee http://www.jboss.org/j2ee/schema/jboss-ejb3-2_0.xsd http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_1.xsd"
 6     version="3.1" impl-version="2.0">
 7     <enterprise-beans>
 8         <message-driven>
 9             <ejb-name>HelloWorldQueueMDB</ejb-name>
10             <ejb-class>mdb.HelloWorldMDB</ejb-class>
11             <activation-config>
12                 <activation-config-property>
13                     <activation-config-property-name>destinationType</activation-config-property-name>
14                     <activation-config-property-value>javax.jms.Queue</activation-config-property-value>
15                 </activation-config-property>
16                 <activation-config-property>
17                     <activation-config-property-name>destination</activation-config-property-name>
18                     <activation-config-property-value>jms/queue/mytest</activation-config-property-value>
19                 </activation-config-property>
20                 <activation-config-property>
21                     <activation-config-property-name>acknowledgeMode</activation-config-property-name>
22                     <activation-config-property-value>Auto-acknowledge</activation-config-property-value>
23                 </activation-config-property>
24             </activation-config>
25         </message-driven>
26     </enterprise-beans>
27     <assembly-descriptor>
28         <c:clustering>
29             <ejb-name>DDBasedClusteredSFSB</ejb-name>
30             <c:clustered>true</c:clustered>
31         </c:clustering>
32     </assembly-descriptor>
33 </jboss:ejb-jar>
jboss-ejb3.xml

然后把HelloWorldQueueMDB類上的那一堆注解全注釋掉,再跑下,順利的話,也同樣可以接收消息

示例源代碼下載:mdb-sample.zip


文章列表




Avast logo

Avast 防毒軟體已檢查此封電子郵件的病毒。
www.avast.com


arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()