目录
基本组件定义(org.springframework.amqp.core)
消息发送(org.springframework.amqp.rabbit.core)
配置文件
springboot-rabbitMq全量配置说明与使用 - 知乎 (zhihu.com)
Qos
就是配置文件中prefetch。
Springboot与RabbitMQ上手学习之Qos限流(四) - 简书 (jianshu.com)
SpringCloud10-Springboot 整合RabbitMQ - SegmentFault 思否
获取rabbitmq连接
最后的boolean不知道作用,true、false都能用,没有注释,方法内部参数名为var1。
rabbitTemplate.getConnectionFactory().createConnection().createChannel(true);
基本组件定义(org.springframework.amqp.core)
!!!!!!!!!!!!!!!!!!!!!!!!
@bean配置类方式只有与rabbitmq进行一次连接时才会实际创建组件,在此之只创建bean,如进行一次消息投递或利用其他方式进行组件注册来触发组件创建。
注解方式和jpa方式会立即创建组件。
核心功能在这个包里 org.springframework.amqp.core
队列
定义queue
有两个类可以定义queue
1.Queue类
方法完整参数列表
public Queue(String name, boolean durable, boolean exclusive, boolean autoDelete, @Nullable Map<String, Object> arguments)
2.QueueBuilder
使用示例
return QueueBuilder.durable("rabbitmq").autoDelete().build();
方法完整方法列表见源码
队列参数
(44条消息) rabbitmq queue参数_qq_52390606的博客-CSDN博客
交换器
创建交换器
创建交换器分为两种方式
1.ExchangeBuilder类
使用示例
ExchangeBuilder.directExchange("exchangeName").durable(true).withArguments(null).build();
四种交换器类型可选 direct***
2.使用
FanoutExchange DirectExchange TopicExchange 创建
public FanoutExchange(String name, boolean durable, boolean autoDelete, Map<String, Object> arguments)
public DirectExchange(String name, boolean durable, boolean autoDelete, Map<String, Object> arguments)
public TopicExchange(String name, boolean durable, boolean autoDelete, Map<String, Object> arguments)
绑定
两种绑定方式可选
1.Binding类(destination为目标队列或交换器,DesdinationType指出目标是交换器还是对列)
public Binding(String destination, Binding.DestinationType destinationType, String exchange, String routingKey, @Nullable Map<String, Object> arguments)
成员内部类
public static enum DestinationType {
QUEUE,
EXCHANGE;
private DestinationType() {
}
}
2.BindBuilder类
return BindingBuilder.bind(目标队列或交换器).to(交换器).with(路由键).and(参数);
示例(queueBuilder()、qwer()是同一个类中声明queue和exchange的方法)
return BindingBuilder.bind(queueBuilder()).to(qwer()).with("TestDirectRouting");
消息发送(org.springframework.amqp.rabbit.core)
简单消息发送
@Autowired
RabbitTemplate rabbitTemplate; //使用RabbitTemplate,这提供了接收/发送等等方法
1.直接发送
public void send(String exchange, String routingKey, Message message, @Nullable CorrelationData correlationData)
public void convertAndSend(String exchange, String routingKey, Object object, @Nullable CorrelationData correlationData) throws AmqpException {
this.send(exchange, routingKey, this.convertMessageIfNecessary(object), correlationData);
}
public void convertAndSend(String exchange, String routingKey, Object message, MessagePostProcessor messagePostProcessor, @Nullable CorrelationData correlationData)
2.提前设置参数
public void setExchange(@Nullable String exchange)
public void setRoutingKey(String routingKey)
public void send(Message message) throws AmqpException {
this.send(this.exchange, this.routingKey, message);
}
消息持久化(相关参数设置也可以参考这个)
通过message.getMessageProperties().set*** 设置消息参数。
(44条消息) RabbitMQ笔记(三)RabbitMQ持久化的几个姿势(Spring Boot版本)_嘉禾嘉宁papa的博客-CSDN博客
Mandatory参数(看这个博客后半段)
通过spring.rabbitmq.publisher-returns=true
属性以及实现org.springframework.amqp.rabbit.core.RabbitTemplate.RabbitTemplate.ReturnCallback
接口来接收无法路由的消息。
(44条消息) RabbitMQ学习笔记 - mandatory参数_mytt_10566的博客-CSDN博客
确认机制
(44条消息) RabbitMQ SpringBoot+RabbitMQ发送确认和消费手动确认机制_day day day ...的博客-CSDN博客_rabbitmq消费者手动确认机制
(44条消息) rabbitmq学习7-springboot和rabbitmq发送方确认及手动确认_苏葛的博客-CSDN博客
rabbitMQ 有以下两个接口供实现:
ConfirmCallback:通过实现 ConfirmCallback 接口,消息发送到 Broker 后触发回调,确认消息是否到达 Broker 服务器,也就是只确认是否正确到达 Exchange 中
ReturnsCallback:通过实现 ReturnsCallback 接口,启动消息失败返回,如果正确到达队列不执行。比如路由不到队列时触发回调
PS: RabbitTemplate.ReturnCallback 已经过时了,改用上面那个,加个 s;
# 发送确认
spring.rabbitmq.publisher-confirms=true
# 发送失败返回
spring.rabbitmq.publisher-returns=true
@Component
public class RabbitConfirmCallback implements RabbitTemplate.ConfirmCallback,RabbitTemplate.ReturnCallback {
\\这个无所谓 private Logger logger
private Logger logger= LoggerFactory.getLogger(RabbitConfirmCallback.class);
@Autowired
private RabbitTemplate rabbitTemplate;
@PostConstruct
public void init() {
/**
* Mandatory为true时,消息通过交换器无法匹配到队列会返回给生产者 并触发MessageReturn
* 为false时,匹配不到会直接被丢弃,默认为false。
*/
rabbitTemplate.setMandatory(true);
rabbitTemplate.setConfirmCallback(this); //指定 ConfirmCallback(本文中为下面的confirm方法)
rabbitTemplate.setReturnCallback(this); //指定 ReturnCallback(本文中为下面的 MessageReturn方法)
}
@Override
public void confirm(CorrelationData correlationData, boolean ack, String cause) {
if (ack) {
logger.info("消息已到达broker);
} else {
logger.info("消息未到达broker);
}
}
@Override
public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
logger.info("消息被退回 {}" , message.toString());
}
}
消息接收
rabbitmq自带客户端
rabbitmq自带客户端接收消息(复杂的消费者重写用这个,spring封装的太厉害,rabbitmqtemplate方法中只找到一个能传递有限几个参数来创建消费者的类,没找到传入消费者类的方法)
@Configuration
public class Consumer {
@Autowired
RabbitTemplate rabbitTemplate;
@Bean
public Channel channel() throws IOException, TimeoutException {
Channel channel=rabbitTemplate.getConnectionFactory().createConnection().createChannel(false);
channel.basicConsume("c1-queue",new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println("delivertag="+envelope.getDeliveryTag()+"\n"
+"consumertag="+consumerTag+"\n"
+"message="+new String(body));
channel.basicAck(envelope.getDeliveryTag(),false);
}
});
return channel;
}
}
springboot接收消息
主要注解
(44条消息) RabbitMQ:@RabbitListener 与 @RabbitHandler 及 消息序列化_砂锅大的拳头的博客-CSDN博客_rabbitlistener注解
@Component
public class ConsumerService {
@RabbitListener(queues = QUEUE NAME)
@RabbitHandler
public void consumeMessage(Message message){
log.info("收到的消息:{}",message);
}
}
手动确认
(44条消息) RabbitMQ SpringBoot+RabbitMQ发送确认和消费手动确认机制_day day day ...的博客-CSDN博客_rabbitmq消费者手动确认机制
# 消费手动确认
spring.rabbitmq.listener.simple.acknowledge-mode=manual
/**
* 手动签收接受者
*
* @param msg 消息
* @param deliveryTag 消息唯一标识
* @param channel 通道
* @throws IOException
*/
@RabbitListener(queuesToDeclare =@Queue("boot_queue_ManuallySigned")//使用默认的交换机 @Queue:队列消息配置)
public voidreceiveMsgToManuallySigned(String msg, @Header(AmqpHeaders.DELIVERY_TAG) longdeliveryTag, Channel channel) throws IOException {
try {
//模拟出现异常
//int a = 1 / 0;
log.info("收到的消息-> msg:{}", msg);
log.info("收到的消息标识-> deliveryTag:{}", deliveryTag);
log.info("收到的消息-> channel:{}", channel.toString());
//手动签收 channel.basicAck(消息唯一标识,是否批量签收);
channel.basicAck(deliveryTag,false);
} catch (Exception e) {
e.printStackTrace();
//channel.basicNack(deliveryTag:消息的唯一标识,multiple:是否批量处理,requeue:是否重新放入队列);
//消息出现异常时,若requeue=false,则该消息会被放入死信队列,若没有配置死信队列则该消息会丢失。
channel.basicNack(deliveryTag,false, false);
}
}