本篇将继续延续上一篇的内容,作为知识补充篇,为接下来我们学习spring整合ActiveMQ打好基础

本篇主要学习内容:

  1.ActiveMQ 队列服务监听

  2.ActiveMQ Topic模型


回顾下上一篇ActiveMQ学习总结我们学习到了:

  1.ActiveMQ术语及API介绍

  2.ActiveMQ 文本消息处理

  3.ActiveMQ 对象消息处理

相信大现在对ActiveMQ的一些简单操作已经很轻松掌握了

上一篇文章地址:https://www.cnblogs.com/arebirth/p/activemq02.html


一 ActiveMQ实现队列服务监听

在我们上一篇的练习中,所有的消费者都是接收一次消息即断开连接,这样是不是很不方便。

试想一下,如果我们的provider在consumer接收完第一条消息后又继续发送了一条消息,那么consumer已经断开连接了,是不是就不能连接不间断的实时获取消息?

解决方案:

  很容易,用我们的队列服务监听即可

注*:根据上一章的学习,大家对环境搭建使用配置,肯定都已经相当清楚了,这里就不过多阐述,直接进行代码实战

1 消息生产者

相比之下,我么你的生产者照之前是没有任何变化的,主要的变化还是在cosumer身上

package cn.arebirth.mq;

import org.apache.activemq.ActiveMQConnectionFactory;

import javax.jms.*;

public class ActiveMQQueueListenerProducer {
public static void sendTextActiveMq(String txt) {
//定义链接工厂
ConnectionFactory connectionFactory = null; //定义链接对象
Connection connection = null; //定义会话
Session session = null; //目的地
Destination destination = null; //定义消息的发送者
MessageProducer producer = null; //定义消息
Message message = null; try {
//创建链接工厂
connectionFactory = new ActiveMQConnectionFactory("admin", "admin", "tcp://169.254.18.20:61616"); //创建链接诶对象
connection = connectionFactory.createConnection(); //启动链接
connection.start(); //创建会话
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); //创建目的地
destination = session.createQueue("queue-listener"); //创建消息生产者
producer = session.createProducer(destination); //创建消息对象
message = session.createTextMessage(txt); //发送消息
producer.send(message);
} catch (Exception ex) {
ex.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();
}
}
}
}
}

2 消息消费者

package cn.arebirth.mq;

import org.apache.activemq.ActiveMQConnectionFactory;

import javax.jms.*;

public class ActiveMQQueueListenerConsumer {
public static void receiveTextActiveMq() {
// 定义链接工厂
ConnectionFactory connectionFactory = null;
// 定义链接对象
Connection connection = null;
// 定义会话
Session session = null;
// 目的地
Destination destination = null;
// 定义消息的发送者
MessageConsumer consumer = null;
// 定义消息
Message message = null; try {
//创建链接工厂
connectionFactory = new ActiveMQConnectionFactory("admin", "admin", "tcp://169.254.18.20:61616"); //创建链接对象
connection = connectionFactory.createConnection(); //启动链接
connection.start(); //创建会话
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); //创建目的地
destination = session.createQueue("queue-listener"); //创建消息消费者
consumer = session.createConsumer(destination); //队列服务监听
consumer.setMessageListener(new MessageListener() {
//ActiveMQ回调方法。通过该方法将消息传递到consumer
@Override
public void onMessage(Message message) {
//处理消息
String msg = null;
try {
msg = ((TextMessage) message).getText();
} catch (JMSException e) {
e.printStackTrace();
}
System.out.println("Producer say:" + msg);
}
});
} catch (Exception ex) {
ex.printStackTrace();
}
}
}

3 测试

3.1 provider测试

package cn.arebirth.mq;

public class ProducerTest {
public static void main(String[] args) {
ActiveMQQueueListenerProducer.sendTextActiveMq("Hello,consumer!");
}
}

观察我们的控制台可以发现已经成功发布到队列

3.2 consumer测试

package cn.arebirth.mq;

public class ConsumerTest {
public static void main(String[] args) {
ActiveMQQueueListenerConsumer.receiveTextActiveMq();
}
}

我们运行后可以发现,它接收到了消息,但是它的进程并没有关闭,

我们用provider继续发布一条消息,看看consumer能不能接收到

可以看到,consumer持续在后台监听我们发布的消息,

通过上面代码,不难发现,provider没有任何改动,只是consumer修改了一部分

通过调用匿名内部类的方法来实现持续监听

 consumer.setMessageListener(new MessageListener() {
@Override
public void onMessage(Message message) { } }

注意:因为涉及到队列持续监听,所以我们不能在finally处给资源回收,否则还在监听状态,资源都回收没了,也就无从监听啦。


二 Topic模型

在本系列文章第一篇也有介绍过一些Topic模型的概念,那么这里我们将以原理+实战的方式来带领大家掌握

1 Publish/Subscribe处理模式(Topic)

消息生产者(发布)消息到topic中,同时有多个消息消费者(订阅)消费该消息。

和点对点方式不同,发布到Topic的消息会被所有的订阅者消费,而点对点的只能是指定的消费者去消费

当生产者发布消息,不管是否有消费者,都不会保存消息,也就是说它是发完就啥也不管了那种,

所以要注意:一定要有消费者,然后在有生产者,否则生产者不发完消息什么也不管了,你消费者在生产者之后才有,那么你是接收不到消息的。

接下来我们就以实战的方式鼓捣下。

2 创建生产者

package cn.arebirth.mq;

import org.apache.activemq.ActiveMQConnectionFactory;

import javax.jms.*;

public class ActiveMQTopicProducer {
public static void sendTextActiveMQ(String txt){
//定义链接工厂
ConnectionFactory connectionFactory = null; //定义链接对象
Connection connection = null; //定义会话
Session session = null; //目的地
Destination destination = null; //定义消息的发送者
MessageProducer producer = null; //定义消息
Message message = null; try {
//创建链接工厂
connectionFactory = new ActiveMQConnectionFactory("admin", "admin", "tcp://169.254.18.20:61616"); //创建链接诶对象
connection = connectionFactory.createConnection(); //启动链接
connection.start(); //创建会话
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); //创建目的地
destination = session.createTopic("topic-test"); //创建消息生产者
producer = session.createProducer(destination); //创建消息对象
message = session.createTextMessage(txt); //发送消息
producer.send(message);
} catch (Exception ex) {
ex.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();
}
}
}
}
}

我们可以发现,在创建目的地destination的时候代码有了变动

destination = session.createTopic("topic-test");

变成了createTopic,对这就是topic模式了。

3 创建消费者

package cn.arebirth.mq;

import org.apache.activemq.ActiveMQConnectionFactory;

import javax.jms.*;

public class ActiveMQTopicConsumer implements Runnable {

    public static void receiveTextActiveMQ(String threadName) {
// 定义链接工厂
ConnectionFactory connectionFactory = null;
// 定义链接对象
Connection connection = null;
// 定义会话
Session session = null;
// 目的地
Destination destination = null;
// 定义消息的发送者
MessageConsumer consumer = null;
// 定义消息
Message message = null; try {
//创建链接工厂
connectionFactory = new ActiveMQConnectionFactory("admin", "admin", "tcp://169.254.18.20:61616"); //创建链接对象
connection = connectionFactory.createConnection(); //启动链接
connection.start(); //创建会话
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); //创建目的地
destination = session.createTopic("topic-test"); //创建消息的消费者
consumer = session.createConsumer(destination); //服务监听
consumer.setMessageListener(new MessageListener() {
//ActiveMQ回调方法。通过该方法将消息传递到consumer
@Override
public void onMessage(Message message) {
//处理消息
String msg = null;
try {
msg = ((TextMessage) message).getText();
} catch (JMSException e) {
e.printStackTrace();
}
System.out.println(threadName + "--Producer say:" + msg);
}
});
} catch (Exception ex) {
ex.printStackTrace();
}
} @Override
public void run() {
receiveTextActiveMQ(Thread.currentThread().getName());
}
}

我们可以发现,在创建目的地destination的时候代码有了变动

destination = session.createTopic("topic-test");

还有实现了Runnable这个是为了一会测试的时候,多线程启动,看效果,是否多个都会接受到,(如果看着糊涂的话,你也可以去掉线程的部分,单独复制多个对象,并启动,效果也是一样的)

4 测试(要先启动消费者,否则消费者是接收不到消息的!当然,你自己可以试一下)

4.1 测试消费者

package cn.arebirth.mq;

public class ConsumerTest {
public static void main(String[] args) {
ActiveMQTopicConsumer a1 = new ActiveMQTopicConsumer();
Thread t1 = new Thread(a1,"a1"); ActiveMQTopicConsumer a2 = new ActiveMQTopicConsumer();
Thread t2 = new Thread(a2,"a2"); ActiveMQTopicConsumer a3 = new ActiveMQTopicConsumer();
Thread t3 = new Thread(a3,"a3"); t1.start();
t2.start();
t3.start();
}
}

可以看到,我们的消费者已经启动了,三个线程。并以监听服务的方式启动

4.2 测试生产者

package cn.arebirth.mq;

public class ProducerTest {
public static void main(String[] args) {
ActiveMQTopicProducer.sendTextActiveMQ("hello,topic");
}
}

可以看到,在topics下面,我们发布的内容已经有记录了

然后我们在看下,我们的consumer

可以发现,三个consumer都已经接收到了

ps:

  如果你对ActiveMQ原理性的东西感到困惑,可以看下我们前面的文章:https://www.cnblogs.com/arebirth/p/activemq01.html

ActiveMQ学习总结------原生实战操作(下)03的更多相关文章

  1. ActiveMQ学习总结------Spring整合ActiveMQ 04

    通过前几篇的学习,相信大家已经对我们的ActiveMQ的原生操作已经有了个深刻的概念, 那么这篇文章就来带领大家一步一步学习下ActiveMQ结合Spring的实战操作 注:本文将省略一部分与Acti ...

  2. ActiveMQ学习笔记(5)——使用Spring JMS收发消息

      摘要 ActiveMQ学习笔记(四)http://my.oschina.net/xiaoxishan/blog/380446 中记录了如何使用原生的方式从ActiveMQ中收发消息.可以看出,每次 ...

  3. Java学习心得之 Linux下搭建Java环境

    作者:枫雪庭 出处:http://www.cnblogs.com/FengXueTing-px/ 欢迎转载 Java学习心得之 Linux下搭建Java环境 1.前言2.JDK安装3.配置环境变量4. ...

  4. Ruby学习心得之 Linux下搭建Ruby环境

    作者:枫雪庭 出处:http://www.cnblogs.com/FengXueTing-px/ 欢迎转载 Ruby学习心得之 Linux下搭建Ruby环境1.前言2.Linux下安装Ruby环境 一 ...

  5. CSS学习笔记四:下拉选择框以及其动画特效

    以前学的只是了解了css的一些基本属性,在做项目的时候都是直接使用bootstrap响应式来写项目,这样子很方便,很快捷,但是在自己看来还是有一点缺陷的,毕竟,我很多时候不怎么清楚它里面的具体运作.所 ...

  6. ActiveMQ学习总结(一)

    自己写的网上商城项目中使用了ActiveMQ,虽然相比于RabbitMQ,kafka,RocketMQ等相比,ActiveMQ可能性能方面不是最好的选择,不过消息队列其实原理区别不大,这里对学过的关于 ...

  7. Linux学习心得之 Linux下命令行Android开发环境的搭建

    作者:枫雪庭 出处:http://www.cnblogs.com/FengXueTing-px/ 欢迎转载 Linux学习心得之 Linux下命令行Android开发环境的搭建 1. 前言2. Jav ...

  8. Linux学习心得之 Linux下ant安装与使用

    作者:枫雪庭 出处:http://www.cnblogs.com/FengXueTing-px/ 欢迎转载 Linux学习心得之 Linux下ant安装与使用 1. 前言2. ant安装3. 简单的a ...

  9. Java学习心得之 Linux下搭建JavaWeb环境

    作者:枫雪庭 出处:http://www.cnblogs.com/FengXueTing-px/ 欢迎转载 Java学习心得之 Linux下搭建JavaWeb环境 1. 前言2. Java安装3. t ...

随机推荐

  1. IDC数据中心应具备如下基本条件:

    IDC数据中心应具备如下基本条件: 电力:有充足的直流电力保证,同时还应具备UPS不间断电源及充足的电池组以备用.高端数据中心通常配备柴油发电机等. 环境:符合电信标准的建筑设施,防尘防静电,相对适合 ...

  2. Jmeter 之 逻辑控制器 if 控制器

    最近工作不忙,利用空闲时间整理了下Jmeter的相关知识,下面给大家分享下Jmeter中 如果(if)控制的使用和应用. 如下图:线程组 > 添加 > 逻辑控制器 > 如果 (if) ...

  3. 深入Go的错误处理机制使用

    开篇词 程序运行过程中不可避免的发生各种错误,要想让自己的程序保持较高的健壮性,那么异常,错误处理是需要考虑周全的,每个编程语言提供了一套自己的异常错误处理机制,在Go中,你知道了吗?接下来我们一起看 ...

  4. 虚拟化(三) -vsphere套件的安装注意及使用

    https://www.cnblogs.com/zhrngM/p/9547958.html [转]虚拟化(三):vsphere套件的安装注意及使用 vsphere套件里面主要的组件有esxi.vcen ...

  5. NOIP2009 1.多项式输出

    题目: 其中,aixi称为 i 次项,ai 称为 i 次项的系数.给出一个一元多项式各项的次数和系数,请按照如下规定的格式要求输出该多项式: 1. 多项式中自变量为 x,从左到右按照次数递减顺序给出多 ...

  6. 单点登录(Single Sign On)解决方案

    单点登录(Single Sign On)解决方案 需求 多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统. A 网站和 B 网站是同一家公司的关联服务.现在要求,用户只要在其中一个网 ...

  7. DirectX12 3D 游戏开发与实战第四章内容(上)

    Direct3D的初始化(上) 学习目标 了解Direct3D在3D编程中相对于硬件所扮演的角色 理解组件对象模型COM在Direct3D中的作用 掌握基础的图像学概念,例如2D图像的存储方式,页面翻 ...

  8. RocksDB线程局部缓存

    概述 在开发过程中,我们经常会遇到并发问题,解决并发问题通常的方法是加锁保护,比如常用的spinlock,mutex或者rwlock,当然也可以采用无锁编程,对实现要求就比较高了.对于任何一个共享变量 ...

  9. (七十一)c#Winform自定义控件-折现图

    前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. GitHub:https://github.com/kwwwvagaa/NetWinformControl 码云:ht ...

  10. Java网络编程--Netty中的责任链

    Netty中的责任链 设计模式 - 责任链模式 责任链模式(Chain of Responsibility Pattern)是一种是行为型设计模式,它为请求创建了一个处理对象的链.其链中每一个节点都看 ...