TopicExchange
和 DirectExchange
这两种交换机非常相似,Topic
类型的Exchange
与Direct
相比,都是可以根据RoutingKey
把消息路由到不同的队列。只不过Topic
类型的RoutingKey必须是多个单词的列表,并用.
隔开。
例如:
china.news:中国新闻的异步通讯
china.weather:中国天气的异步通信
japan.news:小日子新闻的异步通讯
japan.weather:小日子天气的异步通讯
这个东西很有意思,他是可以使用通配符的,其中
#:代表0个或多个单词
*:代表1个单词
如此,如果我们现在要监听的是中国的所有消息,那么我们的routingKey就是china.#
,如果我们想监听的是所有国家的新闻,那么我们的routingKey就是*.news
。
废话少说,代码来一波:
配置pom导入依赖跟配置yaml文件环境的代码就不说了。
步骤一、使用@RabbitListener写我们的监听器。
@RabbitListener(bindings = @QueueBinding(
value = @Queue(name = "topic.queue1"),
exchange = @Exchange(name = "exchange.topic", type = ExchangeTypes.TOPIC),
key = {"china.#"}
))
public void listenTopicQueue1(String msg){
System.out.println("监听到的来自中国的消息为【"+msg+"】");
}
@RabbitListener(bindings = @QueueBinding(
value = @Queue(name = "topic.queue2"),
exchange = @Exchange(name = "exchange.topic", type = ExchangeTypes.TOPIC),
key = "#.news"
))
public void listenTopicQueue2(String msg){
System.out.println("监听到的来自全世界的新闻为【"+msg+"】");
}
步骤二、编写发布者,发送消息
@Test
public void testTopicExchange(){
//交换机的名称
String exchangeName = "exchange.topic";
//消息
String chinaNews = "这是一条来自中国的新闻!";
String chinaWeather = "这是一条来自中国的天气预报!";
String japanNews = "这是一条来自小日子的新闻!";
String japanWeather ="这是一条来自小日子的天气预报!";
//发送消息
rabbitTemplate.convertAndSend(exchangeName, "china.news", chinaNews);
rabbitTemplate.convertAndSend(exchangeName, "china.weather", chinaWeather);
rabbitTemplate.convertAndSend(exchangeName, "japan.news", japanNews);
rabbitTemplate.convertAndSend(exchangeName, "japan.weather", japanWeather);
}
发布完成后,我们来看一下效果:
可以看到
1、监听china.#
的监听者成功监听了来自中国的新闻和天气预报。
2、监听#.news
的监听者监听到了来自全世界的新闻。
这种写法的好处就是,以后假如我们多了来自中国的其他东西,比如china.science,以及加拿大的新闻,我们的监听者都不需要修改任何代码。代码走一波,我们修改一下我们的发布者的代码。
@Test
public void testTopicExchange(){
//交换机的名称
String exchangeName = "exchange.topic";
//消息
String chinaNews = "这是一条来自中国的新闻!";
String chinaWeather = "这是一条来自中国的天气预报!";
String japanNews = "这是一条来自小日子的新闻!";
String japanWeather ="这是一条来自小日子的天气预报!";
//新增加的消息
String chinaScience = "这是一条来自中国的科学!";
String canadaNews = "这是一条来自加拿大的新闻!";
//发送消息
rabbitTemplate.convertAndSend(exchangeName, "china.news", chinaNews);
rabbitTemplate.convertAndSend(exchangeName, "china.weather", chinaWeather);
rabbitTemplate.convertAndSend(exchangeName, "japan.news", japanNews);
rabbitTemplate.convertAndSend(exchangeName, "japan.weather", japanWeather);
//额外发送的消息
rabbitTemplate.convertAndSend(exchangeName, "china.science", chinaScience);
rabbitTemplate.convertAndSend(exchangeName, "canada.news", canadaNews);
}
为了方便看,我还把监听实际新闻的sout改成了err(变成红色),我们来看一下最新的效果:
可以看到,这里计算我们新加了其他的消息,我们的china.#
也可以正常接收routingKey是以china开头的所有消息,而我们的#.news
也可以正常接收routingKey是以news结尾的所有消息。