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 ...
随机推荐
- PIC单片机基础1
1.PIC单片机总线结构——哈佛结构:即指令和数据空间是完全分开的,所以与常见的微控制器不同的一点是,程序和数据总线可以采用不同的宽度.以PIC16F684单片机为例,数据总线是8位的,但指令总线位数 ...
- 【spring源码分析】IOC容器初始化(六)
前言:经过前几篇文章的讲解,我们已经得到了BeanDefinition,接下来将分析Bean的加载. 获取Bean的入口:AbstractApplicationContext#getBean publ ...
- js实现搜索记录列表
<div class="sy_div28"> <div class="sy_div23"> <span>搜索历史</s ...
- resnet18全连接层改成卷积层
想要尝试一下将resnet18最后一层的全连接层改成卷积层看会不会对网络效果和网络大小有什么影响 1.首先先对train.py中的更改是: train.py代码可见:pytorch实现性别检测 # m ...
- lvds接口介绍
1.项目简介 用索尼的imx264 sensor采集图像,在内部模数转换之后,由lvds接收,然后解码,最后送给后端显示 2.框图 imx264配置成从模式,由spi总线配置,需要由FPGA提供 行. ...
- JS 设计模式七 -- 模板方法模式
概念 模板方法模式是一直昂只需使用继承就可以实现的非常简单的模式. 模板方法模式由两部分结构组成,第一部分是抽象父类,第二部分是具体实现的子类. 实现 模板方法模式一般的实现方式为继承. // 体育运 ...
- springboot整合Quartz实现定时任务
1.maven依赖: <!--quartz--> <dependency> <groupId>org.quartz-scheduler</groupId> ...
- MySQL之开发规范
一..数据库命名规范 1.所有数据库对象名称必须使用小写字母并用下划线分割 2.所有数据库对象名称禁止使用mysql保留关键字(如果表名中包含关键字查询时,需要将其用单引号括起来) 3.数据库对象的命 ...
- [蓝桥杯]2014蓝桥省赛B组题目及详解
/*——————————————————————————————————————————————————————————— [结果填空题]T1 题目:啤酒和饮料 啤酒每罐2.3元,饮料每罐1.9元.小 ...
- 解决win环境下访问本机虚拟机中centos7 ftp服务器的问题
inux搭建ftp服务器 1.安装软件: yum install vsftpd 2.修改配置文件vsftpd.conf: vim /etc/vsftpd/vsftpd.conf 把anonymous_ ...