ActiveMQ操作队列和主题
一、JMS编码总体规范
二、创建Maven工程和引入Maven依赖
1 2 3 4 5 6 7 8 9 10 | <dependency> <groupId>org.apache.activemq</groupId> <artifactId>activemq-all</artifactId> <version> 5.15 . 5 </version> </dependency> <dependency> <groupId>org.apache.xbean</groupId> <artifactId>xbean-spring</artifactId> <version> 4.10 </version> </dependency> |
三、队列(Queue)
1、生产者
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | public class JmsQueueProducer { // tcp:一种通信协议 // 192.168.229.129:Linux主机的ip地址 // 61616:ActiveMQ默认的端口 public static final String BROKER_URL = "tcp://192.168.229.129:61616" ; public static final String QUEUE_NAME = "activemq-queue" ; public static final String TEXT_MESSAGE_NAME = "textMessage" ; public static void main(String[] args) throws JMSException { // 1、创建连接工厂 ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(BROKER_URL); // 2、通过连接工厂获取连接对象 Connection connection = connectionFactory.createConnection(); // 3、启动连接 connection.start(); // 4、通过连接对象创建一个JMS Session对象 Session session = connection.createSession( false , Session.AUTO_ACKNOWLEDGE); // 5、创建Destination对象(Destination接口有两个子接口,分别是Queue、Topic) Queue queue = session.createQueue(QUEUE_NAME); // 6、获取生产者对象 MessageProducer producer = session.createProducer(queue); // 发送3个TextMessage类型的消息到队列中 for ( int i = 1 ; i < 4 ; i++) { TextMessage textMessage = session.createTextMessage(TEXT_MESSAGE_NAME + i); producer.send(queue, textMessage); } System.out.println( "send message to queue success!!!" ); // 释放资源 producer.close(); session.close(); connection.close(); } } |
运行生产者代码之后,登录ActiveMQ客户端,可以看到消息已经推送至名称为activemq-queue的队列中了,由于我们发送了3个消息,所以这里的待处理消息就是3,我们还没有创建消费者,所以消费者数目为0,发送了3个消息,并且都进入了队列,所以入队的消息数目为3,没有消费者消费消息,那么出队列的消息数目为0.
队列相关名词解释:
名称 | 简介 |
Number Of Pending Messages |
待处理的消息数目:入队的总数-出队的总数 |
Number Of Consumers |
消费者数目:消费端的消费者数目 |
Messages Enqueued |
已经入队的消息数目,进入队列的消息的数目,这个数目只增不减,即使出队了也不会减少 |
Messages Dequeued |
已经出队的消息数目,也就是消费者消费掉的消息数目 |
2、消费者
一、消费者接收消息方式一
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | public class JmsQueueConsumer { public static final String BROKER_URL = "tcp://192.168.229.129:61616" ; public static final String QUEUE_NAME = "activemq-queue" ; public static void main(String[] args) throws IOException, JMSException { // 1、创建连接工厂 ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(BROKER_URL); // 2、通过连接工厂获取连接对象 Connection connection = connectionFactory.createConnection(); // 3、启动连接 connection.start(); // 4、通过连接对象创建一个JMS Session对象 Session session = connection.createSession( false , Session.AUTO_ACKNOWLEDGE); // 5、创建Destination对象(Destination接口有两个子接口,分别是Queue、Topic) Queue queue = session.createQueue(QUEUE_NAME); // 6、获取消费者对象 MessageConsumer consumer = session.createConsumer(queue); // 7、如果有消息就一直获取 while ( true ) { // 一直等待接收消息,在接收到消息之前一直处于阻塞状态,是同步阻塞方式 //Message message = consumer.receive(); // 在等待 4*1000毫秒之后,如果还没有接收到消息,那么就结束阻塞状态 Message message = consumer.receive( 4 * 1000 ); // 生产者发送到队列的消息是TextMessage类型的,那么这里接收消息的类型也要保持一致 if (message != null && message instanceof TextMessage) { TextMessage textMessage = (TextMessage) message; System.out.println( "消费者接收到的消息是:" + textMessage.getText()); } else { break ; } } // 8、释放资源 consumer.close(); session.close(); connection.close(); } } |
运行消费者代码消费完了消息之后,可以看出待处理的消息是0,入队的消息保持不变,还是3,可以出队的消息也变成了3,也就是代表着3条消息已经消费完了
二、消费者接收消息方式二
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | public class JmsQueueConsumer02 { public static final String BROKER_URL = "tcp://192.168.229.129:61616" ; public static final String QUEUE_NAME = "activemq-queue" ; public static void main(String[] args) throws IOException, JMSException { // 1、创建连接工厂 ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(BROKER_URL); // 2、通过连接工厂获取连接对象 Connection connection = connectionFactory.createConnection(); // 3、启动连接 connection.start(); // 4、通过连接对象创建一个JMS Session对象 Session session = connection.createSession( false , Session.AUTO_ACKNOWLEDGE); // 5、创建Destination对象(Destination接口有两个子接口,分别是Queue、Topic) Queue queue = session.createQueue(QUEUE_NAME); // 6、获取消费者对象 MessageConsumer consumer = session.createConsumer(queue); // 7、消费者使用消息监听的方式来消费消息,是异步非阻塞的方式 consumer.setMessageListener( new MessageListener() { @Override public void onMessage(Message message) { // 生产者发送的消息是什么类型的,那么消费者接收消息的类型也需要保持一致 if (message != null && message instanceof TextMessage) { TextMessage textMessage = (TextMessage) message; try { System.out.println( "消费者接收到的消息是:" + textMessage.getText()); } catch (JMSException e) { e.printStackTrace(); } } } }); // 使主线程不要结束,如果主线程结束了,那么消息监听的线程也会被迫结束,实际应用中程序会一直启动,就不需要这一句代码了 System.in.read(); // 8、释放资源 consumer.close(); session.close(); connection.close(); } } |
消费者获取消息的方式二与方式一有一点点不同,那就是消息监听的方式,消费者会一直处于启动状态,所以一直显示有消费者在线.
四、主题(Topic)
1、生产者
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | public class JmsTopicProducer { public static final String BROKER_URL = "tcp://192.168.229.129:61616" ; public static final String TOPIC_NAME = "activemq-queue" ; public static final String TEXT_MESSAGE_NAME = "textMessage" ; public static void main(String[] args) throws JMSException { // 1、创建连接工厂 ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(BROKER_URL); // 2、通过连接工厂获取连接对象 Connection connection = connectionFactory.createConnection(); // 3、启动连接 connection.start(); // 4、通过连接对象创建一个JMS Session对象 Session session = connection.createSession( false , Session.AUTO_ACKNOWLEDGE); // 5、创建Destination对象(Destination接口有两个子接口,分别是Queue、Topic) Topic topic = session.createTopic(TOPIC_NAME); // 6、获取生产者对象 MessageProducer producer = session.createProducer(topic); // 7、创建消息 for ( int i = 1 ; i < 4 ; i++) { TextMessage textMessage = session.createTextMessage(TEXT_MESSAGE_NAME + i); producer.send(textMessage); } // 8、 释放资源 producer.close(); session.close(); connection.close(); } } |
执行完主题的生产者之后,可以看到三条消息已经发送至名称为activemq-topic的主题中了
2、消费者
一、消费者接收消息方式一
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | public class JmsTopicCousumer { public static final String BROKER_URL = "tcp://192.168.229.129:61616" ; public static final String TOPIC_NAME = "activemq-topic" ; public static void main(String[] args) throws JMSException, IOException { System.out.println( "我是一号主题消费者" ); // 1、创建连接工厂对象 ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(BROKER_URL); // 2、通过连接工厂获取连接对象 Connection connection = connectionFactory.createConnection(); // 3、启动连接 connection.start(); // 4、通过连接对象获取JSM Session对象 Session session = connection.createSession( false , Session.AUTO_ACKNOWLEDGE); // 5、创建目的地 Topic topic = session.createTopic(TOPIC_NAME); // 6、创建主题消费者 MessageConsumer consumer = session.createConsumer(topic); // 7、接收消息方式一 while ( true ) { Message message = consumer.receive(); if (message != null && message instanceof TextMessage) { TextMessage textMessage = (TextMessage) message; System.out.println( "textMessage消息体:" + textMessage.getText()); } else { break ; } } // 8、释放资源 consumer.close(); session.close(); connection.close(); } } |
二、消费者接收消息方式二
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | public class JmsTopicCousumer { public static final String BROKER_URL = "tcp://192.168.229.129:61616" ; public static final String TOPIC_NAME = "activemq-topic" ; public static void main(String[] args) throws JMSException, IOException { // 1、创建连接工厂对象 ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(BROKER_URL); // 2、通过连接工厂获取连接对象 Connection connection = connectionFactory.createConnection(); // 3、启动连接 connection.start(); // 4、通过连接对象获取JSM Session对象 Session session = connection.createSession( false , Session.AUTO_ACKNOWLEDGE); // 5、创建目的地 Topic topic = session.createTopic(TOPIC_NAME); // 6、创建主题消费者 MessageConsumer consumer = session.createConsumer(topic); // 7、接收消息 consumer.setMessageListener( new MessageListener() { @Override public void onMessage(Message message) { if (message != null && message instanceof TextMessage) { TextMessage textMessage = (TextMessage) message; try { System.out.println( "textMessage消息体:" + textMessage.getText()); } catch (JMSException e) { e.printStackTrace(); } } } }); // 让主线程不要停止 System.in.read(); // 8、释放资源 consumer.close(); session.close(); connection.close(); } } |
五、注意事项
1、注意:consumer.receive()方法有两个,它们的区别如下
1 2 3 4 | // 一直接收消息,消费者和队列不会断开连接,处于同步阻塞状态 TextMessage textMessage = (TextMessage) consumer.receive(); // 超过了时间(毫秒值),消费者将和队列自动断开连接,结束阻塞状态 TextMessage textMessage = (TextMessage) consumer.receive( 10 * 1000 ); |
2、消费者通过 consumer.setMessageListener(MessageListerer messageListener)的方式消费消息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | // 消费者通过消息监听的方式消费消息 consumer.setMessageListener( new MessageListener() { @Override public void onMessage(Message message) { if (message != null && message instanceof TextMessage) { TextMessage textMessage = (TextMessage) message; try { System.out.println( "接收到的消息是:" + textMessage.getText()); } catch (JMSException e) { e.printStackTrace(); } } } }); // 保证在连接到MQ之前,控制台不灭,也就是消费到了消息之后才去释放资源,Dubbo中也有 System.in.read(); |
3、对于主题,如果我们先启动生产者,由于主题没有消费者,那么生产者发布的消息就是一条废消息,消费者是不能接收到任何消息的,所以我们应该先启动消费者,然后再启动生产者(类似于公众号订阅,你只有先订阅了之后才可以获得消息,如果没有订阅者的话,发布的消息就是一条废消息,没有任何意义)
4、如果消费者采用的是监听接收消息,一定要记得加上 System.in.read()方法
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?