MessageListenerAdapter 默认仅识别 handleMessage 方法,因 SimpleMessageConverter 将消息体转为 String 或 byte[] 后按类型反射匹配方法;若 handler 仅定义 handleMessage(String) 但接收 raw byte[],则匹配失败且静默忽略。

MessageListenerAdapter 默认只认 handleMessage 方法,不配任何东西也能跑,但一发非 byte[] 类型消息就报错——根源在默认的 SimpleMessageConverter 和反射参数匹配逻辑。
为什么 new MessageListenerAdapter(new MyHandler()) 后收不到消息?
常见现象是控制台没输出、日志无调用痕迹,甚至连接都正常。根本原因不是监听器没注册,而是 MessageListenerAdapter 在反射调用前做了两件事:先用 MessageConverter 转换消息体,再按转换后的类型找方法签名。
- 默认使用
SimpleMessageConverter,它把原始Message的body(byte[])直接转成String(UTF-8),前提是contentType是text/plain或未设;否则返回原byte[] - 你的
MyHandler如果只写了public void handleMessage(String s),但发的是 rawbyte[](比如没设contentType),转换后仍是byte[],就会找不到匹配方法,静默失败 - 检查 RabbitMQ 控制台里消息是否堆积,或加断点进
MessageListenerAdapter.extractMessage()看转换结果
怎么让 String / JSON / 自定义对象都能进同一个 handler?
不能靠重载方法,MessageListenerAdapter 只支持单参数方法,且反射时只认「转换后类型」对应的那个方法。正确做法是统一入口 + 手动类型判断:
- 声明一个接收
Object的方法:public void handleMessage(Object obj) - 禁用自动转换:
adapter.setMessageConverter(null),这样obj就是原始Message,可手动调message.getBody()或解析 headers - 或者保留转换器,但改用
Jackson2JsonMessageConverter,并确保发送端contentType="application/json",此时obj就是反序列化后的 POJO - 别写
handleMessage(String)和handleMessage(MyOrder)两个方法——适配器不会自动选,只会报No suitable method found
如何为不同队列绑定不同处理方法?
靠 setQueueToListenerMapping,不是靠注解或继承。键是队列名(字符串),值是目标方法名(字符串),大小写敏感:
Map<String, String> mapping = new HashMap<>();
mapping.put("order.queue", "onOrder");
mapping.put("log.queue", "onLog");
adapter.setQueueToListenerMapping(mapping);
- 对应 handler 类里必须有
public void onOrder(byte[] data)和public void onLog(byte[] data)这两个方法 - 如果某队列没在 map 里,会 fallback 到
defaultListenerMethod(默认handleMessage) - 注意:这个映射只看
queue名,和 exchange、routingKey、consumer tag 都无关 - Spring Boot 用户慎用——
@RabbitListener更直观,MessageListenerAdapter这套配置容易和容器的 auto-declare 冲突
为什么 response 没发出去?
想让 handler 返回值自动变成 reply 消息,必须同时满足三个条件:
- handler 方法返回非
null值(如return "ok") -
SimpleMessageListenerContainer的setExposeListenerChannel(true)已启用(否则拿不到 channel) - 原始入站
Message的replyTo属性必须存在(例如用rabbitTemplate.convertSendAndReceive()发起 RPC 调用时自动带) - 如果只是普通
convertAndSend(),replyTo为空,返回值会被丢弃,连 warning 都没有
最容易被忽略的是 setExposeListenerChannel(true) —— 它默认是 false,文档里提得轻描淡写,但缺了它,response 功能完全失效。

















