目录
一、添加依赖
在构建springboot项目的时候添加RabbitMQ依赖
二、编写配置信息和配置类
在application.yml文件配置信息
#配置rabbitmq
spring:
rabbitmq:
host: 192...
port: 5672
username: yygs
password: yygs
virtual-host: /
#日志格式
logging:
pattern:
console: '%d{HH:mm:ss.SSS} %clr(%-5level) --- [%-15thread] %cyan(%-50logger{50}:%msg%n)'
编写配置类,包括交换机,队列,以及将交换机和队列进行绑定
import org.springframework.amqp.core.*;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class RabbitConfig {
private final String EXCHANGE_NAME = "boot_topic_exchange";
private final String QUEUE_NAME = "boot_queue";
//创建交换机
@Bean("bootExchange")
public Exchange getExchange() {
return ExchangeBuilder
.topicExchange(EXCHANGE_NAME) //交换机类型
.durable(true) //是否持久化
.build();
}
//创建队列
@Bean("bootQueue")
public Queue getMessageQueue() {
return QueueBuilder
.durable(QUEUE_NAME) //队列持久化
.ttl(10000) // 队列每条消息存活时间10s
.build();
}
//交换机绑定队列
@Bean
public Binding BindMessageQueue(@Qualifier("bootExchange") Exchange exchange, @Qualifier("bootQueue") Queue queue) {
return BindingBuilder
.bind(queue)
.to(exchange)
.with("#.message.#")
.noargs();
}
}
三、创建生产者
package com.yygs.demo;
import org.junit.jupiter.api.Test;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import javax.annotation.Resource;
@SpringBootTest
public class TestProducer {
// 注入RabbitTemplate工具类
@Resource
private RabbitTemplate rabbitTemplate;
@Test
public void testSendMessage(){
/*
* 参数1:交换机名字
* 参数2:路由键
* 参数3:消息主体
*/
rabbitTemplate.convertAndSend("boot_topic_exchange", "message","消息");
}
}
四、创建消费者
消费者同样要编写application.yml来监听队列
然后消费者类:
package com.yygs.demo;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
@Component
public class Consumer {
// 监听队列
@RabbitListener(queues = "boot_queue")
public void listenMessage(String message) {
System.out.println("接受消息:" + message);
}
}
五、消息可靠性投递
有三种模式。
RabbitMQ消息投递的路径为:
生产者 ---> 交换机 ---> 队列 ---> 消费者
在RabbitMQ工作的过程中,每个环节消息都可能传递失败,那么 RabbitMQ是如何监听消息是否成功投递的呢?
确认模式(confirm)可以监听消息是否从生产者成功传递到交换机。
退回模式(return)可以监听消息是否从交换机成功传递到队列。
消费者消息确认(Consumer Ack)可以监听消费者是否成功处理消息。
1. 确认模式
application.yml
#配置rabbitmq
spring:
rabbitmq:
host: 192...
port: 5672
username: yygs
password: yygs
virtual-host: /
#开启确认模式
publisher-confirm-type: correlated
#日志格式
logging:
pattern:
console: '%d{HH:mm:ss.SSS} %clr(%-5level) --- [%-15thread] %cyan(%-50logger{50}:%msg%n)'
生产者
@SpringBootTest
public class TestProducer {
// 注入RabbitTemplate工具类
@Resource
private RabbitTemplate rabbitTemplate;
@Test
public void testSendMessage(){
// 定义确认模式的回调放啊发,消息向交换机发送后会会调用confirm方法
rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
/**
*被调用的回调方法
* @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("confirm接受失败,原因是:" + cause);
// 做一些处理,让消息再次发送
}
}
});
/*
* 参数1:交换机名字
* 参数2:路由通配符
* 参数3:消息主体
*/
rabbitTemplate.convertAndSend("boot_topic_exchange", "message","消息");
}
}
2. 退回模式
application.yml配置
#配置rabbitmq
spring:
rabbitmq:
host: 192...
port: 5672
username: yygs
password: yygs
virtual-host: /
#开启确认模式
publisher-confirm-type: correlated
#开启退回模式
publisher-returns: true
#日志格式
logging:
pattern:
console: '%d{HH:mm:ss.SSS} %clr(%-5level) --- [%-15thread] %cyan(%-50logger{50}:%msg%n)'
生产者
@Test
public void testReturn(){
// 定义退回模式的回调方法
rabbitTemplate.setReturnsCallback(new RabbitTemplate.ReturnsCallback() {
/**
* @param returned 失败后将失败信息封装发到参数中
*/
@Override
public void returnedMessage(ReturnedMessage returned) {
System.out.println("消息对象:" + returned.getMessage());
System.out.println("错误码:" + returned.getReplyCode());
System.out.println("错误信息:" + returned.getReplyText());
System.out.println("交换机:" + returned.getExchange());
System.out.println("路由键:" + returned.getRoutingKey());
}
});
rabbitTemplate.convertAndSend("boot_topic_exchange", "message","消息");
}
3. ack签收
application.yml配置
#配置rabbitmq
spring:
rabbitmq:
host: 192...
port: 5672
username: yygs
password: yygs
virtual-host: /
#开启消息自动签收
listener:
simple:
acknowledge-mode: none
#日志格式
logging:
pattern:
console: '%d{HH:mm:ss.SSS} %clr(%-5level) --- [%-15thread] %cyan(%-50logger{50}:%msg%n)'
消费者
import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import java.io.IOException;
public class AckConsumer {
@RabbitListener(queues = "boot_queue")
public void listenMessage(Message message, Channel channel) throws IOException {
// 消息投递序号,消息每次投递该值都会+1
long deliveryTag = message.getMessageProperties().getDeliveryTag();
try {
// 签收消息
System.out.println(new String(message.getBody()));
/**
* 参数1:消息投递序号
* 参数2:是否一次可以签收多条消息
*/
channel.basicAck(deliveryTag, true);
}catch (Exception e) {
// 拒签消息
/**
* 参数1:消息投递序号
* 参数2:是否一次可以签收多条消息
* 参数3:拒签后消息是否重回队列
*/
channel.basicNack(deliveryTag, true, true);
}
}
}