直接模式(Direct)
我们需要将消息发给唯一一个节点时使用这种模式,这是最简单的一种形式;
任何发送到Direct Exchange的消息都会被转发到RouteKey中指定的Queue。
- 一般情况可以使用rabbitMQ自带的Exchange:”"(该Exchange的名字为空字符串,下文称其为default Exchange)。
- 这种模式下不需要将Exchange进行任何绑定(binding)操作
- 消息传递时需要一个“RouteKey”,可以简单的理解为要发送到的队列名字。
- 如果vhost中不存在RouteKey中指定的队列名,则该消息会被抛弃。
代码测试:
-
创建一个叫test的队列;
Durability参数表示:是否做持久化 Durable(持久) transient(临时)
Auto delete表示 : 是否自动删除 -
创建工程rabbitmq_demo,引入amqp依赖 ,pom.xml如下
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
- 编写配置文件application.yml:
server:
port: 8090
spring:
rabbitmq:
host: 192.168.0.102 #rabbitmq服务器地址
- 启动类
@SpringBootApplication
public class RabbitApplication {
public static void main(String[] args) {
SpringApplication.run(RabbitApplication.class);
}
}
- 生产者测试类
@RunWith(SpringRunner.class)
@SpringBootTest(classes = RabbitApplication.class)
public class ProductTest {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 直接模式
*/
//@Test
public void sendMsg01(){
rabbitTemplate.convertAndSend("test","直接模式测试");
}
}
运行可以看到RabbitMQ管理界面test的消息变成 1:
- 消费者类
@Component
@RabbitListener(queues = "test") #消费的队列名称
public class Custimer1 {
@RabbitHandler
public void showMessage(String msg){
System.out.println("test接受到的消息:"+ msg);
}
}
- 运行启动类,可以在控制台看到刚才发送的消息
分列模式(Fanout)
当我们需要将消息一次发给多个队列时,需要使用这种模式。如下图:
任何发送到Fanout Exchange的消息都会被转发到与该Exchange绑定(Binding)的所有Queue上。
- 可以理解为路由表的模式;
- 这种模式不需要RouteKey;
- 这种模式需要提前将Exchange与Queue进行绑定,一个Exchange可以绑定多个Queue,一个Queue可以同多个Exchange进行绑定;
- 如果接受到消息的Exchange没有与任何Queue绑定,则消息会被抛弃;
交换器绑定队列
- 在queue中添加队列test02,test03
- 新建交换器cz (名字任意)
- 将test02 和test03 两个队列绑定到交换器cz
点击 cz 进入交换器管理界面
代码测试
- 测试类新增分裂模式方法
/**
* 分裂模式
*/
@Test
public void sendMsg02(){
rabbitTemplate.convertAndSend("cz", "","分裂模式测试");
}
- 创建消息监听类,用于监听test02的消息
@Component
@RabbitListener(queues = "test02")
public class Custimer2 {
@RabbitHandler
public void showMessage(String msg){
System.out.println("test02接受到的消息:"+ msg);
}
}
- 创建消息监听类,用于监听test03的消息
@Component
@RabbitListener(queues = "test03")
public class Custimer3 {
@RabbitHandler
public void showMessage(String msg){
System.out.println("test03接受到的消息:"+ msg);
}
}
- 启动消费者工程,发送消息测试
主题模式(Topic)
任何发送到Topic Exchange的消息都会被转发到所有关心RouteKey中指定话题的Queue上;
如上图所示:
此类交换器使得来自不同的源头的消息可以到达一个对列,其实说的更明白一点就是模糊匹配的意思,例如:上图中红色对列的routekey为usa.#, 图中usa.newsusa.weather,都能找到红色队列,符号 # 匹配一个或多个词,符号 * 只能匹配一个词。因此 usa.# 能够匹配到 usa.news.XXX ,但是 usa.* 只会匹配到 usa.XXX 。
交换器说到底是一个名称与队列绑定的列表。当消息发布到交换器时,实际上是由你所连接的信道,将消息路由键同交换器上绑定的列表进行比较,最后路由消息。
任何发送到Topic Exchange的消息都会被转发到所有关心RouteKey中指定话题的Queue上;
- 这种模式较为复杂,简单来说,就是每个队列都有其关心的主题,所有的消息都带有一个“标题”(RouteKey),Exchange会将消息转发到所有关注主题能与RouteKey模糊匹配的队列;
- 这种模式需要RouteKey,也许要提前绑定Exchange与Queue;
- 在进行绑定时,要提供一个该队列关心的主题,如“#.log.#”表示该队列关心所有涉及log的消息(一个RouteKey为”MQ.log.error”的消息会被转发到该队列);
- #”表示0个或若干个关键字,“”表示一个关键字。如“log.”能与“log.warn”匹配,无法与“log.warn.timeout”匹配;但是“log.#”能与上述两者匹配;
- 同样,如果Exchange没有发现能够与RouteKey匹配的Queue,则会抛弃此消息;
创建队列与绑定
(1)新建一个交换器 ,类型选择topic
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HmmIBdWA-1582169098986)(en-resource://database/2400:1)]
(2)点击topic进入,添加匹配规则,添加后列表如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-s9FBSo77-1582169098988)(en-resource://database/2402:1)]
代码实现
- 在测试类添加主题模式测试方法,分别测试good.abc,abc.log,good.log
@Test
public void sendMsg03(){
rabbitTemplate.convertAndSend("topic", "good.abc","主题模式测试");
//rabbitTemplate.convertAndSend("topic", "abc.log","主题模式测试");
//rabbitTemplate.convertAndSend("topic", "good.log","主题模式测试");
}
第一次:
第二次:
第三次: