DirectExchange模式
只有当 Routing Key 等于 Binding Key 时,消息才会被路由到队列中。
搭建RabbitMq生产者
1、创建maven项目
2、引入相关依赖
<dependencies>
<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>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.amqp</groupId>
<artifactId>spring-rabbit-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<!--使用阿里云仓库加快依赖包的下载速度-->
<pluginRepositories>
<pluginRepository>
<id>public</id>
<name>aliyun nexus</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
3、配置文件
server:
port: 8001
spring:
rabbitmq:
addresses: 47.94.217.248
port: 5672
username: guest
password: guest
4、创建RabbitMq配置
RabbitMq 的相关配置主要包括以下:
- 定义Exchange类型、名称
- 定义Queue 队列
- 定义Binding 使exchange和queue通过routing-key绑定起来
@Configuration
public class RabbitMQConfig {
// 定义短信队列
public final static String SHORT_MESSAGE_QUEUE="SHORT_MESSAGE_QUEUE";
@Bean
public Queue shortMessageQueue(){
return new Queue(RabbitMQConfig.SHORT_MESSAGE_QUEUE);
}
// 定义fanout短信交换机
public final static String FANOUT_SHORT_MESSAGE_EXCHANGE="FANOUT_SHORT_MESSAGE_EXCHANGE";
@Bean
public FanoutExchange fanoutShortMessageExchange() {
return new FanoutExchange(RabbitMQConfig.FANOUT_SHORT_MESSAGE_EXCHANGE);
}
// 定义direct交换机
public final static String DIRECT_SHORT_MESSAGE_EXCHANGE="DIRECT_SHORT_MESSAGE_EXCHANGE";
@Bean
public DirectExchange directShortMessageExchange(){
return new DirectExchange(RabbitMQConfig.DIRECT_SHORT_MESSAGE_EXCHANGE);
}
// 定义topic交换机
public final static String TOPIC_SHORT_MESSAGE_EXCHANGE="TOPIC_SHORT_MESSAGE_EXCHANGE";
@Bean
public TopicExchange topicShortMessageExchange(){
return new TopicExchange(RabbitMQConfig.TOPIC_SHORT_MESSAGE_EXCHANGE);
}
// 定义routing key
public final static String SHORT_MESSAGE_ROUTING_KEY="SHORT_MESSAGE_ROUTING_KEY";
/* 定义Binding,将DIRECT_SHORT_MESSAGE_EXCHANGE 交换机和 SHORT_MESSAGE_QUEUE 队列通过 SHORT_MESSAGE_ROUTING_KEY绑定到一起
* 可以理解成,发送消息到'将DIRECT_SHORT_MESSAGE_EXCHANGE' 交换机时,'DIRECT_SHORT_MESSAGE_EXCHANGE' 这个交换机查找维护的路由表
* (routing-key)找到相应的队列,然后再将消息推送到此队列
*/
@Bean
public Binding shortMessageBindingKey(){
return BindingBuilder.bind(shortMessageQueue()).to(directShortMessageExchange()).with(RabbitMQConfig.SHORT_MESSAGE_ROUTING_KEY);
}
}
5、发送消息
@RestController
@RequestMapping("/short-message")
@RequiredArgsConstructor
@Slf4j
public class ShortMessageController {
private final RabbitTemplate rabbitTemplate;
@GetMapping
public void directExchangeProducer(){
// 指定将消息发送给 ‘DIRECT_SHORT_MESSAGE_EXCHANGE’ 交换机,通过‘SHORT_MESSAGE_ROUTING_KEY’ 这个routing-key找到相应的队列
rabbitTemplate.convertAndSend(RabbitMQConfig.DIRECT_SHORT_MESSAGE_EXCHANGE,RabbitMQConfig.SHORT_MESSAGE_ROUTING_KEY,"directExchangeProducer:hello");
log.info("directExchangeProducer send Message to "+RabbitMQConfig.SHORT_MESSAGE_ROUTING_KEY);
}
}
搭建RabbitMq消费者
1、搭建maven项目
2、引入相关依赖(同producer)
3、配置文件 同producer ,需要更改下端口号
4、定义消费者
@Component
public class ShortMessageConsumer {
private final static String SHORT_MESSAGE_QUEUE="SHORT_MESSAGE_QUEUE";
private final static String DIRECT_SHORT_MESSAGE_EXCHANGE="DIRECT_SHORT_MESSAGE_EXCHANGE";
public final static String SHORT_MESSAGE_ROUTING_KEY="SHORT_MESSAGE_ROUTING_KEY";
// 消费者监听指定队列'SHORT_MESSAGE_QUEUE'
@RabbitListener(queues = {SHORT_MESSAGE_QUEUE})
public void listenShortMessage(String message){
System.out.println("收到消息:"+message);
}
}
测试结果
FanoutExchange模式
实现了一种广播机制,将消息发送到所有与这个 Exchange 绑定的队列中。
fanoutExchange 不需要设置routing-key。
1、 新建两个队列
在RabbitMqConfig文件中
// 定义邮件队列
public final static String EMAIL_MESSAGE_QUEUE="EMAIL_MESSAGE_QUEUE";
@Bean
public Queue emailMessageQueue(){
return new Queue(RabbitMQConfig.EMAIL_MESSAGE_QUEUE);
}
// 定义邮件队列1
public final static String EMAIL_MESSAGE_QUEUE_1="EMAIL_MESSAGE_QUEUE_1";
@Bean
public Queue emailMessageQueue1(){
return new Queue(RabbitMQConfig.EMAIL_MESSAGE_QUEUE_1);
}
2、 新建一个FanoutExchange
// 定义fanout短信交换机
public final static String FANOUT_SHORT_MESSAGE_EXCHANGE="FANOUT_SHORT_MESSAGE_EXCHANGE";
@Bean
public FanoutExchange fanoutShortMessageExchange() {
return new FanoutExchange(RabbitMQConfig.FANOUT_SHORT_MESSAGE_EXCHANGE);
}
3、新建两个binding
将fanoutExchange交换机和两个队列分别绑定
@Bean
public Binding fanoutBindingKey(){
return BindingBuilder.bind(emailMessageQueue()).to(fanoutShortMessageExchange());
}
@Bean
public Binding fanoutBindingKey1(){
return BindingBuilder.bind(emailMessageQueue1()).to(fanoutShortMessageExchange());
}
4、新建两个消费者
新建两个消费者,用来验证fanout交换机是否将消息广播给与他绑定的两个队列
@RabbitListener(queues = {EMAIL_MESSAGE_QUEUE})
public void fanoutShortMessage(String message){
System.out.println("fanoutShortMessage收到消息:"+message);
}
@RabbitListener(queues = {EMAIL_MESSAGE_QUEUE_1})
public void fanoutShortMessage1(String message){
System.out.println("fanoutShortMessage1收到消息:"+message);
}
5、发送消息与消费
// 注意,fanout交换机不需要指定rouing-key,所以routing-key 这个参数可以设置为null或者为空字符串(当我们将routing-key设置为null时,会使用的默认的routing-key 是个空字符串)
@GetMapping("fanout")
public void fanoutExchangeProducer(){
rabbitTemplate.convertAndSend(RabbitMQConfig.FANOUT_SHORT_MESSAGE_EXCHANGE,null,"fanoutExchangeProducer:hello");
log.info("fanoutExchangeProducer send Message");
}
6、两个消费者都接收到消息
TopicExchange
定义了一种匹配规则,同样根据 Routing Key 和 Binding Key 进行模糊匹配,更加灵活
1、配置文件修改
// 定义队列
public final static String TOPIC_QUEUE_1="TOPIC_QUEUE_1";
public final static String TOPIC_QUEUE_2="TOPIC_QUEUE_2";
public final static String TOPIC_QUEUE_3="TOPIC_QUEUE_3";
@Bean
public Queue topicQueue1(){
return new Queue(TOPIC_QUEUE_1);
}
@Bean
public Queue topicQueue2(){
return new Queue(TOPIC_QUEUE_2);
}
@Bean
public Queue topicQueue3(){
return new Queue(TOPIC_QUEUE_3);
}
// 定义topic交换机
public final static String TOPIC_SHORT_MESSAGE_EXCHANGE="TOPIC_SHORT_MESSAGE_EXCHANGE";
@Bean
public TopicExchange topicShortMessageExchange(){
return new TopicExchange(RabbitMQConfig.TOPIC_SHORT_MESSAGE_EXCHANGE);
}
// 定义routing-key
public final static String topic_routing_key_one="com.cxm.*";// 匹配com.cxm下所有(不包括com.cxm)
public final static String topic_routing_key_two="com.ww.*";// 匹配com.ww下所有(不包括com.ww)
public final static String topic_routing_key_three="com.cxm.#";// 匹配com.cxm下0个或多个(包括com.cxm)
@Bean
public Binding topicBindingOne(){
return BindingBuilder.bind(topicQueue1()).to(topicShortMessageExchange()).with(topic_routing_key_one);
}
@Bean
public Binding topicBindingTwo(){
return BindingBuilder.bind(topicQueue2()).to(topicShortMessageExchange()).with(topic_routing_key_two);
}
@Bean
public Binding topicBindingThree(){
return BindingBuilder.bind(topicQueue3()).to(topicShortMessageExchange()).with(topic_routing_key_three);
}
2、创建消费者
public final static String TOPIC_QUEUE_1="TOPIC_QUEUE_1";
public final static String TOPIC_QUEUE_2="TOPIC_QUEUE_2";
public final static String TOPIC_QUEUE_3="TOPIC_QUEUE_3";
@RabbitListener(queues = {TOPIC_QUEUE_1})
public void topicShortMessage1(String message){
System.out.println("TOPIC_QUEUE_1 收到消息:"+message);
}
@RabbitListener(queues = {TOPIC_QUEUE_2})
public void topicShortMessage2(String message){
System.out.println("TOPIC_QUEUE_2 收到消息:"+message);
}
@RabbitListener(queues = {TOPIC_QUEUE_3})
public void topicShortMessage3(String message){
System.out.println("TOPIC_QUEUE_3 收到消息:"+message);
}
3、发送消息
@GetMapping("topic")
public void topicExchangeProducer(){
rabbitTemplate.convertAndSend(RabbitMQConfig.TOPIC_SHORT_MESSAGE_EXCHANGE,"com.cxm.abc","topicExchangeProducer:hello ,routing-key: com.cxm.abc");
rabbitTemplate.convertAndSend(RabbitMQConfig.TOPIC_SHORT_MESSAGE_EXCHANGE,"com.ww.5257","topicExchangeProducer:hello ,routing-key: com.ww.5257");
rabbitTemplate.convertAndSend(RabbitMQConfig.TOPIC_SHORT_MESSAGE_EXCHANGE,"com.cxm","topicExchangeProducer:hello ,routing-key: com.cxm");
}
4、消费者接受到消息
通过结果可以看出,只有com.cxm.#匹配到了com.cxm,因为#代表匹配0个或者多个!