Spring rabbitMq 中 correlationId或CorrelationIdString 消费者获取为null的问题
问题
在用Spring boot 的 spring-boot-starter-amqp 快速启动 rabbitMq 是遇到了个坑
消费者端获取不到:correlationId或CorrelationIdString
问题产生的原因
correlationId 的在 spring rabbitmq 2.0 以后 byte方式会被放弃,所以 目前 代码中有些地方没有改过来,应该算一个BUG
@SuppressWarnings("deprecation")
public class DefaultMessagePropertiesConverter implements MessagePropertiesConverter {
@Deprecated
public enum CorrelationIdPolicy {
STRING, BYTES, BOTH
}
private static final int DEFAULT_LONG_STRING_LIMIT = 1024;
private final int longStringLimit;
private final boolean convertLongLongStrings;
private volatile CorrelationIdPolicy correlationIdPolicy = CorrelationIdPolicy.BYTES;
}
/**
* For inbound, determine whether correlationId, correlationIdString or
* both are populated. For outbound, determine whether correlationIdString
* or correlationId is used when mapping; if {@code CorrelationIdPolicy.BOTH}
* is set for outbound, String takes priority and we fallback to bytes.
* Default {@code CorrelationIdPolicy.BYTES}.
* @param correlationIPolicy true to use.
* @deprecated - the byte[] version of correlation id will be removed in 2.0
*/
@Deprecated
public void setCorrelationIdPolicy(CorrelationIdPolicy correlationIPolicy) {
setCorrelationIdAsString(correlationIPolicy);
} @SuppressWarnings("deprecation")
public MessageProperties toMessageProperties(final BasicProperties source, final Envelope envelope,
final String charset) {
MessageProperties target = new MessageProperties();
Map<String, Object> headers = source.getHeaders();
if (!CollectionUtils.isEmpty(headers)) {
for (Map.Entry<String, Object> entry : headers.entrySet()) {
String key = entry.getKey();
if (MessageProperties.X_DELAY.equals(key)) {
Object value = entry.getValue();
if (value instanceof Integer) {
target.setReceivedDelay((Integer) value);
}
}
else {
target.setHeader(key, convertLongStringIfNecessary(entry.getValue(), charset));
}
}
}
target.setTimestamp(source.getTimestamp());
target.setMessageId(source.getMessageId());
target.setReceivedUserId(source.getUserId());
target.setAppId(source.getAppId());
target.setClusterId(source.getClusterId());
target.setType(source.getType());
Integer deliveryMode = source.getDeliveryMode();
if (deliveryMode != null) {
target.setReceivedDeliveryMode(MessageDeliveryMode.fromInt(deliveryMode));
}
target.setDeliveryMode(null);
target.setExpiration(source.getExpiration());
target.setPriority(source.getPriority());
target.setContentType(source.getContentType());
target.setContentEncoding(source.getContentEncoding());
String correlationId = source.getCorrelationId();
if (!CorrelationIdPolicy.BYTES.equals(this.correlationIdPolicy) && correlationId != null) {
target.setCorrelationIdString(correlationId);
}
if (!CorrelationIdPolicy.STRING.equals(this.correlationIdPolicy)) {
if (correlationId != null) {
try {
target.setCorrelationId(source.getCorrelationId().getBytes(charset));
}
catch (UnsupportedEncodingException ex) {
throw new AmqpUnsupportedEncodingException(ex);
}
}
}
String replyTo = source.getReplyTo();
if (replyTo != null) {
target.setReplyTo(replyTo);
}
if (envelope != null) {
target.setReceivedExchange(envelope.getExchange());
target.setReceivedRoutingKey(envelope.getRoutingKey());
target.setRedelivered(envelope.isRedeliver());
target.setDeliveryTag(envelope.getDeliveryTag());
}
return target;
} public BasicProperties fromMessageProperties(final MessageProperties source, final String charset) {
BasicProperties.Builder target = new BasicProperties.Builder();
target.headers(this.convertHeadersIfNecessary(source.getHeaders()))
.timestamp(source.getTimestamp())
.messageId(source.getMessageId())
.userId(source.getUserId())
.appId(source.getAppId())
.clusterId(source.getClusterId())
.type(source.getType());
MessageDeliveryMode deliveryMode = source.getDeliveryMode();
if (deliveryMode != null) {
target.deliveryMode(MessageDeliveryMode.toInt(deliveryMode));
}
target.expiration(source.getExpiration())
.priority(source.getPriority())
.contentType(source.getContentType())
.contentEncoding(source.getContentEncoding());
@SuppressWarnings("deprecation")
byte[] correlationId = source.getCorrelationId();
String correlationIdString = source.getCorrelationIdString();
if (!CorrelationIdPolicy.BYTES.equals(this.correlationIdPolicy)
&& StringUtils.hasText(correlationIdString)) {
target.correlationId(correlationIdString);
correlationId = null;
}
if (!CorrelationIdPolicy.STRING.equals(this.correlationIdPolicy)
&& correlationId != null && correlationId.length > 0) {
try {
target.correlationId(new String(correlationId, charset));
}
catch (UnsupportedEncodingException ex) {
throw new AmqpUnsupportedEncodingException(ex);
}
}
String replyTo = source.getReplyTo();
if (replyTo != null) {
target.replyTo(replyTo);
}
return target.build();
}
解决方法
生产者:
public void topicPublish(String content) {
CorrelationData correlationId = new CorrelationData(UUID.randomUUID().toString());
rabbitTemplate.convertAndSend(AmqpDirectExchangeConfig.FANOUT_EXCHANGE,"",
this.buildMessage(content,correlationId.getId()), correlationId);
this.log.info("消息id-{},消息内容为-{},已发送",correlationId,content);
}
/**
* 返回rabbitTemplate
* @return
*/
@Bean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
//必须是prototype类型
public RabbitTemplate rabbitRtryTemplate() {
RabbitTemplate template = new RabbitTemplate(connectionAckFactory());
template.setMessagePropertiesConverter(defaultMessagePropertiesConverter());
template.setRetryTemplate(rabbitRetry());
template.setReplyTimeout(2000);//2s秒超时
return template;
}
@Bean
public MessagePropertiesConverter defaultMessagePropertiesConverter(){
DefaultMessagePropertiesConverter messagePropertiesConverter=new DefaultMessagePropertiesConverter();
messagePropertiesConverter.setCorrelationIdPolicy(DefaultMessagePropertiesConverter.CorrelationIdPolicy.STRING);
return messagePropertiesConverter;
}
消费者:
/**
* 消息消费者
* @return
*/
@Bean
public SimpleMessageListenerContainer messageContainer() {
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionAckFactory());
container.setQueues(queue1());
container.setExposeListenerChannel(true);
container.setMessagePropertiesConverter(defaultMessagePropertiesConverter());
container.setMaxConcurrentConsumers(1);
container.setConcurrentConsumers(1);
container.setAcknowledgeMode(AcknowledgeMode.MANUAL); //设置确认模式手工确认
container.setMessageListener(new ChannelAwareMessageListener () {
@Override
public void onMessage(Message message, Channel channel) throws Exception {
byte[] body = message.getBody();
MessageProperties messageProperties=message.getMessageProperties();
log.info("消费者A,从队列{},订阅到CorrelationId=[{}],消息body=[{}]",
messageProperties.getConsumerQueue(),
messageProperties.getCorrelationIdString(),
new String(body,"utf-8"));
channel.basicAck(message.getMessageProperties().getDeliveryTag(), false); //确认消息成功消费
}
});
return container;
}
Spring rabbitMq 中 correlationId或CorrelationIdString 消费者获取为null的问题的更多相关文章
- 【String注解驱动开发】面试官让我说说:如何使用FactoryBean向Spring容器中注册bean?
写在前面 在前面的文章中,我们知道可以通过多种方式向Spring容器中注册bean.可以使用@Configuration结合@Bean向Spring容器中注册bean:可以按照条件向Spring容器中 ...
- Spring Boot中使用RabbitMQ
很久没有写Spring Boot的内容了,正好最近在写Spring Cloud Bus的内容,因为内容会有一些相关性,所以先补一篇关于AMQP的整合. Message Broker与AMQP简介 Me ...
- 从Spring容器中获取Bean。ApplicationContextAware
引言:我们从几个方面有逻辑的讲述如何从Spring容器中获取Bean.(新手勿喷) 1.我们的目的是什么? 2.方法是什么(可变的细节)? 3.方法的原理是什么(不变的本质)? 1.我们的目的是什么? ...
- 获取Spring容器中的Bean
摘要 SpringMVC框架开发中可能会在Filter或Servlet中用到spring容器中注册的java bean 对象,获得容器中的java bean对象有如下方法 Spring中的Applic ...
- Spring MVC 中获取session的几种方法
Spring MVC 中使用session是一种常见的操作,但是大家上网搜索一下可以看到获取session的方式方法五花八门,最近,自己终结了一下,将获取session的方法记录下来,以便大家共同学习 ...
- 如何手动获取Spring容器中的bean(ApplicationContextAware 接口)
ApplicationContextAware 接口的作用 先来看下Spring API 中对于 ApplicationContextAware 这个接口的描述: 即是说,当一个类实现了这个接口之 ...
- [十]SpringBoot 之 普通类获取Spring容器中的bean
我们知道如果我们要在一个类使用spring提供的bean对象,我们需要把这个类注入到spring容器中,交给spring容器进行管理,但是在实际当中,我们往往会碰到在一个普通的Java类中,想直接使用 ...
- java 从spring容器中获取注入的bean对象
java 从spring容器中获取注入的bean对象 CreateTime--2018年6月1日10点22分 Author:Marydon 1.使用场景 控制层调用业务层时,控制层需要拿到业务层在 ...
- java web中如何获取spring容器中定义的bean----WebApplicationContext的使用
本文简单编写一个servlet来获取spring容器中管理的<bean id="dateBean" class="java.util.Date" sin ...
随机推荐
- Linux(Manjaro) -Docker 安装及基本配置
Linux(Manjaro) -Docker 安装及基本配置 基本安装 # Pacman 安装 Docker sudo pacman -S docker # 启动docker服务 sudo syste ...
- nexus 10 救砖 安装lineage OS 15 并 root
因为平板自带的谷歌应用太烦人了,想root之后卸载它们. 一.root nexus 10 官方系统 1.把img拷贝到platform-tools(Android官网下载)文件夹 2.platform ...
- UVA - 11090 - Going in Cycle!!(二分+差分约束系统)
Problem UVA - 11090 - Going in Cycle!! Time Limit: 3000 mSec Problem Description You are given a we ...
- Cordova plugin
版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/u010106153/article/details/53418528Cordova plugin工程 ...
- Visual Studio 2019 使用 Live Share
一.前言 Visual Studio 2019 在今天发布(北京时间)了,这次带来了一个比较有趣的 Live Share 功能,使用它可以进行更好的协作开发.主要功能: 更多资料可看官方介绍: Vis ...
- 云计算openstack介绍
一.云计算的前世今生 所有的新事物都不是突然冒出来的,都有前世和今生.云计算也是IT技术不断发展的产物. 要理解云计算,需要对IT系统架构的发展过程有所认识. 请看下 IT系统架构的发展到目前为止大致 ...
- 普通PC通过USB转485串口 ModBus-RTU通信协议控制伺服电机
一.RS485通信 RS485 是半双工通信(2 线制),可以一点对多点进行组网,而且 RS485 是用缆线两端的电压差值来表示传递信号,这与 RS232 电气特性大不一样.RS485 仅仅规定了接收 ...
- 【算法】螺旋方阵 上交OJ1021
输入格式: 输入在一行中给出一个正整数N(<10). 输出格式: 输出N×N的螺旋方阵.每行N个数字,每个数字占3位. 输入样例: 5 1 2 3 4 5 16 17 18 19 6 15 24 ...
- javascript深入浅出——学习笔记(包装对象和类型检测)
3包装对象:https://www.imooc.com/video/5676 当我们尝试把基本类型已对象的方式访问时,javascript会把该基本类型转换为对应的包装类型对象(临时对象),相当于ne ...
- vue.js实战——props单向数据流
Vue2.x通过props传递数据是单向的了,也就是父组件数据变化时会传递给子组件,但是反过来不行. 业务中会经常遇到两种需要改变prop的情况, 一种是父组件传递初始值进来,子组件将它作为初始值保存 ...