1、activemq的几种基本通信方式总结ActiveMQ的几种基本通信方式总结简介 在前面一篇文章里讨论过几种应用系统集成的方式,发现实际上面向消息队列的集成方案算是一个总体比较合理的选择。这里,我们先针对具体的一个消息队列Activemq的基本通信方式进行探讨。activemq是JMS消息通信规范的一个实现。总的来说,消息规范里面定义最常见的几种消息通信模式主要有发布-订阅、点对点这两种。另外,通过结合这些模式的具体应用,我们在处理某些应用场景的时候也衍生出来了一种请求应答的模式。下面,我们针对这几种方式一一讨论一下。基础流程 在讨论具体方式的时候,我们先看看使用activemq需要启动服务的
2、主要过程。 按照JMS的规范,我们首先需要获得一个JMS connection factory.,通过这个connection factory来创建connection.在这个基础之上我们再创建session, destination, producer和consumer。因此主要的几个步骤如下:1. 获得JMS connection factory. 通过我们提供特定环境的连接信息来构造factory。2. 利用factory构造JMS connection3. 启动connection4. 通过connection创建JMS session.5. 指定JMS destination.6.
3、创建JMS producer或者创建JMS message并提供destination.7. 创建JMS consumer或注册JMS message listener.8. 发送和接收JMS message.9. 关闭所有JMS资源,包括connection, session, producer, consumer等。publish-subscribe 发布订阅模式有点类似于我们日常生活中订阅报纸。每年到年尾的时候,邮局就会发一本报纸集合让我们来选择订阅哪一个。在这个表里头列了所有出版发行的报纸,那么对于我们每一个订阅者来说,我们可以选择一份或者多份报纸。比如北京日报、潇湘晨报等。那么这些个
4、我们订阅的报纸,就相当于发布订阅模式里的topic。有很多个人订阅报纸,也有人可能和我订阅了相同的报纸。那么,在这里,相当于我们在同一个topic里注册了。对于一份报纸发行方来说,它和所有的订阅者就构成了一个1对多的关系。这种关系如下图所示: 现在,假定我们用前面讨论的场景来写一个简单的示例。我们首先需要定义的是publisher.publisher publisher是属于发布信息的一方,它通过定义一个或者多个topic,然后给这些topic发送消息。 publisher的构造函数如下:Java代码1. publicPublisher()throwsJMSException2. factor
5、y=newActiveMQConnectionFactory(brokerURL);3. connection=factory.createConnection();4. try5. connection.start();6. catch(JMSExceptionjmse)7. connection.close();8. throwjmse;9. 10. session=connection.createSession(false,Session.AUTO_ACKNOWLEDGE);11. producer=session.createProducer(null);12. 我们按照前面说的流程
6、定义了基本的connectionFactory, connection, session, producer。这里代码就是主要实现初始化的效果。 接着,我们需要定义一系列的topic让所有的consumer来订阅,设置topic的代码如下:Java代码1. protectedvoidsetTopics(Stringstocks)throwsJMSException2. destinations=newDestinationstocks.length;3. for(inti=0;istocks.length;i+)4. destinationsi=session.createTopic(STOC
7、KS.+stocksi);5. 6. 这里destinations是一个内部定义的成员变量Destination。这里我们总共定义了的topic数取决于给定的参数stocks。 在定义好topic之后我们要给这些指定的topic发消息,具体实现的代码如下:Java代码1. protectedvoidsendMessage(Stringstocks)throwsJMSException2. for(inti=0;istocks.length;i+)3. Messagemessage=createStockMessage(stocksi,session);4. System.out.println
8、(Sending:+(ActiveMQMapMessage)message).getContentMap()+ondestination:+destinationsi);5. producer.send(destinationsi,message);6. 7. 8. 9. protectedMessagecreateStockMessage(Stringstock,Sessionsession)throwsJMSException10. MapMessagemessage=session.createMapMessage();11. message.setString(stock,stock)
9、;12. message.setDouble(price,1.00);13. message.setDouble(offer,0.01);14. message.setBoolean(up,true);15. 16. returnmessage;17. 前面的代码很简单,在sendMessage方法里我们遍历每个topic,然后给每个topic发送定义的Message消息。 在定义好前面发送消息的基础之后,我们调用他们的代码就很简单了:Java代码1. publicstaticvoidmain(Stringargs)throwsJMSException2. if(args.length1)3.
10、 thrownewIllegalArgumentException();4. 5. /Createpublisher6. Publisherpublisher=newPublisher();7. 8. /Settopics9. publisher.setTopics(args);10. 11. for(inti=0;i10;i+)12. publisher.sendMessage(args);13. System.out.println(Publisher+i+pricemessages);14. try15. Thread.sleep(1000);16. catch(InterruptedE
11、xceptione)17. e.printStackTrace();18. 19. 20. /Closeallresources21. publisher.close();22. 调用他们的代码就是我们遍历所有topic,然后通过sendMessage发送消息。在发送一个消息之后先sleep1秒钟。要注意的一个地方就是我们使用完资源之后必须要使用close方法将这些资源关闭释放。close方法关闭资源的具体实现如下:Java代码1. publicvoidclose()throwsJMSException2. if(connection!=null)3. connection.close();4
12、. 5. consumer Consumer的代码也很类似,具体的步骤无非就是1.初始化资源。 2. 接收消息。 3. 必要的时候关闭资源。 初始化资源可以放到构造函数里面:Java代码1. publicConsumer()throwsJMSException2. factory=newActiveMQConnectionFactory(brokerURL);3. connection=factory.createConnection();4. connection.start();5. session=connection.createSession(false,Session.AUTO_A
13、CKNOWLEDGE);6. 接收和处理消息的方法有两种,分为同步和异步的,一般同步的方式我们是通过MessageConsumer.receive()方法来处理接收到的消息。而异步的方法则是通过注册一个MessageListener的方法,使用MessageConsumer.setMessageListener()。这里我们采用异步的方式实现:Java代码1. publicstaticvoidmain(Stringargs)throwsJMSException2. Consumerconsumer=newConsumer();3. for(Stringstock:args)4. Destina
14、tiondestination=consumer.getSession().createTopic(STOCKS.+stock);5. MessageConsumermessageConsumer=consumer.getSession().createConsumer(destination);6. messageConsumer.setMessageListener(newListener();7. 8. 9. 10. publicSessiongetSession()11. returnsession;12. 在前面的代码里我们先找到同样的topic,然后遍历所有的topic去获得消息。
15、对于消息的处理我们专门通过Listener对象来负责。 Listener对象的职责很简单,主要就是处理接收到的消息:Java代码1. publicclassListenerimplementsMessageListener2. 3. publicvoidonMessage(Messagemessage)4. try5. MapMessagemap=(MapMessage)message;6. Stringstock=map.getString(stock);7. doubleprice=map.getDouble(price);8. doubleoffer=map.getDouble(offe
16、r);9. booleanup=map.getBoolean(up);10. DecimalFormatdf=newDecimalFormat(#,#,#,#0.00);11. System.out.println(stock+t+df.format(price)+t+df.format(offer)+t+(up?up:down);12. catch(Exceptione)13. e.printStackTrace();14. 15. 16. 17. 它实现了MessageListener接口,里面的onMessage方法就是在接收到消息之后会被调用的方法。 现在,通过实现前面的publish
17、er和consumer我们已经实现了pub-sub模式的一个实例。仔细回想它的步骤的话,主要就是要两者设定一个共同的topic,有了这个topic之后他们可以实现一方发消息另外一方接收。另外,为了连接到具体的message server,这里是使用了连接tcp:/localhost:16161作为定义ActiveMQConnectionFactory的路径。在publisher端通过session创建producer,根据指定的参数创建destination,然后将消息和destination作为producer.send()方法的参数发消息。在consumer端也要创建类似的connecti
18、on, session。通过session得到destination,再通过session.createConsumer(destination)来得到一个MessageConsumer对象。有了这个MessageConsumer我们就可以自行选择是直接同步的receive消息还是注册listener了。p2p p2p的过程则理解起来更加简单。它好比是两个人打电话,这两个人是独享这一条通信链路的。一方发送消息,另外一方接收,就这么简单。在实际应用中因为有多个用户对使用p2p的链路,它的通信场景如下图所示: 我们再来看看一个p2p的示例: 在p2p的场景里,相互通信的双方是通过一个类似于队列的方
19、式来进行交流。和前面pub-sub的区别在于一个topic有一个发送者和多个接收者,而在p2p里一个queue只有一个发送者和一个接收者。发送者 和前面的示例非常相似,我们构造函数里需要初始化的内容基本上差不多:Java代码1. publicPublisher()throwsJMSException2. factory=newActiveMQConnectionFactory(brokerURL);3. connection=factory.createConnection();4. connection.start();5. session=connection.createSession(
20、false,Session.AUTO_ACKNOWLEDGE);6. producer=session.createProducer(null);7. 发送消息的方法如下:Java代码1. publicvoidsendMessage()throwsJMSException2. for(inti=0;ijobs.length;i+)3. 4. Stringjob=jobsi;5. Destinationdestination=session.createQueue(JOBS.+job);6. Messagemessage=session.createObjectMessage(i);7. Sys
21、tem.out.println(Sending:id:+(ObjectMessage)message).getObject()+onqueue:+destination);8. producer.send(destination,message);9. 10. 这里我们定义了一个jobs的数组,通过遍历这个数组来创建不同的job queue。这样就相当于建立了多个点对点通信的链路。 消息发送者的启动代码如下:Java代码1. publicstaticvoidmain(Stringargs)throwsJMSException2. Publisherpublisher=newPublisher(
22、);3. for(inti=0;i10;i+)4. publisher.sendMessage();5. System.out.println(Published+i+jobmessages);6. try7. Thread.sleep(1000);8. catch(InterruptedExceptionx)9. e.printStackTrace();10. 11. 12. publisher.close();13. 我们在这里发送10条消息,当然,在每个sendMessage的方法里实际上是针对每个queue发送了10条。接收者 接收者的代码很简单,一个构造函数初始化所有的资源:Java
23、代码1. publicConsumer()throwsJMSException2. factory=newActiveMQConnectionFactory(brokerURL);3. connection=factory.createConnection();4. connection.start();5. session=connection.createSession(false,Session.AUTO_ACKNOWLEDGE);6. 还有一个就是注册消息处理的对象:Java代码1. publicstaticvoidmain(Stringargs)throwsJMSException2
24、. Consumerconsumer=newConsumer();3. for(Stringjob:consumer.jobs)4. Destinationdestination=consumer.getSession().createQueue(JOBS.+job);5. MessageConsumermessageConsumer=consumer.getSession().createConsumer(destination);6. messageConsumer.setMessageListener(newListener(job);7. 8. 9. 10. publicSession
25、getSession()11. returnsession;12. 具体注册的对象处理方法和前面还是类似,实现MessageListener接口就可以了。Java代码1. importjavax.jms.Message;2. importjavax.jms.MessageListener;3. importjavax.jms.ObjectMessage;4. 5. publicclassListenerimplementsMessageListener6. 7. privateStringjob;8. 9. publicListener(Stringjob)10. this.job=job;11. 12. 13. publicvoidonMessage(Messagemessage)14. try15. /dosomethinghere16. System.out.println(job+id:+(ObjectMessage)me
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1