convertandsend自动序列化java对象并封装为message,send需手动构建message;前者简化开发、支持messagepostprocessor和correlationdata,后者更底层、适用于精确控制消息格式与性能敏感场景。

convertAndSend 会自动序列化对象,send 必须手动构造 Message
convertAndSend 的核心价值是省去手动封装 Message 的步骤。它接收任意 Java 对象(如 String、User),内部调用配置的 MessageConverter(默认是 SimpleMessageConverter)转成 Message 后再发送;而 send 只接受已构建好的 Message 实例,你得自己处理序列化、设置消息头、body 字节数组等。
常见错误现象:直接传 new User("alice") 给 send 会编译失败——因为类型不匹配;传字符串字面量给 send 也报错,必须写成 new Message("hello".getBytes())。
- 如果你用的是 JSON 序列化(比如
Jackson2JsonMessageConverter),convertAndSend会自动把对象转成 JSON 字节流,并设好content_type=application/json;send不做任何内容协商,全靠你自己填对 -
convertAndSend支持传入MessagePostProcessor做发送前增强(比如加 header、改 priority),send同样支持,但你得先有Message才能传进去 - 性能上差异极小,序列化开销基本一致;但开发效率和可维护性上,
convertAndSend明显更友好
convertAndSend 默认走默认 exchange 和 routingKey,send 更“裸”
convertAndSend(String routingKey, Object object) 和 convertAndSend(String exchange, String routingKey, Object object) 都会委托给底层 send(exchange, routingKey, convertedMessage);而 send(Message message) 版本完全不指定 exchange 或 routingKey,直接发往 AMQP 默认交换机(""),且 routingKey 就是队列名——这意味着它只适用于直连到队列的简单场景,无法用于 fanout/topic 等需要交换机路由的模式。
使用场景举例:你想往 topic.exchange 发送带 user.register routingKey 的消息,send 必须显式调用 send("topic.exchange", "user.register", msg);而 convertAndSend 可以直接用三参数重载,语义更清晰。
- 如果只调用无参
send(Message),RabbitMQ 会尝试把消息投递到与message.getMessageProperties().getRoutingKey()同名的队列——这个值若为空或未设,行为不可控,容易丢消息 -
convertAndSend的所有重载都强制你明确声明目标(哪怕只是空字符串),降低了隐式行为带来的风险
convertAndSend 支持 CorrelationData,send 不直接暴露回调机制
convertAndSend 提供带 CorrelationData 参数的重载(如 convertAndSend(exchange, rk, obj, correlationData)),这是实现生产者确认(publisher confirm)和消息追踪的关键。Spring 会把这个 CorrelationData 的 id 写入消息属性,并在收到 broker 确认/失败时回调你注册的 RabbitTemplate.ConfirmCallback 或 ReturnCallback。
send 方法本身不提供 CorrelationData 入参,你得自己把 correlationId 写进 MessageProperties,再配合手动配置的 callback 使用——绕路且易漏。
- 启用 publisher confirms 需在配置中设
spring.rabbitmq.publisher-confirm-type=correlated,否则CorrelationData无效 - 如果你没配 callback,传了
CorrelationData也不会报错,但回调永远不会触发——这点非常容易被忽略 - 测试时别只看日志有没有 “ACK”,要真断网或关掉 broker,观察
ConfirmCallback是否收到ack=false,才能验证链路完整
别混淆 convertAndSend 和 convertSendAndReceive
convertAndSend 是纯单向发送,不等待响应;而 convertSendAndReceive 是 RPC 模式:它会自动生成 reply-to 队列、发请求、阻塞等待响应、再清理临时队列。两者名字像,但语义完全不同,混用会导致线程卡死或超时异常。
典型误用:在高并发 HTTP 接口里用 convertSendAndReceive 调用下游服务,结果线程池被占满;其实你真正需要的只是异步发出去,用 convertAndSend + 消费端落库 + WebSocket 推送更合理。
-
convertSendAndReceive要求消费者端必须调用replyToAddress或显式返回响应,否则调用方永远等不到 reply - 它的超时由
RabbitTemplate.setReplyTimeout()控制,默认 5 秒;超时后抛AmqpTimeoutException,不是网络异常那种重试逻辑 - 如果你只是想“发完就不管”,却写了
convertSendAndReceive,那说明你根本没理解 RPC 和 fire-and-forget 的边界










