RabbitMQ --- 直连交换机 【 有回调方法,获取消费结果 】
1.前言
上一随笔详细记录了直连交换机的方法,发送的消息是异步的,如果消息未被消费者消费,那么可以一直存在消息队列中。
那么有没有办法做一个回调,当消息被消费后,被通知消息成功被消费者消费啦?
答案是有的。
需要在消息生产者的消息生产类实现 RabbitTemplate.ConfirmCallback 接口,重写 回调方法confirm(),
同时 RabbitTemplate 模板工具需要自定义注入连接rabbitmq的连接工厂对象才可以正常执行回调操作。
而消费者端的代码不需要修改。
下面演示,以上一节随笔为基础,修改消息生产者部分代码实现演示,随笔地址https://www.cnblogs.com/c2g5201314/p/13156932.html
总结:
(1)异步操作,获取回调消费结果,需要实现RabbitTemplate.ConfirmCallback 接口,然后重写 confirm()方法。
(2)获取回调结果,指的是获取消息是否被消费端正常消费而返回的结果,并不是消费端返回
的处理结果,这一点得注意,如果需要等待消费端返回处理结果,则需要做同步操作,
而不是做回调操作。
(3)需要做同步操作时,应该rabbitTemplate.convertSendAndReceive()方法,返回结果类型是Object,需要根据消费端返回的数据类型来决定强转的类型。
(4)异步则使用rabbitTemplate.convertAndSend()方法。
2.操作
(1)修改配置类,添加自定义RabbitTemplate模板
完整源码
package com.example.rabbitmqproducer1004.config; import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; /**
* rabbitmq配置类---消息生产者
*/
@Configuration
public class RabbitmqConfig {
//日志记录器
Logger logger = LoggerFactory.getLogger(getClass()); //===========================================================
/**
* 手动配置RabbitTemplate 是为了获得回调操作,否则无法执行获取消费结果
*/ /**
* 获取rabbitmq的登录信息
*/
//ip地址
@Value("${spring.rabbitmq.host}")
private String host;
//端口号
@Value("${spring.rabbitmq.port}")
private int port;
//账号
@Value("${spring.rabbitmq.username}")
private String username;
//密码
@Value("${spring.rabbitmq.password}")
private String password; /**
* 设置连接工厂
*/
@Bean
public ConnectionFactory connectionFactory() {
//实例缓存连接工厂,参数是 rabbitmq的ip和端口
CachingConnectionFactory factory = new CachingConnectionFactory(host, port);
//登录用户名
factory.setUsername(username);
//登录密码
factory.setPassword(password);
//设置主机的虚拟路径
factory.setVirtualHost("/");
//确认是否发布
factory.setPublisherConfirms(true);
return factory;
} /**
* 设置rabbitmq模板
*/
@Bean
public RabbitTemplate rabbitTemplate() {
//将连接工程工厂对象注入模板里,然后返回一个模板对象
return new RabbitTemplate(this.connectionFactory()); } //=====================================================================
/**
* 定义 交换机、消息队列、路由键 的名字
*/ //定义交换机名字 exchange
public static final String EXCHANG_1 = "exchange_1"; //定义消息队列名字 queue
public static final String QUEUE_1 = "queu_1"; //定义路由键 routingkey
public static final String ROUTINGKEY_1 = "routing_1"; //=============================================================== /**
* 下面的是 直连交换机 设置 绑定 消息队列 到 交换机
*
* DirectExchange:直连交换机,按照routingkey分发到指定队列
*/
//============================================== /**
* 设置交换机类型
*/
@Bean
public DirectExchange directExchange() {
logger.warn("设置交换机类型");
//实例交换机对象,然后注入该交换机的名字
return new DirectExchange(EXCHANG_1);
} /**
* 创建消息队列
*/
@Bean
public Queue queue1() {
logger.warn("创建消息队列");
//实例消息队列对象,输入该队列名字,如果需要该队列持久化,则设为true,默认是false
// return new Queue(QUEUE_1, true);
return new Queue(QUEUE_1);
} /**
* 绑定 消息队列 到 交换机【一个 交换机 允许被多个 消息队列 绑定】
*/
@Bean
public Binding binding() {
logger.warn("绑定 消息队列 到 交换机");
//使用绑定构造器将 指定的队列 绑定到 指定的交换机上 ,Direct交换机需要携带 路由键
return BindingBuilder.bind(queue1()).to(directExchange()).with(ROUTINGKEY_1);
} }
(2)修改消息生产类
实现接口
重写回方法
使用构造注入RabbitTemplate模板对象
完整源码
package com.example.rabbitmqproducer1004.rabbitmqFactory; import com.example.rabbitmqproducer1004.config.RabbitmqConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component; import java.util.UUID; /**
* 消息生产类
*/
@Component
//实现接口
//public class SendMessage { //需要设置回调方法,获取消费结果才需要实现 RabbitTemplate.ConfirmCallback 接口,
public class SendMessage implements RabbitTemplate.ConfirmCallback {
Logger logger = LoggerFactory.getLogger(this.getClass()); //======================================================================
/**
* 方法一:设置回调方法,获取消费结果,
* <p>
* 缺点是:必须手动配置RabbitTemplate模板 ,代码量大
*/ //存储 rabbitmq模板的临时变量
private final RabbitTemplate rabbitTemplate; /**
* 构造注入rabbitmq模板,这样可以设置回调方法,获取消费结果,但是必须手动配置RabbitTemplate模板
*/
@Autowired
public SendMessage(RabbitTemplate rabbitTemplate) {
this.rabbitTemplate = rabbitTemplate;
//设置确认回调的方法,参数类型为ConfirmCallback
this.rabbitTemplate.setConfirmCallback(this);
} /**
* 回调方法,获取消费结果
*
* @param correlationData 关联数据
* @param b 消息是否被消费成功,成功为true ,失败为false
* @param s 原因 ,消费成功则返回null,否则返回失败原因
*/
@Override
public void confirm(CorrelationData correlationData, boolean b, String s) {
logger.warn("回调的连接数据:" + correlationData);
if (correlationData != null) {
//CorrelationData [id=1bcab025-2b4c-4f74-a22d-41007e30f551]
logger.warn("获取correlationData的id值:" + correlationData.getId());
}
//1bcab025-2b4c-4f74-a22d-41007e30f551
if (b) {
logger.warn("回调结果:消息消费成功");
} else {
logger.warn("回调结果:失败。原因:" + s);
}
} //========================================================================
// /**
// * 方法二 :不需要获取获取消费结果,只需要发送即可
// *
// * 优点:自动装配,代码量少
// */
// @Autowired
// private RabbitTemplate rabbitTemplate; //======================================================================== /**
* 发送消息
* <p>
* 参数是消息内容
*/
public void send(String message) {
logger.warn("发送消息,内容:" + message);
/**
* 方法一:异步操作,不等待消费者端返回处理结果,设置在回调操作的关联数据,用于识别是哪一条消息和确认是否执行成功
*/
// 实例关联数据对象,使用UUID随机数 作为 回调id
CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
// 发送消息 ,参数分别是 : 指定的交换机名字 、指定的路由关键字、消息字符串、关联数据
rabbitTemplate.convertAndSend(RabbitmqConfig.EXCHANG_1,RabbitmqConfig.ROUTINGKEY_1,message,correlationData);
/**
* 方法二:异步操作,不等待消费者端返回处理结果,且在消息回调操作的关联数据为null,如果不做回调操作,则建议这样使用
*/
// //发送消息 ,参数分别是 : 指定的交换机名字 、指定的路由关键字、消息字符串
// rabbitTemplate.convertAndSend(RabbitmqConfig.EXCHANG_1, RabbitmqConfig.ROUTINGKEY_1, message);
/**
* 方法三:同步操作,等待消费者端返回处理结果
*/
// Object dd = rabbitTemplate.convertSendAndReceive(RabbitmqConfig.EXCHANG_1, RabbitmqConfig.ROUTINGKEY_1, message);
// logger.warn("结果是什么???==" + dd);
} }
3.测试
依次启动生产者端、消费者端
访问网址 http://localhost:1004/mq?msg=你大爷,帮我发短信3999
查看生产者控制台打印
对调成功
再看看消费者的打印台
成功!!!撒花
RabbitMQ --- 直连交换机 【 有回调方法,获取消费结果 】的更多相关文章
- RabbitMQ --- 直连交换机 【 同步操作,等到消费者处理完后返回处理结果 】
1.前言 RabbleMQ这种消息中间件,主要的功能是使用异步操作,来达到解耦的目的,比如,有系统a和系统b, 系统a通过消息中间件通知系统b来做业务,那么系统a只需要把要做的事情[也就是消息]发给消 ...
- RabbitMQ --- 直连交换机 【 无回调方法,不能获取消费结果 】
1.前言 消息队列除了kafka 外,还有许多种,比如RabbitMQ .ActiveMQ.ZeroMQ.JMQ等. 老牌的ActiveMQ ,底层使用Java写的,资源消耗大,速度也慢,但是适合 J ...
- rabbitmq学习(二):rabbitmq(消息队列)的作用以及rabbitmq之直连交换机
前言 上篇介绍了AMQP的基本概念,组成及其与rabbitmq的关系.了解了这些东西后,下面我们开始学习rabbitmq(消息队列)的作用以及用java代码和rabbitmq通讯进行消息发布和接收.因 ...
- RabbitMQ指南之四:路由(Routing)和直连交换机(Direct Exchange)
在上一章中,我们构建了一个简单的日志系统,我们可以把消息广播给很多的消费者.在本章中我们将增加一个特性:我们可以订阅这些信息中的一些信息.例如,我们希望只将error级别的错误存储到硬盘中,同时可以将 ...
- jquery通过ajax方法获取json数据不执行success回调
问题描述:jquery通过ajax方法获取json数据不执行success回调方法 问题原因:json格式存在问题或不符合标准写法,导致总是执行error回调方法 解决方案:使json格式务必符合下述 ...
- 微信授权登录,关于调不起授权页面,无法响应回调方法,获取不到code 详解
前期准备工作:申请AppId,下载资源包jar.文档等. 微信授权登录步骤: 1. 第三方发起微信授权登录请求,微信用户允许授权第三方应用后,微信会拉起应用或重定向到第三方网站,并且带上授权临时票据c ...
- SpringCloudStream学习(二)RabbitMQ中的交换机跟工作模式
知识储备: 交换机: RabbitMQ中有4中交换机,分别是 (FANOUT)扇形交换机: 扇形交换机是最基本的交换机类型,它所能做的事情非常简单---广播消息.扇形交换机会把能接收到的消息全部发 ...
- rabbitmq之队列性能测试及优化方法(六)
前言 下面关注一下rabbitmq实际使用时的性能问题和怎么进行一些优化. 性能测试 针对每个需要生产/消费者与rabbitmq进行通讯的方法进行测试 测试环境 排除网络IO的干扰,采用生产者和消费者 ...
- 使用rabbitmq手动确认消息的,定时获取队列消息实现
描述问题 最近项目中因为有些数据,需要推送到第三方系统中,因为数据会一直增加,并且需要与第三方系统做相关交互. 相关业务 本着不影响线上运行效率的思想,我们将增加的消息放入rabbitmq,使用另一个 ...
随机推荐
- Go语言核心36讲(Go语言实战与应用二十四)--学习笔记
46 | 访问网络服务 前导内容:socket 与 IPC 人们常常会使用 Go 语言去编写网络程序(当然了,这方面也是 Go 语言最为擅长的事情).说到网络编程,我们就不得不提及 socket. s ...
- 【Spark】【RDD】初次学习RDD 笔记 汇总
RDD Author:萌狼蓝天 [哔哩哔哩]萌狼蓝天 [博客]https://mllt.cc [博客园]萌狼蓝天 - 博客园 [微信公众号]mllt9920 [学习交流QQ群]238948804 目录 ...
- 2、Spring的IOC标签介绍以及实例
一.Spring_ioc配置文件bean标签介绍 1. bean标签 名称:bean 类型:标签 归属:beans标签 作用:定义spring中的资源,受此标签定义的资源将受到spring控制 格式: ...
- Nginx配置访问黑名单
目录 一.简介 二.脚本 一.简介 有的时候需要将某些大访问量的ip加入到黑名单中 二.脚本 1.脚本内容为,检测本地并发访问超过15并且是ip地址,则加入nginx黑名单中.其中的53a是deny行 ...
- tcache poisoning(爆破stout获得libc并且熟练使用了realloc)
这道题目帮助我学习了realloc这个函数,是一道十分经典的题目,我会尽量的把exp的每一步都说清楚 例行检查我就不放了 讲程序放入ida中 比较简单的流程,没有show功能,所有我们需要通过爆破st ...
- 在React中使用 react-router-dom 编程式路由导航的正确姿势【含V5.x、V6.x】
## react-router-dom 编程式路由导航 (v5) ###### 1.push跳转+携带params参数 ```jsx props.history.push(`/b/child1/${i ...
- 三、Uniapp+vue+腾讯IM+腾讯音视频开发仿微信的IM聊天APP,支持各类消息收发,音视频通话,附vue实现源码(已开源)-配置项目并实现IM登录
项目文章索引 1.项目引言 2.腾讯云后台配置TXIM 3.配置项目并实现IM登录 4.会话好友列表的实现 5.聊天输入框的实现 6.聊天界面容器的实现 7.聊天消息项的实现 8.聊天输入框扩展面板的 ...
- Mybatis一对一、一对多级联查询使用
在A对象的xml配置文件中 一对一<association property="shop" column="shop_id" select="c ...
- 优化MySQL占用内存过高
打开mysql 的配置文件 my.cnf 查找方式:https://www.cnblogs.com/pxblog/p/13701211.html 在[mysqld]后面修改或添加 # The max ...
- cmake之指定clang(++)编译器为默认编译器
1.说明 本文演示环境的cmake版本3.18 clang是自己源码安装的,非获取已经编译好的binary 2.代码 2.1 添加下面的代码到CMakeLists.txt中,且放到 project语句 ...