上一篇已經知道了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 }
注意該類上的注解,它表明了要監聽哪個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>
二、測試驗證
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 }
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>
然后把HelloWorldQueueMDB類上的那一堆注解全注釋掉,再跑下,順利的話,也同樣可以接收消息
示例源代碼下載:mdb-sample.zip
文章列表