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常用保护机制
Linux程序常见用的一些保护机制 一.NX(Windows中的DEP) NX:No-eXecute.DEP:Data Execute Prevention 也就是数据不可执行,防止因为程序运行出现溢 ...
- Bootstrap -- 插件: 按钮状态、折叠样式、轮播样式
Bootstrap -- 插件: 按钮状态.折叠样式.轮播样式 1. 按钮(Button)插件:可以添加进一些交互,比如控制按钮状态. 如需向按钮添加加载状态,只需要简单地向 button 元素添加 ...
- Java基础系列--07_Object类的学习及源码分析
Object: 超类 (1)Object是类层次结构的顶层类,是所有类的根类,超类. 所有的类都直接或者间接的继承自Object类. 所有对象(包括数组)都实现这个类的方法 (2)Object ...
- “百度杯”CTF比赛 十月场 Hash 复现
进入题后老套路得到两个关键: 1.$hash=md5($sign.$key);the length of $sign is 8 2.key=123&hash=f9109d5f83921a551 ...
- Elastic Stack-Elasticsearch使用介绍(三)
一.前言 上一篇说了这篇要讲解Search机制,但是在这个之前我们要明白下文件是怎么存储的,我们先来讲文件的存储然后再来探究机制: 二.文档存储 之前说过文档是存储在分片上的,这里要思考一个问 ...
- Angular CLI 升级 6.0 之后遇到的问题
Angular CLI 1.7.4 在使用 ng build --prod 会构建失败,而 ng build 是正常的.比较好的解决办法是使用 ng build --prod --extract-li ...
- FLOAT 和 DOUBLE区别
以下是 FLOAT 和 DOUBLE 的区别: float : 单精度浮点数 double : 双精度浮点数 ·浮点数以 8 位精度存储在 FLOAT 中,并且有四个字节. ·浮点数存储在 DOUBL ...
- 正则表达式和re模块
目录 re的元字符 字符集[ ] 转义符 分组 ( ) |符号 re下的常用方法 分组 re的元字符 import re ret = re.findall("e..a", &quo ...
- 巧妙使用excel 实现行转列
1. 本来想通过写sql的方式来实现简单的行转列 但是 时间要求很紧 (主要是自己懒 并且sql写的不好. ) 通过同事提醒 以及百度 找到一个很简单的方法,通过excel 来实现. 2. 具体操作步 ...
- DAY22、面向对象
一.复习:1.面向过程与面向对象 过程:程序流程化,可拓展性差 对象:程序流程多样化,可拓展性强 面向对象引入属性 | 方法的概念,通过所属者.语法调用2.拥有名称空间的对象:有__dict__属性, ...