- 浏览: 303947 次
- 性别:
- 来自: 上海
文章分类
- 全部博客 (167)
- <HTML and JavaScript and CSS> (6)
- 《Java2 基础知识及概念》 (3)
- Java2 Tools及其他 (11)
- EJB2.0 相关 (3)
- 英语学习 (4)
- Oracle Database Server (27)
- 计算机理论 (9)
- Java持久层框架 (2)
- 《Linux操作系统》 (24)
- 杂项技术 (4)
- Application Server (15)
- Windows操作系统 (7)
- Java中间件 (6)
- 娱乐生活 (4)
- 《Java设计模式》 (3)
- 《Interview Skill》 (1)
- 《Struts原理及应用》 (1)
- Workflow (2)
- 云计算 (3)
- 项目实践 (3)
- WEB相关技术 (10)
- JavaScript技巧及应用 (1)
最新评论
1. JMS基本概念
JMS(Java Message Service) 即Java消息服务。它提供标准的产生、发送、接收消息的接口简化企业应用的开发。它支持两种消息通信模型:点到点(point-to-point)(P2P)模型和发布/订阅(Pub/Sub)模型。P2P模型规定了一个消息只能有一个接收者;Pub/Sub 模型允许一个消息可以有多个接收者。
对于点到点模型,消息生产者产生一个消息后,把这个消息发送到一个Queue(队列)中,然后消息接收者再从这个Queue中读取,一旦这个消息被一个接收者读取之后,它就在这个Queue中消失了,所以一个消息只能被一个接收者消费。与点到点模型不同,发布/订阅模型中,消息生产者产生一个消息后,把这个消息发送到一个Topic中,这个Topic可以同时有多个接收者在监听,当一个消息到达这个Topic之后,所有消息接收者都会收到这个消息。
几个重要概念
Destination:消息发送的目的地,也就是前面说的Queue和Topic。创建好一个消息之后,只需要把这个消息发送到目的地,消息的发送者就可以继续做自己的事情,而不用等待消息被处理完成。至于这个消息什么时候,会被哪个消费者消费,完全取决于消息的接受者。
Message:从字面上就可以看出是被发送的消息。它有下面几种类型:
StreamMessage:Java 数据流消息,用标准流操作来顺序的填充和读取。
MapMessage:一个Map类型的消息;名称为 string 类型,而值为 Java 的基本类型。
TextMessage:普通字符串消息,包含一个String。
ObjectMessage:对象消息,包含一个可序列化的Java 对象
BytesMessage:二进制数组消息,包含一个byte[]。
XMLMessage: 一个XML类型的消息。
最常用的是TextMessage和ObjectMessage。
Session:与JMS提供者所建立的会话,通过Session我们才可以创建一个Message。
Connection:与JMS提供者建立的一个连接。可以从这个连接创建一个会话,即Session。
ConnectionFactory:那如何创建一个Connection呢?这就需要下面讲到的ConnectionFactory了。通过这个工厂类就可以得到一个与JMS提供者的连接,即Conection。
Producer:消息的生产者,要发送一个消息,必须通过这个生产者来发送。
MessageConsumer:与生产者相对应,这是消息的消费者或接收者,通过它来接收一个消息。
前面多次提到JMS提供者,因为JMS给我们提供的只是一系列接口,当我们使用一个JMS的时候,还是需要一个第三方的提供者,它的作用就是真正管理这些Connection,Session,Topic和Queue等。
通过下面这个简图可以看出上面这些概念的关系。
ConnectionFactory---->Connection--->Session--->Message
Destination + Session------------------------------------>Producer
Destination + Session------------------------------------>MessageConsumer
那么可能有人会问: ConnectionFactory和Destination 从哪儿得到? 这就和JMS提供者有关了. 如果在一个JavaEE环境中, 可以通过JNDI查找得到, 如果在一个非JavaEE环境中, 那只能通过JMS提供者提供给我们的接口得到了.
2. 一个JMS的例子
首先需要做的是选择一个JMS提供者, 如果在JavaEE环境中可以不用考虑这些. 我们选择ActiveMQ, 官方地址:
http://activemq.apache.org/.
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(user, password, url);
url: tcp://10.104.46.119:61616
import org.apache.activemq.ActiveMQConnectionFactory; import org.apache.activemq.command.ActiveMQQueue; import javax.jms.Connection; import javax.jms.ConnectionFactory; import javax.jms.Message; import javax.jms.MessageConsumer; import javax.jms.MessageProducer; import javax.jms.Queue; import javax.jms.Session; import javax.jms.TextMessage; public class MessageSendAndReceive { public static void main(String[] args) throws Exception { ConnectionFactory factory = new ActiveMQConnectionFactory("vm://localhost"); Connection connection = factory.createConnection(); connection.start(); Queue queue = new ActiveMQQueue("testQueue"); final Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); Message message = session.createTextMessage("Hello JMS!"); MessageProducer producer = session.createProducer(queue);
producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT); producer.send(message); System.out.println("Send Message Completed!"); MessageConsumer comsumer = session.createConsumer(queue); Message recvMessage = comsumer.receive(); System.out.println(((TextMessage) recvMessage).getText()); } }
// 关闭连接 public void close() throws JMSException { System.out.println("Producer:->Closing connection"); if (producer != null) producer.close(); if (session != null) session.close(); if (connection != null) connection.close(); }
3. MessageListener
消息的消费者接收消息可以采用两种方式:
1、consumer.receive() 或 consumer.receive(int timeout);
MessageConsumer comsumer = session.createConsumer(queue); connection.start(); for (int i = 0; i < 1; i++) { Message recvMessage = comsumer.receive(); System.out.println(((TextMessage) recvMessage).getText()); }
2、注册一个MessageListener。
采用第一种方式,消息的接收者会一直等待下去,直到有消息到达,或者超时。后一种方式会注册一个监听器,当有消息到达的时候,会回调它的onMessage()方法。
MessageConsumer comsumer = session.createConsumer(queue); comsumer.setMessageListener(new MessageListener(){ @Override public void onMessage(Message m) { TextMessage textMsg = (TextMessage) m; try { System.out.println(textMsg.getText()); } catch (JMSException e) { e.printStackTrace(); } } });
4. 实战Queue
Queue实现的是点到点模型,在下面的例子中,启动2个消费者共同监听一个Queue,然后循环给这个Queue中发送多个消息,我们依然采用ActiveMQ。
import org.apache.activemq.ActiveMQConnectionFactory; import org.apache.activemq.command.ActiveMQQueue; import javax.jms.Connection; import javax.jms.JMSException; import javax.jms.Message; import javax.jms.MessageConsumer; import javax.jms.MessageListener; import javax.jms.MessageProducer; import javax.jms.Queue; import javax.jms.Session; import javax.jms.TextMessage; public class QueueTest { public static void main(String[] args) throws Exception { ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("vm://localhost"); Connection connection = factory.createConnection(); connection.start(); //创建一个Queue Queue queue = new ActiveMQQueue("testQueue"); //创建一个Session Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); //注册消费者1 MessageConsumer comsumer1 = session.createConsumer(queue); comsumer1.setMessageListener( new MessageListener() { public void onMessage(Message m) { try { System.out.println("Consumer1 get " + ((TextMessage) m).getText()); } catch (JMSException e) { e.printStackTrace(); } } }); //注册消费者2 MessageConsumer comsumer2 = session.createConsumer(queue); comsumer2.setMessageListener( new MessageListener() { public void onMessage(Message m) { try { System.out.println("Consumer2 get " + ((TextMessage) m).getText()); } catch (JMSException e) { e.printStackTrace(); } } }); //创建一个生产者,然后发送多个消息。 MessageProducer producer = session.createProducer(queue); for (int i = 0; i < 10; i++) { producer.send(session.createTextMessage("Message:" + i)); } } }
运行这个例子会得到下面的输出结果:
Consumer1 get Message:0
Consumer2 get Message:1
Consumer1 get Message:2
Consumer2 get Message:3
Consumer1 get Message:4
Consumer2 get Message:5
Consumer1 get Message:6
Consumer2 get Message:7
Consumer1 get Message:8
Consumer2 get Message:9
可以看出每个消息直被消费了一次,但是如果有多个消费者同时监听一个Queue的话,无法确定一个消息最终会被哪一个消费者消费。
5. 实战Topic
与Queue不同的是,Topic实现的是发布/订阅模型,在下面的例子中,启动2个消费者共同监听一个Topic,然后循环给这个Topic中发送多个消息。
import org.apache.activemq.ActiveMQConnectionFactory; import org.apache.activemq.command.ActiveMQTopic; import javax.jms.Connection; import javax.jms.JMSException; import javax.jms.Message; import javax.jms.MessageConsumer; import javax.jms.MessageListener; import javax.jms.MessageProducer; import javax.jms.Session; import javax.jms.TextMessage; import javax.jms.Topic; public class TopicTest { public static void main(String[] args) throws Exception { ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("vm://localhost"); Connection connection = factory.createConnection(); connection.start(); //创建一个Topic Topic topic = new ActiveMQTopic("testTopic"); Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); //注册消费者1 MessageConsumer comsumer1 = session.createConsumer(topic); comsumer1.setMessageListener( new MessageListener() { public void onMessage(Message m) { try { System.out.println("Consumer1 get " + ((TextMessage) m).getText()); } catch (JMSException e) { e.printStackTrace(); } } }); //注册消费者2 MessageConsumer comsumer2 = session.createConsumer(topic); comsumer2.setMessageListener( new MessageListener() { public void onMessage(Message m) { try { System.out.println("Consumer2 get " + ((TextMessage) m).getText()); } catch (JMSException e) { e.printStackTrace(); } } }); //创建一个生产者,然后发送多个消息。 MessageProducer producer = session.createProducer(topic); for (int i = 0; i < 10; i++) { producer.send(session.createTextMessage("Message:" + i)); } } }
运行后得到下面的输出结果:
Consumer1 get Message:0
Consumer2 get Message:0
Consumer1 get Message:1
Consumer2 get Message:1
Consumer1 get Message:2
Consumer2 get Message:2
Consumer1 get Message:3
Consumer2 get Message:3
Consumer1 get Message:4
Consumer2 get Message:4
Consumer1 get Message:5
Consumer2 get Message:5
Consumer1 get Message:6
Consumer2 get Message:6
Consumer1 get Message:7
Consumer2 get Message:7
Consumer1 get Message:8
Consumer2 get Message:8
Consumer1 get Message:9
Consumer2 get Message:9
6. 消息头
一个消息对象分为三部分:消息头(Headers),属性(Properties)和消息体(Payload)。对于StreamMessage和MapMessage,消息本身就有特定的结构,而对于TextMessage,ObjectMessage和BytesMessage是无结构的。一个消息可以包含一些重要的数据或者仅仅是一个事件的通知。
消息的Headers部分通常包含一些消息的描述信息,它们都是标准的描述信息。包含下面一些值:
JMSDestination
消息的目的地,Topic或者是Queue。
JMSDeliveryMode
消息的发送模式:persistent或nonpersistent。前者表示消息在被消费之前,如果JMS提供者DOWN了,重新启动后消息仍然存在。后者在这种情况下表示消息会被丢失。可以通过下面的方式设置:
Producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
JMSTimestamp
当调用send()方法的时候,JMSTimestamp会被自动设置为当前事件。可以通过下面方式得到这个值:
long timestamp = message.getJMSTimestamp();
JMSExpiration
表示一个消息的有效期。只有在这个有效期内,消息消费者才可以消费这个消息。默认值为0,表示消息永不过期。可以通过下面的方式设置:
producer.setTimeToLive(3600000); //有效期1小时 (1000毫秒 * 60秒 * 60分)
JMSPriority
消息的优先级。0-4为正常的优先级,5-9为高优先级。可以通过下面方式设置:
producer.setPriority(9);
JMSMessageID
一个字符串用来唯一标示一个消息。
JMSReplyTo
有时消息生产者希望消费者回复一个消息,JMSReplyTo为一个Destination,表示需要回复的目的地。当然消费者可以不理会它。
JMSCorrelationID
通常用来关联多个Message。例如需要回复一个消息,可以把JMSCorrelationID设置为所收到的消息的JMSMessageID。
JMSType
表示消息体的结构,和JMS提供者有关。
JMSRedelivered
如果这个值为true,表示消息是被重新发送了。因为有时消费者没有确认他已经收到消息或者JMS提供者不确定消费者是否已经收到。
除了Header,消息发送者可以添加一些属性(Properties)。这些属性可以是应用自定义的属性,JMS定义的属性和JMS提供者定义的属性。我们通常只适用自定义的属性。
后面会讲到这些Header和属性的用法。
7. DeliveryMode例子
在下面的例子中,分别发送一个Persistent和nonpersistent的消息,然后关闭退出JMS。
import org.apache.activemq.ActiveMQConnectionFactory; import org.apache.activemq.command.ActiveMQQueue; import javax.jms.Connection; import javax.jms.DeliveryMode; import javax.jms.MessageProducer; import javax.jms.Queue; import javax.jms.Session; public class DeliveryModeSendTest { public static void main(String[] args) throws Exception { ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("vm://localhost"); Connection connection = factory.createConnection(); connection.start(); Queue queue = new ActiveMQQueue("testQueue"); Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); MessageProducer producer = session.createProducer(queue); producer.setDeliveryMode(DeliveryMode.PERSISTENT); producer.send(session.createTextMessage("A persistent Message")); producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT); producer.send(session.createTextMessage("A non persistent Message")); System.out.println("Send messages sucessfully!"); } }
运行上面的程序,当输出“Send messages sucessfully!”时,说明两个消息都已经发送成功,然后我们结束它,来停止JMS Provider。
接下来我们重新启动JMS Provicer,然后添加一个消费者:
import org.apache.activemq.ActiveMQConnectionFactory; import org.apache.activemq.command.ActiveMQQueue; import javax.jms.Connection; import javax.jms.JMSException; import javax.jms.Message; import javax.jms.MessageConsumer; import javax.jms.MessageListener; import javax.jms.Queue; import javax.jms.Session; import javax.jms.TextMessage; public class DeliveryModeReceiveTest { public static void main(String[] args) throws Exception { ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("vm://localhost"); Connection connection = factory.createConnection(); connection.start(); Queue queue = new ActiveMQQueue("testQueue"); Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); MessageConsumer comsumer = session.createConsumer(queue); comsumer.setMessageListener( new MessageListener() { public void onMessage(Message m) { try { System.out.println("Consumer get " + ((TextMessage) m).getText()); } catch (JMSException e) { e.printStackTrace(); } } }); } }
运行上面的程序,可以得到下面的输出结果:
Consumer get A persistent Message
可以看出消息消费者只接收到一个消息,它是一个Persistent的消息。而刚才发送的non persistent消息已经丢失了。
另外, 如果发送一个non persistent消息, 而刚好这个时候没有消费者在监听, 这个消息也会丢失
8. JMSReplyTo
在下面的例子中,首先创建两个Queue,发送者给一个Queue发送,接收者接收到消息之后给另一个Queue回复一个Message,然后再创建一个消费者来接受所回复的消息。
import org.apache.activemq.ActiveMQConnectionFactory; import org.apache.activemq.command.ActiveMQQueue; import javax.jms.Connection; import javax.jms.JMSException; import javax.jms.Message; import javax.jms.MessageConsumer; import javax.jms.MessageListener; import javax.jms.MessageProducer; import javax.jms.Queue; import javax.jms.Session; import javax.jms.TextMessage; public class MessageSendReceiveAndReply { public static void main(String[] args) throws Exception { ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("vm://localhost"); Connection connection = factory.createConnection(); connection.start(); //消息发送到这个Queue Queue queue = new ActiveMQQueue("testQueue"); //消息回复到这个Queue Queue replyQueue = new ActiveMQQueue("replyQueue"); final Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); //创建一个消息,并设置它的JMSReplyTo为replyQueue。 Message message = session.createTextMessage("Andy"); message.setJMSReplyTo(replyQueue); MessageProducer producer = session.createProducer(queue); producer.send(message); //消息的接收者 MessageConsumer comsumer = session.createConsumer(queue); comsumer.setMessageListener( new MessageListener() { public void onMessage(Message m) { try { //创建一个新的MessageProducer来发送一个回复消息。 MessageProducer producer = session.createProducer(m.getJMSReplyTo()); producer.send(session.createTextMessage("Hello " + ((TextMessage) m).getText())); } catch (JMSException e1) { e1.printStackTrace(); } } }); //这个接收者用来接收回复的消息 MessageConsumer comsumer2 = session.createConsumer(replyQueue); comsumer2.setMessageListener( new MessageListener() { public void onMessage(Message m) { try { System.out.println(((TextMessage) m).getText()); } catch (JMSException e) { e.printStackTrace(); } } }); } }
首先消息生产者发送一个消息,内容为“Andy”, 然后消费者收到这个消息之后根据消息的JMSReplyTo,回复一个消息,内容为“Hello Andy‘。 最后在回复的Queue上创建一个接收回复消息的消费者,它输出所回复的内容。
运行上面的程序,可以得到下面的输出结果:
Hello Andy
9. Selector
前面的例子中创建一个消息消费者使用的是:
sesssion.createConsumer(destination)
另外,还提供了另一种方式:
sesssion.createConsumer(destination, selector)
这里selector是一个字符串,用来过滤消息。也就是说,这种方式可以创建一个可以只接收特定消息的一个消费者。Selector的格式是类似于SQL-92的一种语法。可以用来比较消息头信息和属性。
下面的例子中,创建两个消费者,共同监听同一个Queue,但是它们的Selector不同,然后创建一个消息生产者,来发送多个消息。
import org.apache.activemq.ActiveMQConnectionFactory; import org.apache.activemq.command.ActiveMQQueue; import javax.jms.Connection; import javax.jms.JMSException; import javax.jms.Message; import javax.jms.MessageConsumer; import javax.jms.MessageListener; import javax.jms.MessageProducer; import javax.jms.Queue; import javax.jms.Session; import javax.jms.TextMessage; public class JMSSelectorTest { public static void main(String[] args) throws Exception { ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("vm://localhost"); Connection connection = factory.createConnection(); connection.start(); Queue queue = new ActiveMQQueue("testQueue"); Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); MessageConsumer comsumerA = session.createConsumer(queue, "receiver = 'A'"); comsumerA.setMessageListener( new MessageListener() { public void onMessage(Message m) { try { System.out.println("ConsumerA get " + ((TextMessage) m).getText()); } catch (JMSException e1) { } } }); MessageConsumer comsumerB = session.createConsumer(queue, "receiver = 'B'"); comsumerB.setMessageListener( new MessageListener() { public void onMessage(Message m) { try { System.out.println("ConsumerB get " + ((TextMessage) m).getText()); } catch (JMSException e) { } } }); MessageProducer producer = session.createProducer(queue); for (int i = 0; i < 10; i++) { String receiver = (i % 3 == 0 ? "A" : "B"); TextMessage message = session.createTextMessage("Message" + i + ", receiver:" + receiver); message.setStringProperty("receiver", receiver); producer.send(message); } } }
10. JMSCorrelationID与Selector
前面讲过JMSCorrelationID主要是用来关联多个Message,例如需要回复一个消息的时候,通常把回复的消息的JMSCorrelationID设置为原来消息的ID。在下面这个例子中,创建了三个消息生产者A,B,C和三个消息消费者A,B,C。生产者A给消费者A发送一个消息,同时需要消费者A给它回复一个消息。B、C与A类似。
简图如下:
生产者A-----发送----〉消费者A-----回复------〉生产者A
生产者B-----发送----〉消费者B-----回复------〉生产者B
生产者C-----发送----〉消费者C-----回复------〉生产者C
需要注意的是,所有的发送和回复都使用同一个Queue,通过Selector区分。
import org.apache.activemq.ActiveMQConnectionFactory; import org.apache.activemq.command.ActiveMQQueue; import javax.jms.Connection; import javax.jms.DeliveryMode; import javax.jms.JMSException; import javax.jms.Message; import javax.jms.MessageConsumer; import javax.jms.MessageListener; import javax.jms.MessageProducer; import javax.jms.Queue; import javax.jms.Session; import javax.jms.TextMessage; public class JMSCorrelationIDTest { private Queue queue; private Session session; public JMSCorrelationIDTest() throws JMSException { ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("vm://localhost"); Connection connection = factory.createConnection(); connection.start(); queue = new ActiveMQQueue("testQueue"); session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); setupConsumer("ConsumerA"); setupConsumer("ConsumerB"); setupConsumer("ConsumerC"); setupProducer("ProducerA", "ConsumerA"); setupProducer("ProducerB", "ConsumerB"); setupProducer("ProducerC", "ConsumerC"); } private void setupConsumer(final String name) throws JMSException { //创建一个消费者,它只接受属于它自己的消息 MessageConsumer consumer = session.createConsumer(queue, "receiver='" + name + "'"); consumer.setMessageListener( new MessageListener() { public void onMessage(Message m) { try { MessageProducer producer = session.createProducer(queue); System.out.println(name + " get:" + ((TextMessage) m).getText()); //回复一个消息 Message replyMessage = session.createTextMessage("Reply from " + name); //设置JMSCorrelationID为刚才收到的消息的ID replyMessage.setJMSCorrelationID(m.getJMSMessageID()); producer.send(replyMessage); } catch (JMSException e) { } } }); } private void setupProducer(final String name, String consumerName) throws JMSException { MessageProducer producer = session.createProducer(queue); producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT); //创建一个消息,并设置一个属性receiver,为消费者的名字。 Message message = session.createTextMessage("Message from " + name); message.setStringProperty("receiver", consumerName); producer.send(message); //等待回复的消息 MessageConsumer replyConsumer = session.createConsumer(queue, "JMSCorrelationID='" + message.getJMSMessageID() + "'"); replyConsumer.setMessageListener( new MessageListener() { public void onMessage(Message m) { try { System.out.println(name + " get reply:" + ((TextMessage) m).getText()); } catch (JMSException e) { } } }); } public static void main(String[] args) throws Exception { new JMSCorrelationIDTest(); } }
运行结果为:
ConsumerA get:Message from ProducerA
ProducerA get reply:Reply from ConsumerA
ConsumerB get:Message from ProducerB
ProducerB get reply:Reply from ConsumerB
ConsumerC get:Message from ProducerC
ProducerC get reply:Reply from ConsumerC
11. TemporaryQueue和TemporaryTopic
TemporaryQueue和TemporaryTopic,从字面上就可以看出它们是“临时”的目的地。可以通过Session来创建,例如:
TemporaryQueue replyQueue = session.createTemporaryQueue();
虽然它们是由Session来创建的,但是它们的生命周期确实整个Connection。如果在一个Connection上创建了两个Session,则一个Session创建的TemporaryQueue或TemporaryTopic也可以被另一个Session访问。那如果这两个Session是由不同的Connection创建,则一个Session创建的TemporaryQueue不可以被另一个Session访问。
另外,它们的主要作用就是用来指定回复目的地, 即作为JMSReplyTo。
在下面的例子中,先创建一个Connection,然后创建两个Session,其中一个Session创建了一个TemporaryQueue,另一个Session在这个TemporaryQueue上读取消息。
import org.apache.activemq.ActiveMQConnectionFactory; import org.apache.activemq.command.ActiveMQQueue; import javax.jms.Connection; import javax.jms.JMSException; import javax.jms.Message; import javax.jms.MessageConsumer; import javax.jms.MessageListener; import javax.jms.MessageProducer; import javax.jms.Queue; import javax.jms.Session; import javax.jms.TemporaryQueue; import javax.jms.TextMessage; public class TemporaryQueueTest { public static void main(String[] args) throws Exception { ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("vm://localhost"); Connection connection = factory.createConnection(); connection.start(); Queue queue = new ActiveMQQueue("testQueue2"); final Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); //使用session创建一个TemporaryQueue。 TemporaryQueue replyQueue = session.createTemporaryQueue(); //接收消息,并回复到指定的Queue中(即replyQueue) MessageConsumer comsumer = session.createConsumer(queue); comsumer.setMessageListener( new MessageListener() { public void onMessage(Message m) { try { System.out.println("Get Message: " + ((TextMessage) m).getText()); MessageProducer producer = session.createProducer(m.getJMSReplyTo()); producer.send(session.createTextMessage("ReplyMessage")); } catch (JMSException e) { } } }); //使用同一个Connection创建另一个Session,来读取replyQueue上的消息。 Session session2 = connection.createSession(true, Session.AUTO_ACKNOWLEDGE); MessageConsumer replyComsumer = session2.createConsumer(replyQueue); replyComsumer.setMessageListener( new MessageListener() { public void onMessage(Message m) { try { System.out.println("Get reply: " + ((TextMessage) m).getText()); } catch (JMSException e) { } } }); MessageProducer producer = session.createProducer(queue); TextMessage message = session.createTextMessage("SimpleMessage"); message.setJMSReplyTo(replyQueue); producer.send(message); } }
运行结果为:
Get Message: SimpleMessage
Get reply: ReplyMessage
如果将:
Session session2 = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
更改为:
Connection connection2 = factory.createConnection();
Session session2 = connection2.createSession(true, Session.AUTO_ACKNOWLEDGE);
就会得到类似于下面的异常:
Exception in thread "main" javax.jms.InvalidDestinationException: Cannot use a Temporary destination from another Connection。
12. MDB
在EJB3中,一个MDB(消息驱动Bean)就是一个实现了MessageListener接口的POJO。下面就是一个简单的MDB。
@MessageDriven(activationConfig={ @ActivationConfigProperty(propertyName="destinationType", propertyValue="javax.jms.Queue"), @ActivationConfigProperty(propertyName="destination", propertyValue="queue/testQueue")}) public class SimpleMDB implements MessageListener { public void onMessage(Message message) { try { System.out.println("Receive Message : " + ((TextMessage)message).getText()); } catch (JMSException e) { e.printStackTrace(); } } }
@MessageDriven(mappedName = "Test-Topic", activationConfig = { // @ActivationConfigProperty(propertyName = "MessageType", // propertyValue = "INTF"), @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"), @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue") }) @TransactionManagement(TransactionManagementType.BEAN)
它要求必须标注为@MessageDriven。它所监听Destination通过标注属性来注入。
下面是一个发送消息的StatelessBean:
@Remote public interface IMessageSender { public void sendMessage(String content) throws Exception; } @Stateless @Remote public class MessageSender implements IMessageSender { @Resource(mappedName="ConnectionFactory") private ConnectionFactory factory; @Resource(mappedName="queue/testQueue") private Queue queue; public void sendMessage(String content) throws Exception { Connection cn = factory.createConnection(); Session session = cn.createSession(false, Session.AUTO_ACKNOWLEDGE); MessageProducer producer = session.createProducer(queue); producer.send(session.createTextMessage(content)); } }
这个EJB只有一个方法SendMessage。ConnectionFactory和Queue通过标注注入。
接下来是客户端:
public class MessageSenderClient { public static void main(String[] args) throws Exception { Properties props = new Properties(); props.setProperty(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory"); props.setProperty(Context.PROVIDER_URL, "localhost:2099"); Context context = new InitialContext(props); IMessageSender messageSender = (IMessageSender) context.lookup("MessageSender/remote"); messageSender.sendMessage("Hello"); } }
它通过JNDI查找到上面的EJB,然后调用sengMessage.
发表评论
文章已被作者锁定,不允许评论。
-
Weblogic集群概念和配置
2010-08-10 15:26 2126Domain定义一Domain是WebLogi ... -
《J2EE集群原理》
2010-08-09 14:01 1284原文出自 http://www.theserverside ... -
WEBLOGIC中JMS收发消息
2010-07-30 17:47 1269一个 JMS 应用程序由下列元素组成: · JMS 客户机。 ... -
Weblogic环境下JMS配置
2010-07-30 17:39 800Weblogic环境下JMS配置 参见附件 -
JMS五种消息的发送/接收的例子
2010-07-29 21:10 12371、消息发送 //连接工厂 ConnectionFa ...
相关推荐
### 深入掌握 JMS(Java Message Service) #### JMS 基础概念 - **JMS**(Java Message Service)是一种Java平台中的消息中间件技术标准,它定义了一套标准API,用于应用程序之间的消息传递。JMS的出现极大地简化...
JMS(Java Message Service) 即Java消息服务。它提供标准的产生、发送、接收消息的接口简化企业应用的开发。本资源为chm格式,深入介绍了ActiveMQ的应用。
接着,**《深入掌握JMS》** 进一步探讨了JMS的高级特性,如消息选择器、消息组、消息优先级以及事务管理。这部分内容有助于读者解决更复杂的消息处理需求,例如实现特定条件的消息过滤,或者确保消息的有序处理。 *...
《Java消息服务(JMS)1.0.2更新示例程序详解》 Java消息服务(Java Message Service,简称JMS)是Java平台中...无论你是初学者还是经验丰富的开发者,这些示例都提供了宝贵的实践经验,帮助你深入掌握JMS的核心概念。
总的来说,"JMS的Oreilly示例代码"是一个宝贵的资源,它不仅帮助你理解JMS的基本概念,还能让你通过实践深入掌握JMS的使用,提升你在分布式系统中进行消息通信的能力。通过学习和分析这些代码,你可以更好地应用JMS...
《深入掌握J2EE编程技术》是一本专为Java企业级开发人员精心编写的指南,旨在帮助读者全面理解和精通J2EE(Java Platform, Enterprise Edition)的各项核心技术。免积分下载的特点使得更多的开发者能够轻松获取这份...
《深入掌握J2EE编程技术》全面介绍了JSP层,EJB层和EIS层的设计思想与编程技术,涉及的内容包括:JDBC,JNDI,LDAP,Servlet,JSP,Taglib,EJB,J2EE,Connector,SAX与DOM,RMI,CORBA,JavaMail和JMS。...
《JMS 1.1.jar:Java消息服务与Maven的深度解析》 在Java开发领域,消息服务(Java Message Service,简称JMS)扮演着至关重要的角色,它为...理解和掌握JMS原理及操作,对于提升Java应用的稳定性和扩展性至关重要。
在这个"JMS demo 及 资料"的压缩包中,我们可能找到了一些关于JMS的基础教程和示例代码,帮助初学者了解和掌握JMS的基本用法。 JMS的核心概念主要包括以下几个部分: 1. **消息**: 消息是JMS中的基本数据单元,它...
Java消息服务(Java Message Service,简称JMS...对于开发分布式、高并发的企业级应用,掌握JMS是必不可少的技能。同时,文档还可能涵盖了错误处理、性能优化、安全性和与其他技术(如JEE、Spring框架)的集成等内容。
总的来说,JMS是构建高可用、分布式系统的重要工具,理解和掌握JMS对于提升Java开发者在企业级应用开发中的能力至关重要。通过深入学习和实践,我们可以更好地利用JMS来解决复杂系统的异步通信问题。
#### 三、掌握JMS:核心概念与实践 - **JMS概述**:章节介绍了JMS的基本原理,包括点到点(P2P)和发布/订阅(Pub/Sub)两种消息模型,以及如何通过JMS与其他企业级Java API协同工作,如JNDI(Java命名和目录接口)...
在本文中,我们将深入探讨SpringJMS的基本概念、如何与ActiveMQ集成,以及如何通过示例代码理解其工作原理。 1. **SpringJMS简介** SpringJMS是Spring框架对JMS API的包装,它简化了生产者和消费者之间的消息通信...
**正文** JMS(Java Message ...本教程的目的是帮助开发者掌握JMS的使用,从而能够更好地设计和实现基于消息传递的应用程序。无论你是初学者还是有经验的开发者,都可以从这个中文版的JMS规范培训教程中受益匪浅。
1. **JMS、XML和异构企业--使用JMS和XML来促进企业应用的互操作性.doc** - 这份文档可能深入探讨了JMS如何与XML(可扩展标记语言)结合,以支持不同系统间的互操作性。XML常用于数据交换,因为它具有自我描述性和...
【JBOSST建立JMS应用实例】 JBOSST(Java Business Open Source ...通过实践这些步骤,开发者可以掌握如何在JBOSST环境中利用JMS进行高效的数据通信。同时,提供的文档和项目文件为深入理解和实践提供了丰富的资源。