深入掌握 JMS_第1页
深入掌握 JMS_第2页
深入掌握 JMS_第3页
深入掌握 JMS_第4页
深入掌握 JMS_第5页
已阅读5页,还剩8页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、深入 掌握JMS(一):JSM基础 1. JMS基本概念                 JMS(Java Message Service)            即Java消息服务。它提供标准的产生、发送、接收消息的接口简化企业应用的开发。它支持两种消息通信模型:点到点(point-to-point) (P2P)模型和发布/订阅(Pub/Sub)

2、模型。P2P            模型规定了一个消息只能有一个接收者;Pub/Sub 模型允许一个消息可以有多个接收者。            对于点到点模型,消息生产者产生一个消息后,把这个消息发送到一个Queue(队列)中,然后消息接收者再从这个Queue中读取,一旦这个消息被一个接 收者读取之后,它就在这个Queue中消失了,所以一个消息只能被一个接收者消费。   &#

3、160;        与点到点模型不同,发布/订阅模型中,消息生产者产生一个消息后,把这个消息发送到一个Topic中,这个Topic可以同时有多个接收者在监听,当一个 消息到达这个Topic之后,所有消息接收者都会收到这个消息。                  简单的讲,点到点模型和发布/订阅模型的区别就是前者是一对一,后者是一对多。   &#

4、160;        2. 几个重要概念            Destination:消息发送的目的地,也就是前面说的Queue和Topic。创建好一个消息之后,只需要把这个消息发送到目的地,消息的发送者就 可以继续做自己的事情,而不用等待消息被处理完成。至于这个消息什么时候,会被哪个消费者消费,完全取决于消息的接受者。         

5、60;      Message:从字面上就可以看出是被发送的消息。它有下面几种类型:                    StreamMessage:Java 数据流消息,用标准流操作来顺序的填充和读取。              &#

6、160;     MapMessage:一个Map类型的消息;名称为 string 类型,而值为 Java 的基本类型。                    TextMessage:普通字符串消息,包含一个String。              

7、      ObjectMessage:对象消息,包含一个可序列化的Java 对象                    BytesMessage:二进制数组消息,包含一个byte。                

8、60;   XMLMessage:  一个XML类型的消息。                最常用的是TextMessage和ObjectMessage。               Session:与JMS提供者所建立的会话,通过Session我们才可以创建一个Message。  

9、60;            Connection:与JMS提供者建立的一个连接。可以从这个连接创建一个会话,即Session。            ConnectionFactory:那如何创建一个Connection呢?这就需要下面讲到的ConnectionFactory了。通过这个工厂类 就可以得到一个与JMS提供者的连接,即Conection。   

10、0;           Producer:消息的生产者,要发送一个消息,必须通过这个生产者来发送。               MessageConsumer:与生产者相对应,这是消息的消费者或接收者,通过它来接收一个消息。            前面多次提到JMS提

11、供者,因为JMS给我们提供的只是一系列接口,当我们使用一个JMS的时候,还是需要一个第三方的提供者,它的作用就是真正管理这些 Connection,Session,Topic和Queue等。                通过下面这个简图可以看出上面这些概念的关系。              ConnectionFactory->C

12、onnection->Session->Message              Destination + Session->Producer              Destination +            Session-&g

13、t;MessageConsumer                那么可能有人会问: ConnectionFactory和Destination 从哪儿得到?                这就和JMS提供者有关了. 如果在一个JavaEE环境中, 可以通过JNDI查找得到, 如果在一个非JavaEE环境中, 

14、0;          那只能通过JMS提供者提供给我们的接口得到了.深入 掌握JMS(二):一个JMS例子 前一讲简单的介绍了一下JMS的基本概念, 这一讲结合一个例子让大家深入理解前一讲的基本概念.             首先需要做的是选择一个JMS提供者, 如果在JavaEE环境中可以不用考虑这些. 我们选择ActiveMQ, 官方地址: . 网上有很多介绍ActiveMQ的文档, 所以在

15、这里就不介绍了.             按照上一讲的这个简图,             public class MessageSendAndReceive             深入 掌握JMS(三):MessageListener 消息的消费者接收消息可以采用两

16、种方式: 深入 掌握JMS(四):实战Queue             public class QueueTest                 public static void main(String args) throws Exception       

17、0;             ActiveMQConnectionFactory factory = new             ActiveMQConnectionFactory("vm:/localhost");           

18、0;         Connection connection = factory.createConnection();                     connection.start();          

19、60;         /创建一个Queue                     Queue queue = new ActiveMQQueue("testQueue");            

20、         /创建一个Session                     Session session = connection.createSession(false,             Sessio

21、n.AUTO_ACKNOWLEDGE);                    /创建一个生产者,然后发送多个消息。                     MessageProducer producer = sess

22、ion.createProducer(queue);                     for(int i=0; i<10; i+)                       

23、  producer.send(session.createTextMessage("Message:" + i);                                        &#

24、160;                      运行这个例子会得到下面的输出结果:             Consumer1 get Message:0            

25、; Consumer2 get Message:1             Consumer1 get Message:2             Consumer2 get Message:3             Consumer1 get Message:4 &

26、#160;           Consumer2 get Message:5             Consumer1 get Message:6             Consumer2 get Message:7     

27、0;       Consumer1 get Message:8             Consumer2 get Message:9               可以看出每个消息直被消费了一次,但是如果有多个消费者同时监听一个Queue的话,无法确定一个消息最终会被哪一个消费者消费。深入 掌握J

28、MS(五):实战Topic 与Queue不同的是,Topic实现的是发布/订阅模型,在下面的例子中,启动2个消费者共同监听一个Topic,然后循环给这个Topic 中发送多个消息。             public class TopicTest                     

29、0;   运行后得到下面的输出结果:             Consumer1 get Message:0             Consumer2 get Message:0             Consumer1 get Message:

30、1             Consumer2 get Message:1             Consumer1 get Message:2             Consumer2 get Message:2     &

31、#160;       Consumer1 get Message:3             Consumer2 get Message:3             Consumer1 get Message:4         

32、0;   Consumer2 get Message:4             Consumer1 get Message:5             Consumer2 get Message:5             Consumer1 ge

33、t Message:6             Consumer2 get Message:6             Consumer1 get Message:7             Consumer2 get Message:7   

34、60;         Consumer1 get Message:8             Consumer2 get Message:8             Consumer1 get Message:9        

35、     Consumer2 get Message:9             说明每一个消息都会被所有的消费者消费。深入 掌握JMS(六):消息头 一个消息对象分为三部分:消息头(Headers),属性(Properties)和消息体(Payload)。对于 StreamMessage和             MapMessage,

36、消息本身就有特定的结构,而对于TextMessage,ObjectMessage和BytesMessage是无结构的。一个 消息可以包含一些重要的数据或者仅仅是一个事件的通知。                 消息的Headers部分通常包含一些消息的描述信息,它们都是标准的描述信息。包含下面一些值:             JMSDes

37、tination                    消息的目的地,Topic或者是Queue。             JMSDeliveryMode             消息的发送模式:pe

38、rsistent或nonpersistent。前者表示消息在被消费之前,如果JMS提供者DOWN了,重新启动后消息仍然存在。 后者在这种情况下表示消息会被丢失。可以通过下面的方式设置:                    Producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);        &

39、#160;           JMSTimestamp                    当调用send()方法的时候,JMSTimestamp会被自动设置为当前事件。可以通过下面方式得到这个值:          

40、0;         long timestamp = message.getJMSTimestamp();             JMSExpiration             表示一个消息的有效期。只有在这个有效期内,消息消费者才可以消费这个消息。默认值为0,表示消息永不过期。可以通过下面

41、的方式设置:                    producer.setTimeToLive(3600000); /有效期1小时 (1000毫秒 * 60秒 * 60分)             JMSPriority        &

42、#160;           消息的优先级。0-4为正常的优先级,5-9为高优先级。可以通过下面方式设置:                    producer.setPriority(9);           &

43、#160; JMSMessageID                    一个字符串用来唯一标示一个消息。             JMSReplyTo             有时消息生产者希望消

44、费者回复一个消息,JMSReplyTo为一个Destination,表示需要回复的目的地。当然消费者可以不理会它。             JMSCorrelationID             通常用来关联多个Message。例如需要回复一个消息,可以把JMSCorrelationID设置为所收到的消息的JMSMessageID。    

45、60;        JMSType                    表示消息体的结构,和JMS提供者有关。             JMSRedelivered 如果这个值为true,表示消息是被重新发送了。因为有时消费者没有确认他

46、已经收 到消息或者JMS提供者不确定消费者是否已经收到。             除了Header,消息发送者可以添加一些属性(Properties)。这些属性可以是应用自定义的属性,JMS定义的属性和JMS提供者定义的属性。 我们通常只适用自定义的属性。                 后面会讲到这些Header和属性的用法。深入 掌握

47、JMS(七):DeliveryMode例子 在下面的例子中,分别发送一个Persistent和nonpersistent的消息,然后关闭退出JMS。             public class DeliveryModeSendTest                 运行上面的程序,当输出“Send messages  &

48、#160;          sucessfully!”时,说明两个消息都已经发送成功,然后我们结束它,来停止JMS Provider。                 接下来我们重新启动JMS Provicer,然后添加一个消费者:           &#

49、160; public class DeliveryModeReceiveTest             运行上面的程序,可以得到下面的输出结果:             Consumer get A persistent Message             可以

50、看出消息消费者只接收到一个消息,它是一个Persistent的消息。而刚才发送的non persistent消息已经丢失了。             另外, 如果发送一个non persistent消息, 而刚好这个时候没有消费者在监听, 这个消息也会丢失.深入 掌握JMS(八):JMSReplyTo 在下面的例子中,首先创建两个Queue,发送者给一个Queue发送,接收者接收到消息之后给另一个Queue回复一个Message,然后 再创建一个消费者来接受所回复的消息。  

51、           public class MessageSendReceiveAndReply                 public static void main(String args) throws Exception          

52、           ActiveMQConnectionFactory factory = new             ActiveMQConnectionFactory("vm:/localhost");              

53、       Connection connection = factory.createConnection();                     connection.start();             

54、0;       /消息发送到这个Queue                     Queue queue = new ActiveMQQueue("testQueue");             

55、0;       /消息回复到这个Queue                     Queue replyQueue = new ActiveMQQueue("replyQueue");            

56、0;        final Session session = connection.createSession(false,             Session.AUTO_ACKNOWLEDGE);                   &#

57、160;         首先消息生产者发送一个消息,内容为“Andy”,             然后消费者收到这个消息之后根据消息的JMSReplyTo,回复一个消息,内容为“Hello Andy'。             最后在回复的Queue上创建一个接收回复消息的消费者,它输出所

58、回复的内容。                 运行上面的程序,可以得到下面的输出结果:             Hello Andy深入 掌握JMS(九):Selector 前面的例子中创建一个消息消费者使用的是:           &#

59、160;           sesssion.createConsumer(destination)               另外,还提供了另一种方式:                 sesssion.creat

60、eConsumer(destination, selector)             这里selector是一个字符串,用来过滤消息。也就是说,这种方式可以创建一个可以只接收特定消息的一个消费者。Selector的格式是类似于 SQL-92的一种语法。可以用来比较消息头信息和属性。               下面的例子中,创建两个消费者,共同监听同一个

61、Queue,但是它们的Selector不同,然后创建一个消息生产者,来发送多个消息。             public class JMSSelectorTest             结果如下:             ConsumerA get Message

62、0, receiver:A             ConsumerB get Message1, receiver:B             ConsumerB get Message2, receiver:B             ConsumerA get M

63、essage3, receiver:A             ConsumerB get Message4, receiver:B             ConsumerB get Message5, receiver:B             ConsumerA

64、 get Message6, receiver:A             ConsumerB get Message7, receiver:B             ConsumerB get Message8, receiver:B             Con

65、sumerA get Message9, receiver:A             可以看出,消息消费者只会取走它自己感兴趣的消息。深入 掌握JMS(十):JMSCorrelationID与Selector 前面讲过JMSCorrelationID主要是用来关联多个Message,例如需要回复一个消息的时候,通常把回复的消息的            JMSCorrelationID设

66、置为原来消息的ID。在下面这个例子中,创建了三个消息生产者A,B,C和三个消息消费者A,B,C。生产者A给消费 者A发送一个消息,同时需要消费者A给它回复一个消息。B、C与A类似。                简图如下:                   生产者A-发送-消费者A-回复

67、-生产者A                    生产者B-发送-消费者B-回复-生产者B                    生产者C-发送-消费者C-回复-生产者C      

68、0;         需要注意的是,所有的发送和回复都使用同一个Queue,通过Selector区分。            运行结果为:            ConsumerA get:Message from ProducerA        

69、    ProducerA get reply:Reply from ConsumerA            ConsumerB get:Message from ProducerB            ProducerB get reply:Reply from ConsumerB       

70、0;    ConsumerC get:Message from ProducerC            ProducerC get reply:Reply from ConsumerC深入 掌握JMS(十一):TemporaryQueue和TemporaryTopic 深入 掌握JMS(十二):MDB             它要求必须标注为Messag

71、eDriven。它所监听Destination通过标注属性来注入。             下面是一个发送消息的StatelessBean:             Remote             public interface IMessageSender &

72、#160;               public void sendMessage(String content) throws Exception;                         Stateless  &#

73、160;          Remote             public class MessageSender implements IMessageSender                 Resource(mappedName=&qu

74、ot;ConnectionFactory")                 private ConnectionFactory factory;                 Resource(mappedName="queue/testQueue")  

75、               private Queue queue;                 public void sendMessage(String content) throws Exception        

76、0;            Connection cn = factory.createConnection();                     Session session = cn.createSession(false,      

77、       Session.AUTO_ACKNOWLEDGE);                     MessageProducer producer = session.createProducer(queue);           

78、60;         producer.send(session.createTextMessage(content);                                   

79、0;     这个EJB只有一个方法SendMessage。ConnectionFactory和Queue通过标注注入。 ActiveMQ 在C#中的应用 ActiveMQ是个好东东,不必多说。ActiveMQ提供多种语言支持,如Java, C, C+, C#, Ruby, Perl, Python, PHP等。由于我在windows下开发GUI,比较关心C+和C#,其中C#的ActiveMQ很简单,Apache提供NMS(.Net Messaging Service)支持.Net开发,只需如下几个步骤即能建立简单的实现。C+的应用相对麻烦些,稍后写文章

80、介绍。 1、去ActiveMQ官方网站下载最新版的ActiveMQ,网址:2、去ActiveMQ官方网站下载最新版的Apache.NMS,网址:producer:                 Console.ReadLine();                   

81、0;    catch (System.Exception e)                             Console.WriteLine("0",e.Message);         &#

82、160;       Console.ReadLine();                         consumer: namespace Subscribe     class Program         

83、0;   static void Main(string args)                     try                         &#

84、160;   /Create the Connection factory                 IConnectionFactory factory = new ConnectionFactory("tcp:/localhost:61616/");             &#

85、160;   /Create the connection                 using (IConnection connection = factory.CreateConnection()                                     connection.ClientId = "testing listener"       

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论