spring-rabbit 中MessageListenerAdapter类

本文深入解析MessageListenerAdapter在处理RabbitMQ消息时的灵活使用方法,包括消息类型转换、响应消息生成及配置细节。通过具体代码示例,详细展示了如何将普通POJO类适配为MessageListener,以及XML配置方式与自动消息转换机制。重点讨论了避免混淆的方法名选择,并提供了基于Java和XML的配置实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Message listener adapter adapter that delegates the handling of messages to target listener methods via refection, with flexible message tyep conversion. Allows listener methods to operate on message content types, completely independent from the Rabbit API.

 

By default, the content of incoming Rabbit messges gets extracted before being passed into the target listener method, to let the target method operate on message content tyeps such as String or byte array instead of the raw 'Message'. Message type conversion is delegated to a Spring AMQ 'MessageConverter'. Be default, a 'SimpleMessageConverter' will be used. (If you do not want such automatic message conversijon taking palce, then be sure to set the 'setMessageConverter MessageConverter' to 'null'.)

 

If a target listener method returns a non-null object (typically of a message content type such as String or byte array), it will get wrapped in a Rabbit 'Message' and sent to the exchange of the incoming message with the routingKey that comes from the Rabbit ReplyTo property or via 'setResponseRoutingKey(String) spicified routingKye').

 

Note: The sending of response messges is only available when using the 'ChannelAwareMessageListener' entry point (typically through a Spring message listener container). Usage as 'MessageListener' does 'not' support the generation of response messages.

 

Find below some examples of method signaures compliant with this adapter class. This first example handles all 'Message' types and gets passed the contents of each 'Message' type as an argument. No 'Message' will be sent back as all of these methods return 'void'.

 

 

public interface MessageContentsDelegate {
    void handleMessage(String text);

    void handleMessage(Map map);

    void handleMessage(byte[] bytes);

    void handleMessage(Serializable obj);
}

 This next example handle a 'Message' delegate that just consumes the 'String' contents of 'Message Messages'. Notice also how the name of the 'Message' handling method is different from the 'ORIGINAL_DEFAULT_LISTENER_METHOD original' (this will have to be configured in the attandant bean definition). Again, no 'Message' will be sent back as the method returns 'void'.

 

 

public interface TextMessageContentDelegate {
    void onMessage(String text);
}

 This final example illustrates a 'Message' delegate that just consumes the 'String' contents of 'Message Messages'. Notice how the return type of this method is 'String': This will result in the configured 'MessageListenerAdapter' sending a 'Message' in response.

 

 

public interface ResponsiveTextMessageContentDelegate {
    String handleMessage(String text);
}

For further examples and discussion please do refer to the Spring reference documentation which describes. this class (and its attendant XML configuration) in detail.

 

开始解释坑爹的地方,众所周知,MessageListener接口为

 

 

public interface MessageListener {
    void onMessage(Message message);
}

上面的the next example中也使用了onMessage方法,于是我以为可以直接写一个带有这个方法的pojo类让MessageListenerAdapter适配,结果很显然悲剧。注释中的“Notice also how the name of the 'Message' handling method is different from the 'ORIGINAL_DEFAULT_LISTENER_METHOD original' (this will have to be configured in the attandant bean definition).”开始没怎么明白,后来才知道“this will have to be configured in the attandant bean definition”告诉我们要使用onMessage方法,请修改Bean的配置,将ORIGINAL_DEFAULT_LISTENER_METHOD设置成'onMessage'!哎,为什么用onMessage这个容易浑淆的方法名作例子呢?

 

/**
 * Out-of-the-box value for the default listener method: "handleMessage".
 */
public static final String ORIGINAL_DEFAULT_LISTENER_METHOD = "handleMessage";
 

2011.3.14 12:47 更新

如果采用java-based的配置:

 

package asynchronous.consumer;

import org.springframework.amqp.core.MessageListener;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ExampleAmqpConfiguration {

	@Autowired
	private ConnectionFactory connectionFactory;
	
	@Bean
	public SimpleMessageListenerContainer messageListenerContainer() {
		SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
		container.setConnectionFactory(connectionFactory);
		container.setQueueNames("myqueue");
		container.setMessageListener(exampleListener());
		return container;
	}
	
	@Bean
	public ExampleListener plainExampleListener() {
		ExampleListener exampleListener = new ExampleListener();
		return exampleListener;
	}
	
	@Bean
	public MessageListener exampleListener() {
		MessageListener listener = new MessageListenerAdapter(plainExampleListener());
		return listener;
	}
	
}

 

 将一个简单的POJO通过MessageListenerAdapter代理成MessageListener,在注入到SimpleMessageListenerContainer。

那么XML配置又是怎样的呢?截取一个配置片段:

 

<bean id="textMessageContentListener"
		class="stephansun.github.samples.amqp.spring.listeneradapter.TextMessageContentListener"/>
		
	<rabbit:listener-container connection-factory="connectionFactory">
		<rabbit:listener ref="textMessageContentListener" queues="myqueue" method="handleMessage"/>
	</rabbit:listener-container>

 

 可以看出XML配置文件不需要我们知道MessageListenerAdapter类,关键点在<rabbit:listener/>Element的method Node上,看注释:

 

Attribute : method
The name of the listener method to invoke. If not 
 specified, the target bean is supposed to implement 
 the MessageListener or ChannelAwareMessageListener 
 interface.

Data Type : string

 如果没有写method,Spring会认为你ref的Bean是一个实现了MessageListener和ChanelAwareMessage接口的类,这两个接口分别有onMessage(Message message)和onMessage(Message message, Channel channel)方法。只有写了method,Spring才会调用MessageListenerAdapter来适配你的POJO类,并默认将method对应的方法变成监听消息的处理方法。默认handleMessage,所以想使用XML配置文件,即使自己写的POJO也是MessageListenerAdapter中默认的适配的handleMessage方法,也是必须在在XML中写上method="handleMessage"。

 

 

 

 

 

 

### Spring AMQP 教程 Spring AMQP 是一种用于简化 Spring 应用程序与支持 AMQP 的消息代理(尤其是 RabbitMQ)集成的框架[^1]。通过此框架,开发人员可以更轻松地实现消息驱动的应用逻辑。 #### 配置指南 为了使应用程序能够利用 Spring AMQP 功能,在 `pom.xml` 或者构建文件中添加依赖项: 对于 Maven 用户来说,应该加入如下依赖: ```xml <dependency> <groupId>org.springframework.amqp</groupId> <artifactId>spring-rabbit</artifactId> <version>${spring-amqp.version}</version> </dependency> ``` 接着配置连接工厂以及声明交换器、队列和其他必要的资源。下面是一个简单的 Java Config 示例来设置这些组件: ```java @Configuration public class AmqpConfig { @Bean public ConnectionFactory connectionFactory() { CachingConnectionFactory factory = new CachingConnectionFactory("localhost"); return factory; } @Bean public SimpleMessageListenerContainer container(ConnectionFactory connectionFactory, MessageListenerAdapter listenerAdapter) { SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(); container.setConnectionFactory(connectionFactory); container.setQueueNames("myqueue"); container.setMessageListener(listenerAdapter); return container; } } ``` #### 常见问题及解决方案 - **连接超时** 当遇到网络不稳定或其他原因导致无法建立到 MQ 服务器的有效链接时,可能会发生这种情况。为此,Spring AMQP 提供了一种自动重试机制,允许在初次尝试失败之后再次发起请求直到成功为止[^3]。 - **消费者丢失消息** 如果发现某些情况下消费者未能接收到预期中的全部消息,则可能是由于确认模式不当造成的。确保已正确设置了手动应答模式,并且只有在处理完每条记录后再向 broker 发送 ACK 确认信号。 - **生产者发送异常** 有时即使已经建立了稳定可靠的通道,仍然会因为各种因素而触发异常情况下的消息投递失败事件。此时可以通过监听回调接口捕获此错误并采取适当措施加以应对。 #### 实际应用案例分析 假设有一个电商系统需要异步通知订单状态更新给其他微服务实例;这时就可以借助于 Spring Boot 和 Spring AMQP 来快速搭建起一套健壮高效的分布式通信架构。具体做法是在下单完成后立即将相关信息封装成 JSON 字符串形式并通过 RabbitTemplate 对象推送到指定的主题下等待订阅方消费。 ```java @Autowired private RabbitTemplate rabbitTemplate; // ... rabbitTemplate.convertAndSend("order.exchange", "routing.key", orderJsonString); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值