ActiveMQ消息队列,一对一推送,一对多订阅

生产者:推送消息方,主要负责给用户推送消息。(ActiveMQ接口)

消费者:接收消息方,主要查看推送过来的消息。(用户)

ActiveMQ安装非常简单,在此我就不发了,安装完ActiveMQ后,进入网址 http://localhost:8161/admin/ ,登录管理后台,默认用户名:admin        密码:admin  到此结束,开始写代码。

写代码之前,还需要开启ActiveMQ服务,在安装文件夹里,打开bin文件夹,运行服务,如果是32位则选用32,64选64的bin。开启服务后,就可以快乐的copy代码了。

一、

  ①、一对一推送消息(Queue模式)生产者代码:      ↓

  

 1 public class Sender {  
 2 
 3     public static void main(String[] args) throws JMSException, InterruptedException {  
 4         // ConnectionFactory :连接工厂,JMS 用它创建连接  
 5         //61616是ActiveMQ默认端口
 6         ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(  
 7                                                   ActiveMQConnection.DEFAULT_USER,  
 8                                                   ActiveMQConnection.DEFAULT_PASSWORD,  
 9                                                   "tcp://localhost:61616");  
10 
11         // Connection :JMS 客户端到JMS Provider 的连接  
12         Connection connection =  connectionFactory.createConnection();  
13 
14         connection.start();  
15         // Session: 一个发送或接收消息的线程  
16         Session session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);  
17 
18         // Destination :消息的目的地;消息发送给谁.  
19         Destination destination =  session.createQueue("my-queue");  
20 
21         // MessageProducer:消息发送者  
22         MessageProducer producer =  session.createProducer(destination);  
23 
24         // 设置不持久化,可以更改  
25         producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);  
26 
27         for(int i=0;i<10;i++){  
28             //创建文本消息  
29             TextMessage message = session.createTextMessage("hello.I am producer, this is a test message"+i);  
30 
31             Thread.sleep(1000);  
32             //发送消息  
33             producer.send(message);  
34         }  
35 
36         session.commit();  
37         session.close();  
38         connection.close();  
39     }  
40 
41 }  

 

 

 ②、消费者代码(Queue模式)接收发送过来的消息:    ↓

 1 // ConnectionFactory :连接工厂,JMS 用它创建连接  
 2    private static ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(ActiveMQConnection.DEFAULT_USER,  
 3            ActiveMQConnection.DEFAULT_PASSWORD, "tcp://localhost:61616");  
 4 
 5    public static void main(String[] args) throws JMSException {  
 6         // Connection :JMS 客户端到JMS Provider 的连接  
 7         final Connection connection =  connectionFactory.createConnection();  
 8 
 9         connection.start();  
10         // Session: 一个发送或接收消息的线程  
11         final Session session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);  
12         // Destination :消息的目的地;消息送谁那获取.  
13         Destination destination =  session.createQueue("my-queue");  
14         // 消费者,消息接收者  
15         MessageConsumer consumer1 =  session.createConsumer(destination);  
16 
17         consumer1.setMessageListener(new MessageListener() {  
18                 @Override  
19                 public void onMessage(Message msg) {  
20 
21                     try {  
22 
23                         TextMessage message = (TextMessage)msg ;  
24                         System.out.println("consumerOne收到消息: "+message.getText());  
25                         session.commit();  
26                     } catch (JMSException e) {                
27                         e.printStackTrace();  
28                     }  
29 
30                 }  
31             });  
32 }  

运行之后控制台不会退出一直监听消息库,对于消息发送者的十条信息,控制输出:

consumerOne收到消息: hello.I am producer, this is a test message0 
consumerOne收到消息: hello.I am producer, this is a test message1 
consumerOne收到消息: hello.I am producer, this is a test message2 
consumerOne收到消息: hello.I am producer, this is a test message3 
consumerOne收到消息: hello.I am producer, this is a test message4 
consumerOne收到消息: hello.I am producer, this is a test message5 
consumerOne收到消息: hello.I am producer, this is a test message6 
consumerOne收到消息: hello.I am producer, this is a test message7 
consumerOne收到消息: hello.I am producer, this is a test message8 
consumerOne收到消息: hello.I am producer, this is a test message9 
如果此时另外一个线程也存在消费者监听该Queue,则两者交换输出。(注:Queue仅使用于 1V1 ,发送推送消息给个人

 

二、

  ①、一对多订阅推送消息(Topic模式)生产者代码:      ↓

 1 package com.ym.admin.config;
 2 
 3 import javax.jms.Connection;
 4 import javax.jms.ConnectionFactory;
 5 import javax.jms.DeliveryMode;
 6 import javax.jms.Destination;
 7 import javax.jms.JMSException;
 8 import javax.jms.MapMessage;
 9 import javax.jms.MessageProducer;
10 import javax.jms.Session;
11 import javax.jms.TextMessage;
12 
13 import org.apache.activemq.ActiveMQConnection;
14 import org.apache.activemq.ActiveMQConnectionFactory;
15 
16 //发送消息
17 public class Sender {  
18     public static void main(String[] args) throws JMSException, InterruptedException {
19         // ConnectionFactory :连接工厂,JMS 用它创建连接  
20         //61616是ActiveMQ默认端口
21         ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(  
22                 "admin",  
23                 "admin",  
24                                                   "tcp://localhost:61616");  
25 
26         // Connection :JMS 客户端到JMS Provider 的连接  
27         Connection connection =  connectionFactory.createConnection();  
28         connection.start();  
29         // Session: 一个发送或接收消息的线程  
30         Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);  //自动确认
31 
32         // Destination :消息的目的地;消息发送给谁.  
33         //Destination destination =  session.createQueue("my-queue");  
34         Destination destination = session.createTopic("STOCKS.myTopic"); //创建topic   myTopic
35         // MessageProducer:消息发送者  
36         MessageProducer producer =  session.createProducer(destination);  
37 
38         // 设置不持久化,可以更改  
39         producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);  
40 
41          for(int i=0;i<3;i++){  
42             //创建文本消息  
43             TextMessage message = session.createTextMessage("j"+i);  
44             //发送消息  
45             System.out.println("发送消息成功:"+i);
46             producer.send(message);  
47         }  
48  
49         session.close();  
50         connection.close();
51     }  
52 }  

  

 

  ②、消费者代码(Topic模式)接收发送过来的消息:    ↓

 1 package com.ym.admin.config;
 2 
 3 import javax.jms.Connection;
 4 import javax.jms.ConnectionFactory;
 5 import javax.jms.ConnectionMetaData;
 6 import javax.jms.Destination;
 7 import javax.jms.JMSException;
 8 import javax.jms.MapMessage;
 9 import javax.jms.Message;
10 import javax.jms.MessageConsumer;
11 import javax.jms.MessageListener;
12 import javax.jms.Session;
13 import javax.jms.TextMessage;
14 import javax.jms.Topic;
15 
16 import org.apache.activemq.ActiveMQConnection;
17 import org.apache.activemq.ActiveMQConnectionFactory;
18 import org.springframework.jms.support.JmsUtils;
19 import org.springframework.util.StringUtils;
20 
21 //接收订阅
22 public class Receiver {  
23     private static ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("admin",
24             "admin", "tcp://localhost:61616");
25     public static void main(String[] args) {  
26 
27             // Connection :JMS 客户端到JMS Provider 的连接
28             try {
29                 final Connection connection = connectionFactory.createConnection();
30                 connection.setClientID("anpei"); //持久订阅需要设置这个。
31                  connection.start();
32                 int INDIVIDUAL_ACK_TYPE = 4;
33                 // Session: 一个发送或接收消息的线程
34                 final Session session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
35                  // Destination :消息的目的地;消息送谁那获取.
36                 Topic topic = session.createTopic("STOCKS.myTopic");// 创建topic
37                  
38                  // 消费者,消息接收者
39             //    MessageConsumer consumer1 = session.createConsumer(destination); 普通订阅
40                 MessageConsumer consumer1 = session.createDurableSubscriber(topic,"anpei");//持久化订阅
41                 
42                 consumer1.setMessageListener(new MessageListener() {
43                     
44                     @Override
45                     public void onMessage(Message msg) {
46 
47                         try {
48                             
49                             TextMessage message = (TextMessage) msg;
50                             System.out.println("AAAAAAAAA收到消息: " + message.getText());54                         //    JmsUtils.commitIfNecessary(session);
55                             session.commit();
56                             
57                              
58                         } catch (JMSException e) {
59                             e.printStackTrace();
60                         }
61 
62                     }
63                 });
64 
65                 /*// 再来一个消费者,消息接收者
66                 MessageConsumer consumer2 = session.createConsumer(destination);
67 
68                 consumer2.setMessageListener(new MessageListener() {
69                     @Override
70                     public void onMessage(Message msg) {
71 
72                         try {
73 
74                             TextMessage message = (TextMessage) msg;
75                             System.out.println("BBBBBBBBB收到消息: " + message.getText());
76                             JmsUtils.commitIfNecessary(session);
77                           //  session.commit();
78                         } catch (JMSException e) {
79                             e.printStackTrace();
80                         }
81 
82                     }
83                 });*/
84             } catch (Exception e) {
85                 e.printStackTrace();
86             }
87     }  
88   
89 }  

 

上面程序运行后输出以下信息:

AAAAAAAAA收到消息: j0

AAAAAAAAA收到消息: j1

AAAAAAAAA收到消息: j2

Session session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
// Session: 一个发送或接收消息的线程

  一、事务

  这一句的 true 代表是否使用事务,true:使用   false:不使用。

  使用事务和不使用事务的区别:↓

  如果使用事务,下面一定要session.commit();提交。 如果不使用事务,则需要把这句话删掉,因为没有事务可以提交,会报错。

  如果使用事务,一切都要按照事务的规则来。如果为false,则需要使用ACK机制进行确认接收。如果不确认接收,将一直收到消息通知。

  二、ACK机制

Session.AUTO_ACKNOWLEDGE  ACK机制,对接收的消息进行处理
  • AUTO_ACKNOWLEDGE = 1    自动确认
  • CLIENT_ACKNOWLEDGE = 2    客户端手动确认   
  • DUPS_OK_ACKNOWLEDGE = 3    自动批量确认
  • SESSION_TRANSACTED = 0    事务提交并确认

    此外AcitveMQ补充了一个自定义的ACK_MODE:

  • INDIVIDUAL_ACKNOWLEDGE = 4    单条消息确认
  • 具体请参考 http://blog.csdn.net/lulongzhou_llz/article/details/42270113 

    三、持久化消息
    定义:消息持久性对于可靠消息传递来说应该是一种比较好的方法,有了消息持久化,即使发送者和接受者不是同时在线(服务同时启动)或者消息中心在发送者发送消息后宕机了,在消息中心重新启动后仍然可以将消息发送出去。(意思就是说,即使消费者处于离线状态,在重新登陆后,依然可以收到消息)
  • 上面一对多订阅的代码,是我持久化过后的代码,通过:
                    connection.setClientID("zhangsan"); //持久订阅需要设置这个。
                    MessageConsumer consumer1 = session.createDurableSubscriber(topic,"zhangsan");//持久化订阅

    如:我是张三,我是张三,请给我馒头。我是王七,我是王七,请给我馒头。对比一对一消息推送,很容易就看懂了。

    上面程序接收的消息,接收一次,就不能接收了,因为

  • AUTO_ACKNOWLEDGE = 1    自动确认
    程序在第一次运行,就已经自动确认已经接收了消息,ActiveMQ将自动删除已经确认的消息。

    如果哪个地方有问题,欢迎留言,谢谢。
posted @ 2017-09-20 18:44  根目录97  阅读(6645)  评论(0编辑  收藏  举报