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 ...
随机推荐
- CG-CTF simple-machine
运行一下,输入flag: 用ida打开: input_length和input_byte_804B0C0为重命名的变量:现在一个个看调用的函数. sub_8048526(): 这个函数使用了mmap分 ...
- MySQL存储引擎简单介绍
MySQL使用的是插件式存储引擎. 主要包含存储引擎有:MyISAM,Innodb,NDB Cluster,Maria.Falcon,Memory,Archive.Merge.Federated. 当 ...
- Chinese Mahjong UVA - 11210 (暴力+回溯递归)
思路:得到输入得到mj[]的各个牌的数量,还差最后一张牌.直接暴力枚举34张牌就可以了. 当假设得到最后一张牌,则得到了的牌看看是不是可以胡,如果可以胡的话,就假设正确.否者假设下一张牌. 关键还是如 ...
- 学习storm实现求和操作
1 storm求和简单操作 主要逻辑,就是spout发送数据源,blot进行处理数据,主要注意的点就是 spout这有个nextTuple自旋,和使用父类的declare..方法声明要发送到下游的名称 ...
- TIA Portal V13 WinCC中创建多语言项目
1. 在项目树下选择“语言和资源”,双击打开“项目语言”,设置编辑语言和参考语言. 2. 在项目语言栏中勾选项目所需要的多种语言,我们以选择德语.英语和中文为例 3. 点击“参考语言”,切换语言为英语 ...
- 如何在sqlite3连接中创建并调用自定义函数
#!/user/bin/env python # @Time :2018/6/8 14:44 # @Author :PGIDYSQ #@File :CreateFunTest.py '''如何在sql ...
- MYSQL Statement violates GTID consistency: Updates to non-transactional tables can only be done in either autocommitted statements or single-statement transactions, and never in the same statement as
[2019-04-21 10:17:20] [ERROR] [org.hibernate.engine.jdbc.spi.SqlExceptionHelper:144] Statement viola ...
- 【翻译】asp.net core2.0中的token认证
原文地址:https://developer.okta.com/blog/2018/03/23/token-authentication-aspnetcore-complete-guide token ...
- Django(七)缓存、信号、Form
大纲 一.缓存 1.1.五种缓存配置 1.2配置 2.1.三种应用(全局.视图函数.模板) 2.2 应用多个缓存时生效的优先级 二.信号 1.Django内置信号 2.自定义信号 三.Form 1.初 ...
- 利用layui前端框架实现对不同文件夹的多文件上传
利用layui前端框架实现对不同文件夹的多文件上传 问题场景: 普通的input标签实现多文件上传时,只能对同一个文件夹下的多个文件进行上传,如果要同时上传两个或多个文件夹下的文件,是无法实现的.这篇 ...