【ActiveMQ】Part2 - 点对点消息传送模型(Point-to-Point)

回顾

JMS入门学习
什么是消息队列

点对点

Queue支持存在多个消费者,但是对一个消息而言,只会有一个消费者可以消费,不可重复消费。
在这里插入图片描述

简单例子

依赖

注意版本对应

<dependency>
	<groupId>org.apache.activemq</groupId>
	<artifactId>activemq-client</artifactId>
	<version>5.15.9</version>
</dependency>

同步方式接收消息

使用同步方式接收消息的话,消息订阅者调用receive()方法。在receive()中,消息未到达或在到达指定时间之前,方法会阻塞,直到消息可用。

生产者

代码:

package com.example.queue.同步;

import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;

@SuppressWarnings("all")
public class ProducerDemo {
    public void sendMessage(String msg) {
        // 连接工厂
        ConnectionFactory factory = null;
        // 连接对象
        Connection connection = null;
        // 目的地
        Destination destination = null;
        // 会话
        Session session = null;
        // 消息发送者
        MessageProducer producer = null;
        // 消息对象
        Message message = null;

        try {
            // 创建连接ActiveMQ服务的连接工厂
            factory = new ActiveMQConnectionFactory("admin", "admin", "tcp://127.0.0.1:61616");

            // 通过工厂,创建连接对象
            connection = factory.createConnection();
            // 消息的发送者可以不启动连接(建议启动连接),消息的消费者必须启动连接
            // producer在发送消息的时候,会检查是否启动了连接。如果未启动,则自动启动
            // 如果没有特殊的配置,建议配置完毕后再启动连接
            connection.start();

            /*
             * 通过连接对象,创建会话对象,必须绑定目的地
             *
             * transacted:是否支持事务
             *     true:支持事务,第二个参数默认无效,建议传递的数据是Session.SESSION_TRANSACTED
             *     false:不支持事务,常用参数,第二个参数必须传递,且必须有效
             *
             * acknowledgeMode:如何确认消息的处理,使用确认机制实现
             *     AUTO_ACKNOWLEDGE:自动确认消息,消息的消费者处理消息后,自动确认
             *     CLIENT_ACKNOWLEDGE:客户端手动确认,消息的消费者处理消息后,必须手动确认
             *     DUPS_OK_ACKNOWLEDGE:有副本的客户端手动确认。一个消息可以多次处理;可以降低Session的消耗,在可以容忍重复消息时使用(不推荐使用)
             */
            session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
            // 创建目的地。参数是目的地名称(唯一标识)
            destination = session.createQueue("hello");

            // 通过会话对象,创建消息的发送者
            // 创建producer的时候,可以不提供目的地,而在发送消息的时候指定目的地
            producer = session.createProducer(destination);

            // 创建文本消息
            message = session.createTextMessage(msg);

            // 使用producer,发送消息到目的地
            producer.send(message);

            System.out.println("消息已发送");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 回收资源
            // 回收消息发送者
            if (producer!=null) {
                try {
                    producer.close();
                } catch (JMSException e) {
                    e.printStackTrace();
                }
            }
            // 回收会话对象
            if (session!=null) {
                try {
                    session.close();
                } catch (JMSException e) {
                    e.printStackTrace();
                }
            }
            // 回收连接对象
            if (connection!=null) {
                try {
                    connection.close();
                } catch (JMSException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void main(String[] args) {
        ProducerDemo demo = new ProducerDemo();
        demo.sendMessage("hello world");
    }
}

输出:

消息已发送

Queues:
在这里插入图片描述

消费者

代码:

package com.example.queue.同步;

import javax.jms.*;
import org.apache.activemq.ActiveMQConnectionFactory;

@SuppressWarnings("all")
public class ConsumerDemo {
    public String receiveTextMessage() {
        String returnMsg = "";
        // 连接工厂
        ConnectionFactory factory = null;
        // 连接对象
        Connection connection = null;
        // 目的地
        Destination destination = null;
        // 会话
        Session session = null;
        // 消息消费者,用于接收消息的对象
        MessageConsumer consumer = null;
        // 消息对象
        Message message = null;

        try {
            // 创建连接ActiveMQ服务的连接工厂
            factory = new ActiveMQConnectionFactory("admin", "admin", "tcp://127.0.0.1:61616");
            // 通过工厂,创建连接对象
            connection = factory.createConnection();
            // 消息的消费者必须启动连接,否则无法处理消息
            connection.start();
            // 通过连接对象,创建会话对象,必须绑定目的地
            session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
            // 创建目的地。参数是目的地名称(唯一标识)
            destination = session.createQueue("hello");
            // 创建消息消费者对象,在指定目的地中获取消息
            consumer = session.createConsumer(destination);
            // 获取队列中的消息
            // receive方法是一个主动获取消息的方法。执行一次,拉取一个消息,开发少用
            message = consumer.receive();
            // 处理文本消息
            returnMsg = ((TextMessage)message).getText();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 回收资源
            // 回收消息消费者
            if (consumer!=null) {
                try {
                    consumer.close();
                } catch (JMSException e) {
                    e.printStackTrace();
                }
            }
            // 回收会话对象
            if (session!=null) {
                try {
                    session.close();
                } catch (JMSException e) {
                    e.printStackTrace();
                }
            }
            // 回收连接对象
            if (connection!=null) {
                try {
                    connection.close();
                } catch (JMSException e) {
                    e.printStackTrace();
                }
            }
        }
        return returnMsg;
    }

    public static void main(String[] args) {
        ConsumerDemo demo = new ConsumerDemo();
        String returnMsg = demo.receiveTextMessage();
        System.out.println(returnMsg);
    }
}

输出:

hello world

Queues:
在这里插入图片描述

异步方式接收消息

使用异步方式接收消息的话,消息订阅者需注册一个消息监听者,类似于事件监听器,只要消息到达,JMS服务提供者会通过调用监听器的onMessage()递送消息。

先创建一个消费者

代码:

package com.example.queue.异步;

import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;

@SuppressWarnings("all")
public class ConsumerDemo {
    public void consumMessage() {
        // 连接工厂
        ConnectionFactory factory = null;
        // 连接对象
        Connection connection = null;
        // 目的地
        Destination destination = null;
        // 会话
        Session session = null;
        // 消息消费者,用于接收消息的对象
        MessageConsumer consumer = null;

        try {
            // 创建连接ActiveMQ服务的连接工厂
            factory = new ActiveMQConnectionFactory("admin", "admin", "tcp://127.0.0.1:61616");
            // 通过工厂,创建连接对象
            connection = factory.createConnection();
            // 消息的消费者必须启动连接,否则无法处理消息
            connection.start();
            // 通过连接对象,创建会话对象,必须绑定目的地
            session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
            // 创建目的地。参数是目的地名称(唯一标识)
            destination = session.createQueue("hello");
            // 创建消息消费者对象,在指定目的地中获取消息
            consumer = session.createConsumer(destination);
            // 注册监听器。注册成功后,队列中的消息变化会自动触发监听器代码。接收消息并处理
            consumer.setMessageListener(new MessageListener() {

                /*
                 * 监听器一旦注册,永久有效(consumer线程不关闭)
                 * 处理消息的方式:只要有消息未处理,自动调用onMessage方法处理消息
                 * 监听器可以注册若干个,注册多个监听器,类似于集群
                 * ActiveMQ自动循环调用多个监听器,处理队列中的消息,实现并行处理
                 *
                 * 处理消息的方法,就是监听方法
                 * 监听的事件是:消息、消息未处理
                 * 要处理的具体内容:消息处理
                 * 参数message:未处理的消息
                 */
                @Override
                public void onMessage(Message message) {
                    try {
                        // 确认方法,代表consumer已经收到消息。确认后,MQ删除对应的消息
                        message.acknowledge();
                        String data = ((TextMessage) message).getText();
                        System.out.println(data);
                    } catch (JMSException e) {
                        e.printStackTrace();
                    }
                }
            });

            // 阻塞当前代码
            System.in.read();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 回收资源
            // 回收消息消费者
            if (consumer != null) {
                try {
                    consumer.close();
                } catch (JMSException e) {
                    e.printStackTrace();
                }
            }
            // 回收会话对象
            if (session != null) {
                try {
                    session.close();
                } catch (JMSException e) {
                    e.printStackTrace();
                }
            }
            // 回收连接对象
            if (connection != null) {
                try {
                    connection.close();
                } catch (JMSException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void main(String[] args) {
        ConsumerDemo demo = new ConsumerDemo();
        demo.consumMessage();
    }
}

在这里插入图片描述

发送消息

在代码里或者mq面板发送一条消息
发送消息代码跟上面同步方式相同
在这里插入图片描述
在这里插入图片描述
IDE内输出:

hello world

测试是否可以重复消费

启动多个实例
在这里插入图片描述
在这里插入图片描述
发送一条消息
在这里插入图片描述
只有一个收到了消息
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值