日积月累,水滴石穿 😄
前言
前面已经用俩篇文章来介绍 RabbitMQ 了。本篇呢,就带大家一起看看在 SpringBoot 中如何去使用RabbitMQ。
环境搭建
导入依赖
pom
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
配置配置文件
在配置文件中配置 RabbitMQ的基本信息,ip、port、username、password、virtual-host。各位如果看过第一篇的,应该对这些会感到很熟悉的。
spring:
application:
name: rabbitmq-boot
rabbitmq:
host: 127.0.0.1
port: 5672
virtual-host: /test-1
username: ***
password: ****
SpringBoot使用RabbitTemplate简化对RabbitMQ操作,使用时候直接在项目中注入即可使用。
使用
接下来呢,就介绍一下在 SpringBoot 如何去使用 RabbitMQ中的消息模型。
hello world 模型
一个生产者对应一个消费者。
1、开发生产者
@Autowired
RabbitTemplate rabbitTemplate;
@Test
void testHello(){
/**
* 参数一:队列名称
* 参数二:消息内容
*/
rabbitTemplate.convertAndSend("hello-boot","hello boot");
}
注:由于我们还没有编写消费者,单独运行上述生产者并不会产生队列,队列是由消费者创建的
2、开发消费者
@Component
public class HelloCustomer {
// 通过注解创建 hello-boot 队列
@RabbitListener(queuesToDeclare = {
@Queue(value = "hello-boot",durable = "false",
autoDelete = "false")
})
public void consumptionStr(String message){
System.out.println("消费消息:" + message);
}
}
被@RabbitListener注解标注的方法,会被作为消费消息的方法,也就是消费者;我们可以通过注解参数指定所监听的队列或者 Binding。
@Queue注解可以设置队列属性,例如:
- value:队列名称
- durable:是否持久化
- autoDelete:是否自动删除 至于其他属性各位可以去看看:RabbitMQ 常用方法介绍(二)
然后运行生产者所在的 testHello方法。
结果:消费消息:hello boot
work模型
一个生产者对应多个消费者。
1、开发生产者
@Test
void testWork(){
/**
* 参数一:队列名称
* 参数二:消息内容
*/
for (int i = 0; i < 10; i++) {
rabbitTemplate.convertAndSend("work-boot","work boot");
}
}
2、开发消费者
@Component
public class WorkCustomer {
// 通过注解创建 work-boot 队列
@RabbitListener(queuesToDeclare = @Queue("work-boot"))
public void work1(String message){
System.out.println("消费消息-1:" + message);
}
@RabbitListener(queuesToDeclare = @Queue("work-boot"))
public void work2(String message){
System.out.println("消费消息-2:" + message);
}
}
结果:
消费消息-1:work boot
消费消息-1:work boot
消费消息-2:work boot
消费消息-2:work boot
消费消息-2:work boot
消费消息-2:work boot
消费消息-2:work boot
消费消息-1:work boot
消费消息-1:work boot
消费消息-1:work boot
我们根据结果可以发现:两个消费者分别消费了 5 条消息。可以说明:默认在Spring AMQP中实现Work这种方式就是公平调度的。如果需要实现能者多劳需要额外配置
fanout模型
这个模型,加入了一个新成员,名为交换机。消息由 mq 分发给交换机,然后由交换机发送给队列。
1、开发生产者
@Test
void testfanout(){
/**
* 参数一:交换机名称
* 参数二:路由名称(在fanout模式下,该参数无作用)
* 参数三:消息内容
*
*/
rabbitTemplate.convertAndSend("fanout-boot-exchange",
"","fanout boot");
}
2、开发消费者
@RabbitListener(bindings = {
@QueueBinding(
value = @Queue, //创建临时队列
exchange = @Exchange(value = "fanout-boot-exchange",
type = "fanout") //绑定交换机
)
})
public void fanoutStr(String message){
System.out.println("消费消息-1:" + message);
}
@RabbitListener(bindings = {
@QueueBinding(
value = @Queue, //创建临时队列
exchange = @Exchange(value = "fanout-boot-exchange",
type = "fanout") //绑定交换机
)
})
public void fanoutStr2(String message){
System.out.println("消费消息-2:" + message);
}
结果:
消费消息-2:fanout boot
消费消息-1:fanout boot
@QueueBinding注解用来绑定队列和交换机。
@Exchange注解用来声明交换机。
根据打印的结果可以发现,队列的消费者都能拿到了消息。实现一条消息被多个消费者消费。
Route 模型
在 Fanout 模式中,一条消息,会被所有订阅的队列都消费。但是,在某些场景下,我们希望不同的消息被不同的队列消费。这时就要用到 Direct 类型的 Exchange。
1、开发生产者
@Test
void testDirect(){
/**
* 参数一:交换机名称
* 参数二:路由名称
* 参数三:消息内容
*
*/
rabbitTemplate.convertAndSend("direct-boot-exchange",
"error","direct boot error");
}
2、开发消费者
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
@Component
public class directCustomer {
@RabbitListener(bindings = {
@QueueBinding(value = @Queue, //创建临时队列
exchange = @Exchange(value = "direct-boot-exchange",
//绑定交换机名称和类型,默认类型就为direct
type = "direct"),
key = {"info"}) //路由key
})
public void directStr(String message){
System.out.println("消费消息-1:" + message);
}
@RabbitListener(bindings = {
@QueueBinding(value = @Queue,
exchange = @Exchange(value = "direct-boot-exchange",
type = "direct"),
key={"info","error"}) //路由key
})
public void directStr2(String message){
System.out.println("消费消息-2:" + message);
}
}
发送路由 key 为 error
消费消息-2:direct boot error
发送路由 key 为 info
消费消息-1:direct boot info
消费消息-2:direct boot info
Topic模型
Topic 类型的 Exchange 与 Direct相比,都是可以根据RoutingKey把消息路由到不同的队列。只不过Topic类型的Exchange可以让队列在绑定Routing key 的时候使用通配符!这种模型Routingkey 一般都是由一个或多个单词组成,多个单词之间以”.”分割,例如: user.insert
统配符有两
* :匹配 1 个词
# : 匹配一个或多个词
如:
- audit.# 匹配 audit.irs.corporate 或者 audit.irs 等
- audit.* 只能匹配 audit.irs
1、开发生产者
@Test
void testTopic(){
/**
* 参数一:交换机名称
* 参数二:路由名称
* 参数三:消息内容
*
*/
rabbitTemplate.convertAndSend("topic-boot-exchange",
"user.role.query","topic boot user.role.query");
}
2、开发消费者
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
@Component
public class TopicCustomer {
@RabbitListener(bindings = {
@QueueBinding(value = @Queue,
exchange = @Exchange(value = "topic-boot-exchange",
type = "topic"),
key ={"user.*"})
})
public void topicStr(String message){
System.out.println("消费消息-1:" + message);
}
@RabbitListener(bindings = {
@QueueBinding(value = @Queue,
exchange = @Exchange(value = "topic-boot-exchange",
type = "topic"),
key ={"user.#"})
})
public void topicStr2(String message){
System.out.println("消费消息-2:" + message);
}
}
发送路由key为user.role.query
消费消息-2:topic boot user.role.query
发送路由key为user.query
消费消息-2:topic boot user.query
消费消息-1:topic boot user.query
- 如你对本文有疑问或本文有错误之处,欢迎评论留言指出。如觉得本文对你有所帮助,欢迎点赞 + 收藏。