消息回调
ConfirmCallback:当消息到达交换机触发回调
ReturnsCallback:消息(带有路由键routingKey)到达交换机,与交换机的所有绑定键进行匹配,匹配不到触发回调
spring:
rabbitmq:
port: 5672
host: 127.0.0.1
username: guest
password: guest
publisher-confirm-type: correlated
publisher-returns: true
# template:
# mandatory: true
package com.yzm.rabbitmq_08.config;
import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.ReturnedMessage;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class RabbitConfig {
/**
* 定义rabbit template用于数据的接收和发送
* connectionFactory:连接工厂
*/
@Bean("rabbit")
public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
RabbitTemplate template = new RabbitTemplate(connectionFactory);
//数据转换为json存入消息队列
template.setMessageConverter(new Jackson2JsonMessageConverter());
/* 若使用 confirm-callback 或 return-callback,需要配置
* publisher-confirm-type: correlated
* publisher-returns: true
*/
template.setConfirmCallback(confirmCallback());
template.setReturnsCallback(returnCallback());
/* 使用return-callback时必须设置mandatory为true,
* 或者在配置中设置rabbitmq.template.mandatory=true
*/
template.setMandatory(true);
return template;
}
public static RabbitTemplate.ConfirmCallback confirmCallback() {
return new RabbitTemplate.ConfirmCallback() {
/**
* 消息到达交换机触发回调
*/
@Override
public void confirm(CorrelationData correlationData, boolean ack, String cause) {
// ack判断消息发送到交换机是否成功
System.out.println("回调id:" + correlationData.getId());
if (ack) {
// 消息发送成功到达交换机
// ...
System.out.println("消息成功到达交换机");
} else {
System.out.println("消息到达交换机失败");
System.out.println("错误信息:" + cause);
}
}
};
}
public static RabbitTemplate.ReturnsCallback returnCallback() {
return new RabbitTemplate.ReturnsCallback() {
/**
* 消息路由失败,回调
* 消息(带有路由键routingKey)到达交换机,与交换机的所有绑定键进行匹配,匹配不到触发回调
*/
@Override
public void returnedMessage(ReturnedMessage returnedMessage) {
System.out.println("交换机:" + returnedMessage.getExchange());
System.out.println("路由键:" + returnedMessage.getRoutingKey());
System.out.println("消息主体 : " + returnedMessage.getMessage());
System.out.println("回复代码 : " + returnedMessage.getReplyCode());
System.out.println("描述:" + returnedMessage.getReplyText());
}
};
}
}
package com.yzm.rabbitmq_08.sender;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.UUID;
@RestController
public class Sender {
@Resource(name = "rabbit")
private RabbitTemplate rabbitTemplate;
@GetMapping("/callback")
public void callback() {
// 全局唯一
CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
String message = "Hello world!";
System.out.println(" [ 生产者 ] Sent ==> '" + message + "'");
rabbitTemplate.convertAndSend("callback.exchange", "callback.a.yzm", message, correlationData);
}
@GetMapping("/callback2")
public void callback2() {
CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
String message = "Hello world!";
System.out.println(" [ 生产者 ] Sent ==> '" + message + "'");
rabbitTemplate.convertAndSend("不存在的交换机", "callback.a.yzm", message, correlationData);
}
@GetMapping("/callback3")
public void callback3() {
CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
String message = "Hello world!";
System.out.println(" [ 生产者 ] Sent ==> '" + message + "'");
rabbitTemplate.convertAndSend("callback.exchange", "不存在的路由键", message, correlationData);
}
}
交换机、队列以及绑定键,通过注解实现
package com.yzm.rabbitmq_08.receiver;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
@Component
public class Receiver {
@RabbitListener(bindings = @QueueBinding(
value = @Queue(value = "callback_queue"),
exchange = @Exchange(value = "callback.exchange"),
key = {"callback.a.yzm", "callback.b.admin"}
))
public void callbackA(Message message) {
System.out.println(" [ 消费者@A号 ] Received ==> '" + new String(message.getBody()) + "'");
}
}
访问http://localhost:8080/callback
运行结果:
消息正确到达交换机触发回调
访问http://localhost:8080/callback2
运行结果:
消息找不到交换机触发回调
访问http://localhost:8080/callback3
运行结果:
消息路由失败触发回调
监听路由失败回调
/**
* 应用:
* 确认消息已经成功发送到队列中,如果未发送成功至队列,可进行消息的重新发送等操作。
*/
@GetMapping("/ret")
public void ret() throws IOException {
Channel channel = rabbitTemplate.getConnectionFactory().createConnection().createChannel(false);
//消息不可达,回调
channel.addReturnListener(new ReturnListener() {
@Override
public void handleReturn(int replyCode, String replyText,
String exchange, String routingKey,
AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println("replyCode:" + replyCode);
System.out.println("replyText:" + replyText);
System.out.println("exchange:" + exchange);
System.out.println("routingKey:" + routingKey);
System.out.println("properties:" + properties);
System.out.println("body:" + new String(body));
}
});
String message = "Hello world!";
System.out.println(" [ 生产者 ] Sent ==> '" + message + "'");
/**
* Mandatory
* 如果设置为ture:就表示的是要监听不可达的消息,然后进行处理
* 如果设置为false:那么队列端会直接删除这个消息(默认值)
*/
channel.basicPublish("callback.exchange", "不存在的路由键", true,
MessageProperties.PERSISTENT_TEXT_PLAIN, message.getBytes());
}