RabbitMQ的消息确认有两种 一种是消息发送确认。这种是用来确认生产者将消息发送给交换器,交换器传递给队列的过程中,消息是否成功投递。发送确认分为两步,一是确认是否到达交换器,二是确认是否到达队列。
第二种是消费接收确认。这种是确认消费者是否成功消费了队列中的消息。
实现当前接口的配置类,当消息向消息队列发送消息时 会自动触发相关回调方法
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
/**
* @author atguigu-mqx
*/
@Component
public class MQProducerAckConfig implements RabbitTemplate.ReturnCallback, RabbitTemplate.ConfirmCallback {
@Autowired
private RabbitTemplate rabbitTemplate;
// 编写一个初始化方法!
@PostConstruct
public void init(){
rabbitTemplate.setReturnCallback(this);
rabbitTemplate.setConfirmCallback(this);
}
/**
* 表示判断消息是否发送到交换机!
* @param correlationData
* @param ack
* @param cause
*/
@Override
public void confirm(CorrelationData correlationData, boolean ack, String cause) {
// 判断
if (ack){
System.out.println("发送成功....");
}else {
System.out.println("发送失败....");
}
}
/**
* 判断当前消息是否能够到队列中! 如果到队列中了,则这个方法不执行! 如果没有到队列中,则方法执行!
* @param message
* @param replyCode
* @param replyText
* @param exchange
* @param routingKey
*/
@Override
public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
// 可以通过判断方式来确切指定哪些是基于延迟插件的交换机路由键 ! 则 return!
// if ("exchange.delay".equals(exchange) && "routing.delay".equals(routingKey)){
// return;
// }
System.out.println("消息主体: " + new String(message.getBody()));
System.out.println("应答码: " + replyCode);
System.out.println("描述:" + replyText);
System.out.println("消息使用的交换器 exchange : " + exchange);
System.out.println("消息使用的路由键 routing : " + routingKey);
}
}
定义发送消息的方法
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* @author atguigu-mqx
*/
@Service
public class RabbitService {
@Autowired
private RabbitTemplate rabbitTemplate;
// 编写发送消息的方法
public Boolean sendMessage(String exchange, String routingKey, Object message){
// 发送消息
this.rabbitTemplate.convertAndSend(exchange,routingKey,message);
// 返回值
return true;
}
生产者 向消息队列发送消息
//想要往交换机发送消息 只需要调用发送消息的方法 往交换机发送消息就可以了
//发送消息的三个参数需要跟消息监听器中的 交换机 消息队列的名称 和 路由Key对应上
消费者 监听消息队列 并确认消息
// 监听消息:
@SneakyThrows
@RabbitListener(bindings = @QueueBinding(
//=======参数1:消息队列名称 参数2:是否过期 参数3:不自动删除
value = @Queue(value = "消息队列名称,一般是从定义的常量类中取出",durable = "true",autoDelete = "false"),
//=========参数:交换机名称,当前名称是从常量类中取出
exchange = @Exchange(value = MqConst.EXCHANGE_DIRECT_PAYMENT_PAY),
//========交换机连接消息队列的 路由key,这里直接从常量类中取的数据
key = {MqConst.ROUTING_PAYMENT_PAY}
))
public void updateOrderStatus(Long orderId,Message message,Channel channel){
/**
这里写业务逻辑代码
*/
// 一定要确认消息,被消费掉!当前方法可以批量拒绝多条消息
//basicNack(long deliveryTag, boolean multiple, boolean requeue)
//deliveryTag:该消息的index。multiple:是否批量. true:将一次性拒绝所有小于deliveryTag的消息。requeue:被拒绝的是否重新入队列。
channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
}
最后一定要记得 创建交换机和相关消息队列还有设置交换机和消息队列直接的路由Key
import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;
/**
* @author atguigu-mqx
注意:这个类中只是演示了 交换机和消息队列的初始化
即:一个交换机绑定一个消息队列
*/
@Configuration
public class DelayedMqConfig {
// 一个交换机一个队列一个绑定关系!
public static final String exchange_delay = "exchange.delay";
public static final String routing_delay = "routing.delay";
public static final String queue_delay_1 = "queue.delay.1";
// 定义交换机
@Bean
public CustomExchange delayExchange(){
// 设置参数
HashMap<String, Object> map = new HashMap<>();
//设置交换机的类型
map.put("x-delayed-type","direct");
// 第二个参数固定值!
return new CustomExchange(exchange_delay,"x-delayed-message",true,false,map);
}
// 定义队列
@Bean
public Queue delayQueue(){
// 返回队列 设置消息队列名称,消息不过期,消息不自动删除等参数
return new Queue(queue_delay_1,true,false,false);
}
// 定义绑定关系 定义交换机和消息队列是用哪个 路由Key连接的
@Bean
public Binding delayBinding(){
// 返回绑定关系!
return BindingBuilder.bind(delayQueue()).to(delayExchange()).with(routing_delay).noargs();
}
}