文章目录
1. 整合Springboot使用RabbitMQ
1.导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
2.配置Yml
server:
port: 9992
spring:
application:
name: rabbitmq-boot
rabbitmq:
host: 127.0.0.1
port: 5672
username: wang
password: wang
virtual-host: /wang1
1.1 Hello模型
1.1.1 生产者
@SpringBootTest(classes = RabbitMqApplication.class)
@RunWith(SpringRunner.class)
public class provider {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 简单hello模型
*/
@Test
public void prodMessages(){
rabbitTemplate.convertAndSend("hello","hello,我是简单hello模型");
}
}
1.1.2 消费者
@Component //不设置默认为 持久化,非独占,非自动删除队列
@RabbitListener(queuesToDeclare = @Queue(value = "hello", durable = "true", autoDelete = "false"))
public class consumer {
@RabbitHandler
public void consumerMessage(String message) {
System.out.println("我是简单模型消费者消费消息为:" + message);
}
}
注意: 当只有生产者没消费者时,队列是不会创建的,只有当消费者存在时才会自动创建
1.2 Work模型
1.2.1 生产者
@SpringBootTest(classes = RabbitMqApplication.class)
@RunWith(SpringRunner.class)
public class provider {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 工作模型 work 和交换机没关系
*/
@Test
public void testWork() {
for (int i = 0; i < 100; i++) {
rabbitTemplate.convertAndSend("work", i + "hello,我是工作模型");
}
}
}
1.2.2 消费者
默认情况下是公平消费,下面配的是能者多劳,目的为避免消息丢失
注意修改yml的配置
spring:
application:
name: rabbitmq-boot
rabbitmq:
host: 127.0.0.1
port: 5672
username: wang
password: wang
virtual-host: /wang1
#配置这个解决work模式中能者多劳的问题
listener:
simple:
prefetch: 1 #每个消费者每次可以消费一个
/**
* @version V1.0.0
* @author: WangQingLong
* @date: 2020/9/29 0:04
* @description: 当@RabbitListener加在方法上,表面这个方法就是执行方法回调,就不需要加@RabbitHandler注解了,在springboot里面默认是循环公平消费,如果要配置能者多劳需要额外配置
*/
@Component
public class ConsumerWork {
//ackMode:MANUAL 手动确认
@RabbitListener(queuesToDeclare = @Queue(value = "work"), ackMode = "MANUAL")
public void consumerMessage1(String msg, Message message, Channel channel) throws IOException {
// 该条消息的消息编号,Long类型,递增的
long deliveryTag = message.getMessageProperties().getDeliveryTag();
try {
//模拟网络延迟
TimeUnit.SECONDS.sleep(1);
// 模拟处理消息
System.out.println("我是消费者1号:"+msg);
// 处理成功 手动ACK回执
// arg0:消息编号 递增的 该消息的index
// arg1: 是否批量.true:将一次性ack所小于deliveryTag的消息。
// true: 将一次性ACK回执成功所小于消息编号(deliveryTag的消息
// false:仅ACK回执成功传入的消息编号(deliveryTag
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 当消息处理异常时,将消息重新放回队列,重新排队
// arg0:消息编号 递增的 该消息的index
// arg1: 是否批量.true:将一次性拒绝所有小于deliveryTag的消息。
// true: 将一次性拒绝所有小于消息编号(deliveryTag的消息
// false:仅拒绝传入的消息编号(deliveryTag
// arg2:true: 让消息重新回到队列
// false:直接丢弃消息
//注意 对比
// channel.basicReject(delivery.getEnvelope().getDeliveryTag(), false);
//deliveryTag:该消息的index
//requeue:被拒绝的是否重新入队列
//
//channel.basicNack 与 channel.basicReject 的区别在于basicNack可以拒绝多条消息,而basicReject一次只能拒绝一条消息
channel.basicNack(deliveryTag, false, true);
}
}
//ackMode:MANUAL 手动确认
@RabbitListener(queuesToDeclare = @Queue(value = "work"), ackMode = "MANUAL")
public void consumerMessage2(String msg, Message message, Channel channel) throws IOException {
// 该条消息的消息编号,Long类型,递增的
long deliveryTag = message.getMessageProperties().getDeliveryTag();
try {
// 模拟处理消息
System.out.println("我是消费者2号:"+msg);
// 处理成功 手动ACK回执
// arg0:消息编号 递增的 该消息的index
// arg1: 是否批量.true:将一次性ack所小于deliveryTag的消息。
// true: 将一次性ACK回执成功所小于消息编号(deliveryTag的消息
// false:仅ACK回执成功传入的消息编号(deliveryTag
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
// 当消息处理异常时,将消息重新放回队列,重新排队
// arg0:消息编号 递增的 该消息的index
// arg1: 是否批量.true:将一次性拒绝所有小于deliveryTag的消息。
// true: 将一次性拒绝所有小于消息编号(deliveryTag的消息
// false:仅拒绝传入的消息编号(deliveryTag
// arg2:true: 让消息重新回到队列
// false:直接丢弃消息
//注意 对比
// channel.basicReject(delivery.getEnvelope().getDeliveryTag(), false);
//deliveryTag:该消息的index
//requeue:被拒绝的是否重新入队列
//
//channel.basicNack 与 channel.basicReject 的区别在于basicNack可以拒绝多条消息,而basicReject一次只能拒绝一条消息
channel.basicNack(deliveryTag, false, true);
}
}
}
1.3 Fanout广播模型
1.3.1 生产者
@SpringBootTest(classes = RabbitMqApplication.class)
@RunWith(SpringRunner.class)
public class provider {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 广播模型 fanout 交换机但是和路由没关系
*/
@Test
public void testFanout() {
rabbitTemplate.convertAndSend("FanoutExchange", "", "我是广播模型生产者");
}
}
1.3.2 消费者
@Component
public class ConsumerFanout {
@RabbitListener(bindings = {
@QueueBinding(
value = @Queue,//如果不指定名字就是临时队列
exchange = @Exchange(value = "FanoutExchange", type = "fanout")
)
})
public void consumerMessage1(String message) {
System.out.println("我是广播模型消费者1号:" + message);
}
@RabbitListener(bindings = {
@QueueBinding(
value = @Queue,//如果不指定名字就是临时队列
exchange = @Exchange(value = "FanoutExchange", type = "fanout")
)
})
public void consumerMessage2(String message) {
System.out.println("我是广播模型消费者2号:" + message);
}
@RabbitListener(bindings = {
@QueueBinding(
value = @Queue,//如果不指定名字就是临时队列
exchange = @Exchange(value = "FanoutExchange", type = "fanout")
)
})
public void consumerMessage3(String message) {
System.out.println("我是广播模型消费者3号:" + message);
}
}
1.4 Route路由模型
1.4.1 生产者
@SpringBootTest(classes = RabbitMqApplication.class)
@RunWith(SpringRunner.class)
public class provider {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 路由模型 Route 交换机固定路由
*/
@Test
public void testRoute() {
rabbitTemplate.convertAndSend("RouteExchange", "info", "我是广播模型生产者");
}
}
1.4.2 消费者
@Component
public class ConsumerRoute {
@RabbitListener(bindings = {
@QueueBinding(
value = @Queue,//创建临时队列
exchange = @Exchange(value = "RouteExchange",type = "direct"),
key = {"info","error"}
)
})
public void consumerMessage1(String message){
System.out.println("我是路由模型消费者1号,指向路由info和error = " + message);
}
@RabbitListener(bindings = {
@QueueBinding(
value = @Queue,//创建临时队列
exchange = @Exchange(value = "RouteExchange",type = "direct"),
key = {"error"}
)
})
public void consumerMessage2(String message){
System.out.println("我是路由模型消费者1号,指向路由error = " + message);
}
}
1.5 Topic订阅模型/动态路由模型
1.5.1 生产者
@SpringBootTest(classes = RabbitMqApplication.class)
@RunWith(SpringRunner.class)
public class provider {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 订阅模型 Topics 也叫动态路由 交换机动态路由
*/
@Test
public void testTopics() {
rabbitTemplate.convertAndSend("TopicsExchange", "user.save", "我是订阅模型生产者");
}
}
1.5.2 消费者
@Component
public class ConsumerTopics {
@RabbitListener(bindings = {
@QueueBinding(
value = @Queue,//创建临时队列
exchange = @Exchange(value = "TopicsExchange",type = "topic"),
key = {"user.*"}
)
})
public void consumerMessage1(String message){
System.out.println("我是路由模型消费者1号,指向路由user.* = " + message);
}
@RabbitListener(bindings = {
@QueueBinding(
value = @Queue,//创建临时队列
exchange = @Exchange(value = "TopicsExchange",type = "topic"),
key = {"user.*","order.#"}
)
})
public void consumerMessage2(String message){
System.out.println("我是路由模型消费者2号,指向路由user.*\",\"order.# = " + message);
}
}