前几篇已经介绍rabbitmq的基础,生产者将消息发送给Exchange,依据是路由关键字 routingkey (如 : topic.message)。
绑定Exchange与Queues队列的依据是bindingKey(如 :topic.#)。
RabbitMq交换机和队列的绑定方式四种:header现在不推荐用,基本上就是剩下的三种
1 Fanout Exchange– 不处理路由键。你只需要简单的将队列绑定到交换机上。一个发送到交换机的消息都会被转发到与该交换机绑定的所有队列上。很像子网广播,每台子网内的主机都获得了一份复制的消息。Fanout交换机转发消息是最快的。
2 Direct Exchange– 处理路由键。需要将一个队列绑定到交换机上,要求该消息与一个特定的路由键完全匹配,一对一的关系。这是一个完整的匹配。如果一个队列绑定到该交换机上要求路由键 “dog”,则只有被标记为“dog”的消息才被转发,不会转发dog.puppy,也不会转发dog.guard,只会转发dog。
3 Topic Exchange– 将路由键和某模式进行匹配。此时队列需要绑定要一个模式上。符号“#”匹配零个或多个词,符号“*”匹配不多不少一个词。因此“audit.#”能够匹配到“audit.irs.corporate”,但是“audit.*” 只会匹配到“audit.irs”
<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.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
一、配置文件:后期配置文件可以将交换机和队列都配置在配置文件中
spring:
rabbitmq:
host: 192.168.163.131
username: datamip
password: datamip
virtual-host: /
port: 5672
publisher-confirms: true
publisher-returns: true
application:
name: rabbitmp
server:
port: 8080
后期修改的配置可以修改为:写一个配文文件配置好queue,exchange,banding
spring:
rabbitmq:
host: 192.168.163.131
virtual-host: /
port: 5672
username: guest
password: guest
connection-timeout: 2000
listener:
acknowledge-mode: auto
concurrency: 200
max-concurrency: 500
retry:
enabled: false
initial-interval: 2000
max-attempts: 2
max-interval: 2000
stateless: false
exchange:
name: topic.exchange
queue:
name: topic.queue
二、配置类
创建对类queue
创建交换机TopicExchange
根据相应的规则将队列绑定到交换机上
package com.atguigu.amqp.config;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Exchange;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConversionException;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Created by admin on 2018/12/3 22:54
*
* @Author: created by admin
* @Date: created in 22:54 2018/12/3
* @param: bindingResult
* @param: result
* @return:
* @throws:
* @Description:
* @version:
*/
@Configuration
public class myConfig {
@Value("${spring.rabbitmq.host}")
private String address;
@Value("${spring.rabbitmq.port}")
private String port;
@Value("${spring.rabbitmq.username}")
private String userName;
@Value("${spring.rabbitmq.password}")
private String password;
@Value("${spring.rabbitmq.virtual-host}")
private String virtualHost;
@Value("${spring.rabbitmq.publisher-confirms}")
private String publisherConfirms;
@Bean
public MessageConverter messageConverter() {
return new Jackson2JsonMessageConverter();
}
/**
* // 指定该参数名是message 见下面Qualifier("message")
* topic.message 是rounting-key,匹配规则
* @return
*/
@Bean(name="message")
public Queue queueMessage() {
return new Queue("topic.message");
}
@Bean(name = "notes")
public Queue queueMessages(){
return new Queue("topic.notes");
}
/**
* 创建交换机topicExchange
* @return
*/
@Bean
public TopicExchange exchange() {
return new TopicExchange("topicExchange");
}
/**
* 根据绑定规则将队列绑定到相应的交换机上(bindingKey)--Exchange Queues
* @param queueMessage
* @param topicExchange
* @return
*
*/
@Bean
public Binding bindingExchangeMessage(@Qualifier("message") Queue queueMessage,TopicExchange topicExchange) {
return BindingBuilder.bind(queueMessage).to(topicExchange).with("topic.message");
}
/**
*
* 将队列"messages" 绑定到交换机上,绑定规则是 topic.messages
* @param queueMessage
* @param topicExchange
* @return
*/
@Bean
public Binding bindingExchangeMessages(@Qualifier("notes") Queue queueMessage,TopicExchange topicExchange){
return BindingBuilder.bind(queueMessage).to(topicExchange).with("topic.#");
}
}
三、消息发送类:TopicSend.java
@Component
public class TopicSend {
@Autowired
AmqpTemplate amqpTemplate;
/**
* 向 名称为 topicExchange 的交换机 发送满足routingkey规则为 "topic.messages " 的内容为 "我是发送消息的内容" 的消息
*/
public void sendMessage() {
amqpTemplate.convertAndSend("topicExchange","topic.message","我是发送消息的内容! ");
}
}
四、创建消息接收类:TopicReceiver.java
@Component
public class TopicReceiver {
@RabbitListener(queues = "topic.message")
public void receiveMessage(String str) {
System.out.println("我是监听topic.message的,仅满足topic.message的过来 , "+str);
}
@RabbitListener(queues ="topic.notes" )
public void receiveMessage2(String str) {
System.out.println("我是监听topic.# 的,满足 topic.# 的都过来 , " + str);
}
}
五、测试
@RunWith(SpringRunner.class)
@SpringBootTest
public class TestAMQP {
@Autowired
private TopicSend topicSender;
@Test
public void contextLoads() {
//routingkey topic.messages
topicSender.sendMessage();
}
@Test
public void test() {
//topic.message
topicSender.sendMessage();
}
}
总结:
routingkey 为 topic.messages,只满足bindingkey为 topic.# 的,所以,只有topic.mnotes监听到消息,但是将routingkey改成topic.message时候两个队列都能够接收。