回复管理

现有的支持MessageListener适配器你的方法已经允许非空返回类型。在这种情况下,调用的结果会封装在发送到指定地址的消息中,回复地址原始消息的头部,或者监听器配置的默认地址。您可以通过使用@SendTo消息抽象的注释。spring-doc.cadn.net.cn

假设我们的进程顺序方法现在应返回订单状态,我们可以这样写成,自动发送回复:spring-doc.cadn.net.cn

@RabbitListener(destination = "myQueue")
@SendTo("status")
public OrderStatus processOrder(Order order) {
    // order processing
    return status;
}

如果你需要以与传输无关的方式设置额外的头部,你可以返回消息而是类似以下内容:spring-doc.cadn.net.cn

@RabbitListener(destination = "myQueue")
@SendTo("status")
public Message<OrderStatus> processOrder(Order order) {
    // order processing
    return MessageBuilder
        .withPayload(status)
        .setHeader("code", 1234)
        .build();
}

或者,你也可以使用消息后处理器beforeSendReplyMessagePostProcessors容器工厂属性以添加更多头部。从版本 2.2.3 开始,调用的 bean/method 可以在回复消息中提供,可在消息后处理中将信息反馈给调用者:spring-doc.cadn.net.cn

factory.setBeforeSendReplyPostProcessors(msg -> {
    msg.getMessageProperties().setHeader("calledBean",
            msg.getMessageProperties().getTargetBean().getClass().getSimpleName());
    msg.getMessageProperties().setHeader("calledMethod",
            msg.getMessageProperties().getTargetMethod().getName());
    return m;
});

从2.2.5版本开始,你可以配置回复后处理器在回复消息发送前修改;在发送后调用关联Id首部已被设置为匹配请求。spring-doc.cadn.net.cn

@RabbitListener(queues = "test.header", group = "testGroup", replyPostProcessor = "echoCustomHeader")
public String capitalizeWithHeader(String in) {
    return in.toUpperCase();
}

@Bean
public ReplyPostProcessor echoCustomHeader() {
    return (req, resp) -> {
        resp.getMessageProperties().setHeader("myHeader", req.getMessageProperties().getHeader("myHeader"));
        return resp;
    };
}

从3.0版本开始,你可以在容器工厂配置后处理器,而不是在注释上。spring-doc.cadn.net.cn

factory.setReplyPostProcessorProvider(id -> (req, resp) -> {
    resp.getMessageProperties().setHeader("myHeader", req.getMessageProperties().getHeader("myHeader"));
    return resp;
});

身份证参数是监听者ID。spring-doc.cadn.net.cn

注释中的设置会优先于出厂设置。spring-doc.cadn.net.cn

@SendTo假设 值为回复交换路由键跟随交换/路由密钥模式 其中可以省略其中一个部分。有效值如下:spring-doc.cadn.net.cn

  • 东西1/东西2:这回复交换与路由键.事情1/:这回复交换与默认(空)路由键.东西2/thing2:这回复 路由键以及默认的(空交换)。或空交换:该/回复默认交换与默认路由键.spring-doc.cadn.net.cn

另外,你也可以使用@SendTo没有属性。 此情况等于 空发送模式。@SendTo仅当入站消息没有回复地址财产。spring-doc.cadn.net.cn

从1.5版本开始,@SendTovalue 可以是豆初始化的 SpEL 表达式,如下示例所示:spring-doc.cadn.net.cn

@RabbitListener(queues = "test.sendTo.spel")
@SendTo("#{spelReplyTo}")
public String capitalizeWithSendToSpel(String foo) {
    return foo.toUpperCase();
}
...
@Bean
public String spelReplyTo() {
    return "test.sendTo.reply.spel";
}

该表达式必须取值为字符串可以是一个简单的队列名称(发送到默认交换机),也可以是形式为交换/路由密钥如前述例子所述。spring-doc.cadn.net.cn

#{…​}表达式在初始化时只被评估一次。

对于动态回复路由,消息发送方应包含reply_tomessage 属性或使用替代的运行时 SpEL 表达式(见下一个示例描述)。spring-doc.cadn.net.cn

从1.6版本开始,@SendTo可以是一个在运行时针对请求进行评估的 SpEL 表达式和 reply,如下示例所示:spring-doc.cadn.net.cn

@RabbitListener(queues = "test.sendTo.spel")
@SendTo("!{'some.reply.queue.with.' + result.queueName}")
public Bar capitalizeWithSendToSpel(Foo foo) {
    return processTheFooAndReturnABar(foo);
}

SpEL表达式的运行时性质用以下方式表示! {…​}分隔符。 评估背景#root表达式的对象具有三个性质:spring-doc.cadn.net.cn

上下文包含映射属性访问器、标准类型转换器和豆解析器,使得上下文中的其他豆子可以被引用(例如,@someBeanName.determineReplyQ(请求,结果)).spring-doc.cadn.net.cn

总之,#{…​}在初始化过程中被评估一次,其中#root对象是应用程序上下文。Beans 以名称引用。! {…​}在运行时对每个消息进行评估,根对象具有之前列出的属性。豆子以其名称引用,前缀为 。@spring-doc.cadn.net.cn

从2.1版本开始,也支持简单的属性占位符(例如,${some.reply.to}). 对于早期版本,以下示例可以作为变通方法:spring-doc.cadn.net.cn

@RabbitListener(queues = "foo")
@SendTo("#{environment['my.send.to']}")
public String listen(Message in) {
    ...
    return ...
}