RabbitMQ is divided into two parts: one is the switch (dealing with the sender) and the other is the queue (dealing with the listener) No matter which working mode, the sender will only send the data to the switch, and then the switch will send it to the queue, and then the queue will send it to the listener, or the listener detects that there is data in the queue and needs to bind the queue to the switch to complete the operation of sending and receiving messages. If the queue is not bound to the switch, there will be no messages in the queue
The entry mode of RabbitMQ and the default switch used at the bottom of the queue working mode bind queues in the default way, that is, send to all queues. If tens of thousands of requests are sent in the actual project, the default switch will send these data to each queue, which will cause the service corresponding to a queue to receive unnecessary data, so To specify the switch, the designated switch official wrote us three commonly used pub/sub subscription modes, routing routing mode and wildcard mode
Pub/Sub subscription mode
Manually specify the binding relationship between the switch and the queue. For example, station b pays attention to an up master. When the up updates a post, all users who pay attention to it must receive the post. Those who do not pay attention must not be allowed to receive it
routing mode
This working mode should not only specify the relationship between the switch and the queue, but also set the same key for the switch and the queue. Suppose that when the up Master of station b sends the post, it can be set that the large members of station b who only pay attention to it can see it, and the ordinary members who pay attention to it can't see it. Then it is set that only the up master and the large members can see it. This can't be realized according to the setting of subscription mode A routing mode needs to wear a key when binding the switch to the queue, so we can judge whether to send it to the user through this key
Topics wildcard pattern
There is a problem with the routing mode. Assuming that we are large members and pay attention to a lot of UPS, we have to write the key many times. Assuming that the key starts with a and does not take into account other situations, this is an example. Following this idea, it will be troublesome for us to write the key many times every time. In this case, we can use the Topics wildcard working mode. The wildcard indicates that only one hypothetical key can be matched. The key is a.1.2.3 Then use the wildcard A. in this way, it will not match a.1.2.3. It can only match a.1. Such a key wildcard # means that multiple a. # can be matched to a.1.2.3
Integrate spring related dependencies
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.1.7.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.amqp</groupId> <artifactId>spring-rabbit</artifactId> <version>2.1.8.RELEASE</version> </dependency>
Sender related spring
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:rabbit="http://www.springframework.org/schema/rabbit" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/rabbit http://www.springframework.org/schema/rabbit/spring-rabbit.xsd"> <!--Load profile--> <context:property-placeholder location="classpath:rabbitmq.properties"/> <!-- definition rabbitmq connectionFactory --> <rabbit:connection-factory id="connectionFactory" host="${rabbitmq.host}" port="${rabbitmq.port}" username="${rabbitmq.username}" password="${rabbitmq.password}" virtual-host="${rabbitmq.virtual-host}"/> <!--Define management switches, queues--> <rabbit:admin connection-factory="connectionFactory"/> <!--Define a persistent queue. If it does not exist, it will be created automatically; Bind to default switch if not bound to switch The default switch type is direct,The name is:"",The routing key is the name of the queue --> <!-- id: bean Name of name: queue Name of auto-declare:Automatic creation auto-delete:Automatically delete. When the last consumer disconnects from the queue, the queue is automatically deleted durable: Persistent --> <rabbit:queue id="spring_queue" name="spring_queue" auto-declare="true"/> <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~radio broadcast; All queues can receive messages~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --> <!--Define the persistent queue in the broadcast switch. If it does not exist, it will be created automatically--> <rabbit:queue id="spring_fanout_queue_1" name="spring_fanout_queue_1" auto-declare="true"/> <!--Define the persistent queue in the broadcast switch. If it does not exist, it will be created automatically--> <rabbit:queue id="spring_fanout_queue_2" name="spring_fanout_queue_2" auto-declare="true"/> <!--Define broadcast type switch; And bind the above two queues--> <rabbit:fanout-exchange id="spring_fanout_exchange" name="spring_fanout_exchange" auto-declare="true"> <rabbit:bindings> <rabbit:binding queue="spring_fanout_queue_1" /> <rabbit:binding queue="spring_fanout_queue_2"/> </rabbit:bindings> </rabbit:fanout-exchange> <!-- Define queue--> <rabbit:queue id="spring_direct_queue" name="spring_direct_queue" auto-declare="true"/> <!-- definition Routing Routing mode interactive machine --> <rabbit:direct-exchange name="spring_direct_exchange" > <rabbit:bindings> <!--direct Switch binding queue of type key : route key queue: Queue name--> <rabbit:binding queue="spring_direct_queue" key="info"></rabbit:binding> </rabbit:bindings> </rabbit:direct-exchange> <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~Wildcards;*Match a word,#Match multiple words <!--Define the persistent queue in the broadcast switch. If it does not exist, it will be created automatically--> <rabbit:queue id="spring_topic_queue_star" name="spring_topic_queue_star" auto-declare="true"/> <!--Define the persistent queue in the broadcast switch. If it does not exist, it will be created automatically--> <rabbit:queue id="spring_topic_queue_well" name="spring_topic_queue_well" auto-declare="true"/> <!--Define the persistent queue in the broadcast switch. If it does not exist, it will be created automatically--> <rabbit:queue id="spring_topic_queue_well2" name="spring_topic_queue_well2" auto-declare="true"/> <!-- statement topic Type of switch --> <rabbit:topic-exchange id="spring_topic_exchange" name="spring_topic_exchange" auto-declare="true"> <rabbit:bindings> <rabbit:binding pattern="baiqi.*" queue="spring_topic_queue_star"/> <rabbit:binding pattern="baiqi.#" queue="spring_topic_queue_well"/> <rabbit:binding pattern="itcast.#" queue="spring_topic_queue_well2"/> </rabbit:bindings> </rabbit:topic-exchange> <!--definition rabbitTemplate Object operation can easily send messages in code--> <rabbit:template id="rabbitTemplate" connection-factory="connectionFactory"/>
classpath:rabbitmq.properties configuration file
rabbitmq.host=192.168.1.104 # ip address of RabbitMQ rabbitmq.port=5672 # Port to send data to RabbitMQ rabbitmq.username=guest # RabbitMQ login account rabbitmq.password=guest # RabbitMQ login password rabbitmq.virtual-host=/baiqi # Virtual machine name
spring sender code
import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.amqp.rabbit.core.RabbitTemplate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "classpath:spring-rabbitmq-producer.xml") // Load a spring configuration file public class ProducerTest { //1. Inject rabbit template @Autowired private RabbitTemplate rabbitTemplate; @Test public void testHelloWorld(){ // Entry mode //2. Send message rabbitTemplate.convertAndSend("spring_queue","hello world sp455445547ring...."); } /** * Send fanout message */ @Test public void testFanout(){ // The switch in subscription mode is of fanout type //2. Send message rabbitTemplate.convertAndSend("spring_fanout_exchange","","spring fanout...."); } @Test public void testDirect(){ // The switch in routing mode is of direct type //2. Send message rabbitTemplate.convertAndSend("spring_direct_exchange","info","spring Direct...."); } /** * Send topic message */ @Test public void testTopics(){ // The switch in Wildcard mode is of direct type //2. Send message rabbitTemplate.convertAndSend("spring_topic_exchange","baiqi.hehe.haha","spring topic...."); }
}
Listener correlation
spring configuration file
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:rabbit="http://www.springframework.org/schema/rabbit" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/rabbit http://www.springframework.org/schema/rabbit/spring-rabbit.xsd"> <!--Load profile--> <context:property-placeholder location="classpath:rabbitmq.properties"/> <!-- definition rabbitmq connectionFactory --> <rabbit:connection-factory id="connectionFactory" host="${rabbitmq.host}" port="${rabbitmq.port}" username="${rabbitmq.username}" password="${rabbitmq.password}" virtual-host="${rabbitmq.virtual-host}"/> <bean id="springQueueListener" class="com.baiqi.rabbitmq.listener.SpringQueueListener"/> // Just look at this one. What is annotated below is that the class names are different <!--<bean id="fanoutListener1" class="com.baiqi.rabbitmq.listener.FanoutListener"/> <bean id="fanoutListener2" class="com.baiqi.rabbitmq.listener.FanoutListener2"/> <bean id="topicListenerStar" class="com.baiqi.rabbitmq.listener.TopicListenerStar"/> <bean id="topicListenerWell" class="com.baiqi.rabbitmq.listener.TopicListenerWell"/> <bean id="topicListenerWell2" class="com.baiqi.rabbitmq.listener.TopicListenerWell2"/> --> <rabbit:listener-container connection-factory="connectionFactory" auto-declare="true"> // Create a long connection of listener type <rabbit:listener ref="springQueueListener" queue-names="spring_queue"/> // Queue names the listener only deals with the queue and only needs to write the queue name, because the association relationship is established at the sender <rabbit:listener ref="fanoutListener1" queue-names="spring_fanout_queue_1"/> <!--<rabbit:listener ref="fanoutListener2" queue-names="spring_fanout_queue_2"/> <rabbit:listener ref="topicListenerStar" queue-names="spring_topic_queue_star"/> <rabbit:listener ref="topicListenerWell" queue-names="spring_topic_queue_well"/> <rabbit:listener ref="topicListenerWell2" queue-names="spring_topic_queue_well2"/>--> </rabbit:listener-container> </beans>
monitor
import org.springframework.amqp.core.Message; import org.springframework.amqp.core.MessageListener; public class SpringQueueListener implements MessageListener { // As long as you override the onMessage method under the pretext of implementing MessageListener, you can listen to the queue @Override public void onMessage(Message message) { // Message here is the message //Print message System.out.println(new String(message.getBody())); } }
Listener test class
import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Test { public static void main(String[] args) { //Initialize the IOC container so that it can listen to the messages in the queue. The association relationships are mapped in the spring configuration file ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:spring-rabbitmq-consumer.xml"); }
}