server:
port: 8021
spring:
#给项目来个名字
application:
name: rabbitmq-test
#配置rabbitMq 服务器
rabbitmq:
host: 127.0.0.1
port: 5672
username: need
password: 123456
#虚拟host 可以不设置,使用server默认host
virtual-host: /testhost
listener:
simple:
acknowledge-mode: manual #手动ACK
direct:
acknowledge-mode: manual #手动ACK
2 创建交换机,队列,绑定等,注意看createZhengChangQueue() 方法,创建后的效果图,也可以看上面的博文
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import java.util.HashMap;
@Configuration
public class ExchangeQueueBindingConfig {
//自动创建就是靠他
//解决循环依赖
@Lazy
@Autowired
RabbitAdmin rabbitAdmin;
//死信队列
@Bean
public Queue createShiXinQueue() {
return new Queue("shixin_queue", true);
}
//死信交换机
@Bean
public DirectExchange createShiXinExchange() {
return new DirectExchange("shixin_exchange", true, false);
}
//死信交换机 死信队列 绑定
@Bean
public Binding createShiXinBinding() {
return BindingBuilder.bind(createShiXinQueue()).to(createShiXinExchange()).with("shixin");
}
//正常队列,这里要设置死信交换机,关键所在
@Bean
public Queue createZhengChangQueue() {
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("x-dead-letter-exchange", "shixin_exchange");
map.put("x-dead-letter-routing-key", "shixin");
//故意设置成500,演示 消息满以后,会到死信队列中
map.put("x-max-length",500);
return new Queue("zhengchang_queue", true, false, false, map);
}
//正常交换机
@Bean
public TopicExchange createZhengChangExchange() {
return new TopicExchange("zhengchang_exchange", true, false);
}
//正常交换机 正常队列 绑定
@Bean
public Binding createZhengChangBinding() {
return BindingBuilder.bind(createZhengChangQueue()).to(createZhengChangExchange()).with("chongqing.#");
}
//创建初始化RabbitAdmin对象
@Bean
public RabbitAdmin rabbitAdmin(ConnectionFactory connectionFactory) {
RabbitAdmin rabbitAdmin = new RabbitAdmin(connectionFactory);
// 只有设置为 true,spring 才会加载 RabbitAdmin 这个类
rabbitAdmin.setAutoStartup(true);
return rabbitAdmin;
}
//创建交换机和对列
@Bean
public void createExchangeQueue() {
//死信
rabbitAdmin.declareExchange(createShiXinExchange());
rabbitAdmin.declareQueue(createShiXinQueue());
//正常
rabbitAdmin.declareExchange(createZhengChangExchange());
rabbitAdmin.declareQueue(createZhengChangQueue());
}
}
3 演示发送TTL超时消息,并不要有消费者去消费,过期后就会到死信队列
import cn.huawei.rabbitmqtest1.pojo.User;
import com.alibaba.fastjson.JSON;
import org.junit.jupiter.api.Test;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.nio.charset.StandardCharsets;
import java.util.UUID;
@SpringBootTest
public class Test_1 {
@Autowired
RabbitTemplate rabbitTemplate; //使用RabbitTemplate,这提供了接收/发送等等方法
@Test
void fangfa1() {
MessageProperties messageProperties = new MessageProperties();
messageProperties.setExpiration("9000"); // 设置过期时间,单位:毫秒
for (int i = 1; i < 10; i++) {
messageProperties.setMessageId(i+"");
User user = new User(i + "", "小明 " + i);
// 这个参数是用来做消息的唯一标识
//发布消息时使用,存储在消息的headers中
CorrelationData correlationData = new CorrelationData(i+"");
Message message = new Message(JSON.toJSONString(user).getBytes(StandardCharsets.UTF_8), messageProperties);
rabbitTemplate.convertAndSend("zhengchang_exchange", "chongqing.news", message, correlationData);
}
}
}
4 一定要手动ack,演示 故意乱输信息(文字等),会出错,进而走到 basic.nack 并且不再重新投递 requeue=false,就会到死信队列
import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
import java.io.IOException;
@Component
public class Test_2 {
//监听的队列名称
@RabbitListener(queues = "zhengchang_queue")
/**
* 注意:后4个参数,需要生产者发送消息时加上,否则为报错,注解里添加 required=false 或 删除参数
*/
public void process(Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
@Header(AmqpHeaders.MESSAGE_ID) String messageId,
@Header(AmqpHeaders.CONSUMER_TAG) String consumerTag,
CorrelationData correlationData) throws IOException {
//long deliveryTag = message.getMessageProperties().getDeliveryTag();
//或
//@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag
try {
String msgbody = new String(message.getBody());
//1.接收转换消息
System.out.println("消费者 1 收到消息 : " + msgbody + " 编号: " + deliveryTag);
//2. 处理业务逻辑
System.out.println("处理业务逻辑...");
//模拟出现错误
System.out.println(500 / Double.valueOf(msgbody));
//3. 手动签收
channel.basicAck(deliveryTag, true);
} catch (Exception e) {
//4.拒绝签收
/*
第三个参数:requeue:重回队列。如果设置为true,则消息重新回到queue,broker会重新发送该消息给消费端
这里要演示发到死信队列,就设置为false
*/
channel.basicNack(deliveryTag, true, false);
//channel.basicReject(deliveryTag,false);
}
}
}
5 演示 达到最大队列长度,并不要有消费者去消费,多的消息也会到列信队列
注意看第二步故意设成500,而这里故意调成505,多的几条就会到死信队列中
另外如果发送a,b,c,d,e,f ,而到死信中的是 a,b,c,也就是先发送的消息会弄到死信中
import cn.huawei.rabbitmqtest1.pojo.User;
import com.alibaba.fastjson.JSON;
import org.junit.jupiter.api.Test;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.nio.charset.StandardCharsets;
import java.util.UUID;
@SpringBootTest
public class Test_3 {
@Autowired
RabbitTemplate rabbitTemplate; //使用RabbitTemplate,这提供了接收/发送等等方法
@Test
void fangfa3() {
MessageProperties messageProperties = new MessageProperties();
for (int i = 1; i < 505; i++) {
messageProperties.setMessageId(i+"");
User user = new User(i + "", "小明 " + i);
// 这个参数是用来做消息的唯一标识
//发布消息时使用,存储在消息的headers中
CorrelationData correlationData = new CorrelationData(i+"");
Message message = new Message(JSON.toJSONString(user).getBytes(StandardCharsets.UTF_8),messageProperties);
rabbitTemplate.convertAndSend("zhengchang_exchange", "chongqing.news", message, correlationData);
}
}
}