Spring Boot學習筆記(十七)Spring Boot RabbitMQ基本使用以及Topic Exchange, Fanout Exchange -- 實戰篇

Spring Boot RabbitMQ基本使用以及Topic Exchange, Fanout Exchange – 實戰篇

Github: IDEA Spring Boot RabbitMQ 消息隊列

初始化項目
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
項目結構
在這裏插入圖片描述
在這裏插入圖片描述
測試一:RabbitMQ的簡單使用

  • 初始化項目後,請自行搜索 win 10 rabbitMQ 安裝

  • 安裝完畢之後配置項目的 pom.xml, 其實就是添加以下依賴:

      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-amqp</artifactId>
      </dependency>
    

    pom.xml 完整文件:

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.1.9.RELEASE</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
        <groupId>wen</groupId>
        <artifactId>rabbitmq</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <name>rabbitmq</name>
        <description>Demo project for Spring Boot</description>
    
        <properties>
            <java.version>1.8</java.version>
        </properties>
    
        <dependencies>
            <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>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-amqp</artifactId>
            </dependency>
    
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    </project>
    
    
  • 接下來設置 項目目錄 resources下的 application.properties 文件,配置 rabbitmq 的安裝地址、端口及賬戶信息:

    spring.rabbitmq.host=127.0.0.1
    spring.rabbitmq.port=5672
    spring.rabbitmq.username=guest
    spring.rabbitmq.password=guest
    
  • 定義隊列 config包下 RabbitConfig.java, 測試一用到的隊列是

        @Bean
        public Queue Queue() {
            return new Queue("hello");
        }
    

    RabbitConfig.java 完整代碼:

    package wen.rabbitmq.config;
    
    import org.springframework.amqp.core.Queue;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class RabbitConfig {
    
        @Bean
        public Queue Queue() {
            return new Queue("hello");
        }
    
        @Bean
        public Queue StephanieQueue() {
            return new Queue("Stephanie");
        }
    
        @Bean
        public Queue objectQueue() {
            return new Queue("many to many");
        }
    
        @Bean
        public Queue UserQueue() {
            return new Queue("user");
        }
    }
    
    
  • 定義發送者, AmqpTemplate 是 Spring Boot 提供的默認實現:

    package wen.rabbitmq.oto.sender;
    
    import org.springframework.amqp.core.AmqpTemplate;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    
    import java.util.Date;
    
    @Component
    public class HelloSender {
    
        @Autowired
        private AmqpTemplate rabbitTemplate;
    
        public void send() {
            String context = "hello " + new Date();
            System.out.println("Hello Sender: " + context);
            this.rabbitTemplate.convertAndSend("hello", context);
        }
    }
    
    
  • 定義接收者,注意使用註解 @RabbitListener ,使用 queues 指明隊列名稱, @RabbitHandler 爲具體接收的方法,注意,發送者和接收者的 queue name 必須一致,不然不能接收:

    package wen.rabbitmq.oto.receiver;
    
    import org.springframework.amqp.rabbit.annotation.RabbitHandler;
    import org.springframework.amqp.rabbit.annotation.RabbitListener;
    import org.springframework.stereotype.Component;
    
    @Component
    @RabbitListener(queues = "hello")
    public class HelloReceiver {
    
        @RabbitHandler
        public void process(String hello) {
            System.out.println("Hello Receiver : " + hello);
        }
    
    }
    
    
  • 測試代碼:

    package wen.rabbitmq;
    
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.test.context.junit4.SpringRunner;
    import wen.rabbitmq.fanout.send.FanoutSender;
    import wen.rabbitmq.model.User;
    import wen.rabbitmq.ntn.sender.SenderOne;
    import wen.rabbitmq.ntn.sender.SenderTwo;
    import wen.rabbitmq.object.sender.ObjectSender;
    import wen.rabbitmq.otn.sender.StephanieSender;
    import wen.rabbitmq.oto.sender.HelloSender;
    import wen.rabbitmq.topic.sender.TopicSender;
    
    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class RabbitmqApplicationTests {
    
        @Autowired
        private HelloSender helloSender;
    
        /**
         * one to one test
         *
         * @throws Exception
         */
        @Test
        public void hello() throws Exception {
            helloSender.send();
            Thread.sleep(1000L);
        }
    
    }
    
    

    在這裏插入圖片描述

測試二:一對多發送

  • 配置隊列:

    @Bean
    public Queue StephanieQueue() {
        return new Queue("Stephanie");
    }
    
  • 定義一個發送者:

    package wen.rabbitmq.otn.sender;
    
    import org.springframework.amqp.core.AmqpTemplate;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    
    @Component
    public class StephanieSender {
    
        @Autowired
        private AmqpTemplate rabbitTemplate;
    
        public void send(int i) {
            String context = "Stephanie Queue: " + i;
            System.out.println("Sender: " + context);
            this.rabbitTemplate.convertAndSend("Stephanie", context);
        }
    
    }	
    
  • 定義兩個接收者:

    package wen.rabbitmq.otn.receiver;
    
    import org.springframework.amqp.rabbit.annotation.RabbitHandler;
    import org.springframework.amqp.rabbit.annotation.RabbitListener;
    import org.springframework.stereotype.Component;
    
    @Component
    @RabbitListener(queues = "Stephanie")
    public class ReceiverOne {
    
        @RabbitHandler
        public void process(String Stephanie) {
            System.out.println("Receiver One: " + Stephanie);
        }
    
    }
    
    
    package wen.rabbitmq.otn.receiver;
    
    import org.springframework.amqp.rabbit.annotation.RabbitHandler;
    import org.springframework.amqp.rabbit.annotation.RabbitListener;
    import org.springframework.stereotype.Component;
    
    @Component
    @RabbitListener(queues = "Stephanie")
    public class ReceiverTwo {
    
        @RabbitHandler
        public void process(String Stephanie) {
            System.out.println("Receiver Two: " + Stephanie);
        }
    
    }
    
    
  • 以上定義了一個發送者、兩個接收者,發送一百個消息:

    package wen.rabbitmq;
    
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.test.context.junit4.SpringRunner;
    import wen.rabbitmq.fanout.send.FanoutSender;
    import wen.rabbitmq.model.User;
    import wen.rabbitmq.ntn.sender.SenderOne;
    import wen.rabbitmq.ntn.sender.SenderTwo;
    import wen.rabbitmq.object.sender.ObjectSender;
    import wen.rabbitmq.otn.sender.StephanieSender;
    import wen.rabbitmq.oto.sender.HelloSender;
    import wen.rabbitmq.topic.sender.TopicSender;
    
    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class RabbitmqApplicationTests {
    
        @Autowired
        private HelloSender helloSender;
    
        @Autowired
        private StephanieSender stephanieSender;
    
        /**
         * one to one test
         *
         * @throws Exception
         */
        @Test
        public void hello() throws Exception {
            helloSender.send();
            Thread.sleep(1000L);
        }
    
        /**
         * one to N tests
         *
         * @throws Exception
         */
        @Test
        public void oneToN() throws Exception {
            for (int i = 0; i < 100; i++) {
                stephanieSender.send(i);
            }
            Thread.sleep(10000L);
        }
    }
    

    在這裏插入圖片描述

  • 通過測試得知:一個發送者、多 個接收者,經過測試接收端均勻接收到消息,也說明接收端自動進行了均衡負載,我們也可以利用這個特性做流量分發

測試三:多對多消息發送

  • 配置隊列:

    @Bean
    public Queue StephanieQueue() {
        return new Queue("many to many");
    }
    
  • 定義兩個接受者, 兩個發送者:

    package wen.rabbitmq.ntn.sender;
    
    import org.springframework.amqp.core.AmqpTemplate;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    
    @Component
    public class SenderOne {
    
        @Autowired
        private AmqpTemplate rabbitTemplate;
    
        public void send(int i) {
            String context = "multi Queue: " + i;
            System.out.println("Sender one: " + context);
            this.rabbitTemplate.convertAndSend("many to many", context);
        }
    
    }
    
    
    package wen.rabbitmq.ntn.sender;
    
    import org.springframework.amqp.core.AmqpTemplate;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    
    @Component
    public class SenderTwo {
    
        @Autowired
        private AmqpTemplate rabbitTemplate;
    
        public void send(int i) {
            String context = "multi Queue: " + i;
            System.out.println("Sender two: " + context);
            this.rabbitTemplate.convertAndSend("many to many", context);
        }
    
    }
    
    package wen.rabbitmq.ntn.receiver;
    
    import org.springframework.amqp.rabbit.annotation.RabbitHandler;
    import org.springframework.amqp.rabbit.annotation.RabbitListener;
    import org.springframework.stereotype.Component;
    
    @Component
    @RabbitListener(queues = "many to many")
    public class MultiReceiverOne {
    
        @RabbitHandler
        public void process(String object) {
            System.out.println("Receiver One: " + object);
        }
    
    }
    
    
    package wen.rabbitmq.ntn.receiver;
    
    import org.springframework.amqp.rabbit.annotation.RabbitHandler;
    import org.springframework.amqp.rabbit.annotation.RabbitListener;
    import org.springframework.stereotype.Component;
    
    @Component
    @RabbitListener(queues = "many to many")
    public class MultiReceiverTwo {
    
        @RabbitHandler
        public void process(String object) {
            System.out.println("Receiver Two: " + object);
        }
    
    }
    
    
  • 測試代碼:

    package wen.rabbitmq;
    
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.test.context.junit4.SpringRunner;
    import wen.rabbitmq.fanout.send.FanoutSender;
    import wen.rabbitmq.model.User;
    import wen.rabbitmq.ntn.sender.SenderOne;
    import wen.rabbitmq.ntn.sender.SenderTwo;
    import wen.rabbitmq.object.sender.ObjectSender;
    import wen.rabbitmq.otn.sender.StephanieSender;
    import wen.rabbitmq.oto.sender.HelloSender;
    import wen.rabbitmq.topic.sender.TopicSender;
    
    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class RabbitmqApplicationTests {
    
        @Autowired
        private HelloSender helloSender;
    
        @Autowired
        private StephanieSender stephanieSender;
    
        @Autowired
        private SenderOne senderOne;
    
        @Autowired
        private SenderTwo senderTwo;
    
        /**
         * one to one test
         *
         * @throws Exception
         */
        @Test
        public void hello() throws Exception {
            helloSender.send();
            Thread.sleep(1000L);
        }
    
        /**
         * one to N tests
         *
         * @throws Exception
         */
        @Test
        public void oneToN() throws Exception {
            for (int i = 0; i < 100; i++) {
                stephanieSender.send(i);
            }
            Thread.sleep(10000L);
        }
    
        /**
         * many to many tests
         *
         * @throws Exception
         */
        @Test
        public void manyToMany() throws Exception {
            for (int i = 0; i < 100; i++) {
                senderOne.send(i);
                senderTwo.send(i);
            }
            Thread.sleep(10000L);
        }
    }
    
    

    在這裏插入圖片描述

  • 發送端交替發送消息,接收端仍然會均勻接收到消息

測試四:rabbitMQ 消息隊列高級使用

  • 對象的支持:Spring Boot 已經完美的支持對象的發送和接收,不需要格外的配置

  • 配置隊列:

    @Bean
    public Queue UserQueue() {
        return new Queue("user");
    }
    
  • 定義model的User類,記得一定要加上 implements Serializable

    package wen.rabbitmq.model;
    
    import java.io.Serializable;
    
    public class User implements Serializable {
    
        String username;
    
        String password;
    
        public User() {
        }
    
        public User(String username, String password) {
            this.username = username;
            this.password = password;
        }
    
        @Override
        public String toString() {
            return "[ username: " + this.username + " , " + "password: " + password + " ]";
        }
    
        public String getUsername() {
            return username;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
        public String getPassword() {
            return password;
        }
    
        public void setPassword(String password) {
            this.password = password;
        }
    }
    
    
  • 發送者:

    package wen.rabbitmq.otn.sender;
    
    import org.springframework.amqp.core.AmqpTemplate;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    
    @Component
    public class StephanieSender {
    
        @Autowired
        private AmqpTemplate rabbitTemplate;
    
        public void send(int i) {
            String context = "Stephanie Queue: " + i;
            System.out.println("Sender: " + context);
            this.rabbitTemplate.convertAndSend("Stephanie", context);
        }
    }
    
  • 定義兩個接收者:

    package wen.rabbitmq.otn.receiver;
    
    import org.springframework.amqp.rabbit.annotation.RabbitHandler;
    import org.springframework.amqp.rabbit.annotation.RabbitListener;
    import org.springframework.stereotype.Component;
    
    @Component
    @RabbitListener(queues = "Stephanie")
    public class ReceiverOne {
    
        @RabbitHandler
        public void process(String Stephanie) {
            System.out.println("Receiver One: " + Stephanie);
        }
    
    }
    
    
    package wen.rabbitmq.otn.receiver;
    
    import org.springframework.amqp.rabbit.annotation.RabbitHandler;
    import org.springframework.amqp.rabbit.annotation.RabbitListener;
    import org.springframework.stereotype.Component;
    
    @Component
    @RabbitListener(queues = "Stephanie")
    public class ReceiverTwo {
    
        @RabbitHandler
        public void process(String Stephanie) {
            System.out.println("Receiver Two: " + Stephanie);
        }
    
    }
    
    
  • 測試代碼:

    package wen.rabbitmq;
    
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.test.context.junit4.SpringRunner;
    import wen.rabbitmq.fanout.send.FanoutSender;
    import wen.rabbitmq.model.User;
    import wen.rabbitmq.ntn.sender.SenderOne;
    import wen.rabbitmq.ntn.sender.SenderTwo;
    import wen.rabbitmq.object.sender.ObjectSender;
    import wen.rabbitmq.otn.sender.StephanieSender;
    import wen.rabbitmq.oto.sender.HelloSender;
    import wen.rabbitmq.topic.sender.TopicSender;
    
    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class RabbitmqApplicationTests {
    
        @Autowired
        private HelloSender helloSender;
    
        @Autowired
        private StephanieSender stephanieSender;
    
        @Autowired
        private SenderOne senderOne;
    
        @Autowired
        private SenderTwo senderTwo;
    
        @Autowired
        private ObjectSender objectSender;
    
        /**
         * one to one test
         *
         * @throws Exception
         */
        @Test
        public void hello() throws Exception {
            helloSender.send();
            Thread.sleep(1000L);
        }
    
        /**
         * one to N tests
         *
         * @throws Exception
         */
        @Test
        public void oneToN() throws Exception {
            for (int i = 0; i < 100; i++) {
                stephanieSender.send(i);
            }
            Thread.sleep(10000L);
        }
    
        /**
         * many to many tests
         *
         * @throws Exception
         */
        @Test
        public void manyToMany() throws Exception {
            for (int i = 0; i < 100; i++) {
                senderOne.send(i);
                senderTwo.send(i);
            }
            Thread.sleep(10000L);
        }
    
        /**
         * user test
         *
         * @throws Exception
         */
        @Test
        public void sendObject() throws Exception {
            User user = new User("Stephanie", "123");
            objectSender.send(user);
            Thread.sleep(1000L);
        }
    }
    
    

    在這裏插入圖片描述

測試五:Topic Exchange的使用

  • Topic 是 RabbitMQ 中最靈活的方式,可以根據 routing_key ⾃自由的綁定不同的隊列,首先對 Topic 規則配置,這⾥裏使用兩個隊列來測試

  • 設計 queueMessages 同時匹配兩個隊列,queueMessage 只匹配“topic.message”隊列:

    package wen.rabbitmq.config;
    
    import org.springframework.amqp.core.Binding;
    import org.springframework.amqp.core.BindingBuilder;
    import org.springframework.amqp.core.Queue;
    import org.springframework.amqp.core.TopicExchange;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class TopicRabbitConfig {
    
        final static String MESSAGE = "topic.message";
        final static String MESSAGES = "topic.messages";
    
        //定義隊列
        @Bean
        public Queue queueMessage() {
            return new Queue(TopicRabbitConfig.MESSAGE);
        }
    
        @Bean
        public Queue queueMessages() {
            return new Queue(TopicRabbitConfig.MESSAGES);
        }
    
        //交換機
        @Bean
        TopicExchange exchange() {
            return new TopicExchange("exchange");
        }
    
        //將隊列和交換機綁定:queueMessages 同時匹配兩個隊列,queueMessage 只匹配“topic.message”隊列
        @Bean
        Binding bindingExchangeMessage(Queue queueMessage, TopicExchange exchange) {
            return BindingBuilder.bind(queueMessage).to(exchange).with("topic.message");
        }
    
        @Bean
        Binding bindingExchangeMessages(Queue queueMessages, TopicExchange exchange) {
            return BindingBuilder.bind(queueMessages).to(exchange).with("topic.#");
        }
    }
    
    
  • 發送者

    package wen.rabbitmq.topic.sender;
    
    import org.springframework.amqp.core.AmqpTemplate;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    
    @Component
    public class TopicSender {
    
        @Autowired
        private AmqpTemplate rabbitTemplate;
    
        public void send_one() {
            String context = "Hi, I am message one";
            System.out.println("Sender: " + context);
            this.rabbitTemplate.convertAndSend("exchange", "topic.message", context);
        }
    
        public void send_two() {
            String context = "Hi, I am message two";
            System.out.println("Sender: " + context);
            this.rabbitTemplate.convertAndSend("exchange", "topic.messages", context);
        }
    
    }	
    
  • 接收者:

    package wen.rabbitmq.topic.receiver;
    
    import org.springframework.amqp.rabbit.annotation.RabbitHandler;
    import org.springframework.amqp.rabbit.annotation.RabbitListener;
    import org.springframework.stereotype.Component;
    
    @Component
    @RabbitListener(queues = "topic.message")
    public class TopicReceiverOne {
    
        @RabbitHandler
        public void process(String message) {
            System.out.println("Topic Receiver One: " + message);
        }
    
    }
    
    
    package wen.rabbitmq.topic.receiver;
    
    import org.springframework.amqp.rabbit.annotation.RabbitHandler;
    import org.springframework.amqp.rabbit.annotation.RabbitListener;
    import org.springframework.stereotype.Component;
    
    @Component
    @RabbitListener(queues = "topic.messages")
    public class TopicReceiverTwo {
    
        @RabbitHandler
        public void process(String message) {
            System.out.println("Topic Receiver Two: " + message);
        }
    
    }
    
    
  • 測試代碼:send_one()會匹配到 topic.# 和 topic.message, 兩個 Receiver 都可以收到消息,發送 send2 只有 topic.# 可以匹配,Receiver2 監聽到了消息

    package wen.rabbitmq;
    
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.test.context.junit4.SpringRunner;
    import wen.rabbitmq.fanout.send.FanoutSender;
    import wen.rabbitmq.model.User;
    import wen.rabbitmq.ntn.sender.SenderOne;
    import wen.rabbitmq.ntn.sender.SenderTwo;
    import wen.rabbitmq.object.sender.ObjectSender;
    import wen.rabbitmq.otn.sender.StephanieSender;
    import wen.rabbitmq.oto.sender.HelloSender;
    import wen.rabbitmq.topic.sender.TopicSender;
    
    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class RabbitmqApplicationTests {
    
        @Autowired
        private HelloSender helloSender;
    
        @Autowired
        private StephanieSender stephanieSender;
    
        @Autowired
        private SenderOne senderOne;
    
        @Autowired
        private SenderTwo senderTwo;
    
        @Autowired
        private ObjectSender objectSender;
    
        @Autowired
        private TopicSender topicSender;
    
        /**
         * one to one test
         *
         * @throws Exception
         */
        @Test
        public void hello() throws Exception {
            helloSender.send();
            Thread.sleep(1000L);
        }
    
        /**
         * one to N tests
         *
         * @throws Exception
         */
        @Test
        public void oneToN() throws Exception {
            for (int i = 0; i < 100; i++) {
                stephanieSender.send(i);
            }
            Thread.sleep(10000L);
        }
    
        /**
         * many to many tests
         *
         * @throws Exception
         */
        @Test
        public void manyToMany() throws Exception {
            for (int i = 0; i < 100; i++) {
                senderOne.send(i);
                senderTwo.send(i);
            }
            Thread.sleep(10000L);
        }
    
        /**
         * user test
         *
         * @throws Exception
         */
        @Test
        public void sendObject() throws Exception {
            User user = new User("Stephanie", "123");
            objectSender.send(user);
            Thread.sleep(1000L);
        }
    
        /**
         * 測試topic_rabbit
         *
         * @throws Exception
         */
        @Test
        public void topic() throws Exception {
            topicSender.send_one();
            Thread.sleep(5000L);
            System.out.println("-----send two-----");
            topicSender.send_two();
            Thread.sleep(1000L);
        }
    }
    

    在這裏插入圖片描述

測試六:Fanout Exchange

  • Fanout 就是廣播模式或者訂閱模式,給 Fanout 交換機發送消息,綁定了這個交換機的所有隊列
    都收到這個消息

  • Fanout 相關配置:

    package wen.rabbitmq.config;
    
    import org.springframework.amqp.core.Binding;
    import org.springframework.amqp.core.BindingBuilder;
    import org.springframework.amqp.core.FanoutExchange;
    import org.springframework.amqp.core.Queue;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class FanoutRabbitConfig {
    
        // 定義隊列
        @Bean
        public Queue AMessage() {
            return new Queue("fanout.A");
        }
    
        @Bean
        public Queue BMessage() {
            return new Queue("fanout.B");
        }
    
        @Bean
        public Queue CMessage() {
            return new Queue("fanout.C");
        }
    
        //定義交換機
        @Bean
        FanoutExchange fanoutExchange() {
            return new FanoutExchange("fanoutExchange");
        }
    
        //分部進行綁定
        @Bean
        Binding bindingExchangeA(Queue AMessage, FanoutExchange fanoutExchange) {
            return BindingBuilder.bind(AMessage).to(fanoutExchange);
        }
    
        @Bean
        Binding bindingExchangeB(Queue BMessage, FanoutExchange fanoutExchange) {
            return BindingBuilder.bind(BMessage).to(fanoutExchange);
        }
    
        @Bean
        Binding bindingExchangeC(Queue CMessage, FanoutExchange fanoutExchange) {
            return BindingBuilder.bind(CMessage).to(fanoutExchange);
        }
    }
    
    
  • 發送者:

    package wen.rabbitmq.fanout.send;
    
    import org.springframework.amqp.core.AmqpTemplate;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    
    @Component
    public class FanoutSender {
    
        @Autowired
        private AmqpTemplate rabbitTemplate;
    
        public void send() {
            String context = "hi, fanout message";
            System.out.println("Sender : " + context);
            this.rabbitTemplate.convertAndSend("fanoutExchange", "", context);
        }
    }
    
  • 接收者

    package wen.rabbitmq.fanout.receiver;
    
    import org.springframework.amqp.rabbit.annotation.RabbitHandler;
    import org.springframework.amqp.rabbit.annotation.RabbitListener;
    import org.springframework.stereotype.Component;
    
    @Component
    @RabbitListener(queues = "fanout.A")
    public class FanoutReceiverA {
    
        @RabbitHandler
        public void process(String message) {
            System.out.println("fanout Receiver A: " + message);
        }
    
    }
    
    
    package wen.rabbitmq.fanout.receiver;
    
    import org.springframework.amqp.rabbit.annotation.RabbitHandler;
    import org.springframework.amqp.rabbit.annotation.RabbitListener;
    import org.springframework.stereotype.Component;
    
    @Component
    @RabbitListener(queues = "fanout.B")
    public class FanoutReceiverB {
    
        @RabbitHandler
        public void process(String message) {
            System.out.println("fanout Receiver B: " + message);
        }
    
    }
    
    package wen.rabbitmq.fanout.receiver;
    
    import org.springframework.amqp.rabbit.annotation.RabbitHandler;
    import org.springframework.amqp.rabbit.annotation.RabbitListener;
    import org.springframework.stereotype.Component;
    
    @Component
    @RabbitListener(queues = "fanout.C")
    public class FanoutReceiverC {
    
        @RabbitHandler
        public void process(String message) {
            System.out.println("fanout Receiver C: " + message);
        }
    
    }
    
    
  • 測試代碼:

    package wen.rabbitmq;
    
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.test.context.junit4.SpringRunner;
    import wen.rabbitmq.fanout.send.FanoutSender;
    import wen.rabbitmq.model.User;
    import wen.rabbitmq.ntn.sender.SenderOne;
    import wen.rabbitmq.ntn.sender.SenderTwo;
    import wen.rabbitmq.object.sender.ObjectSender;
    import wen.rabbitmq.otn.sender.StephanieSender;
    import wen.rabbitmq.oto.sender.HelloSender;
    import wen.rabbitmq.topic.sender.TopicSender;
    
    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class RabbitmqApplicationTests {
    
        @Autowired
        private HelloSender helloSender;
    
        @Autowired
        private StephanieSender stephanieSender;
    
        @Autowired
        private SenderOne senderOne;
    
        @Autowired
        private SenderTwo senderTwo;
    
        @Autowired
        private ObjectSender objectSender;
    
        @Autowired
        private TopicSender topicSender;
    
        @Autowired
        private FanoutSender fanoutSender;
    
        /**
         * one to one test
         *
         * @throws Exception
         */
        @Test
        public void hello() throws Exception {
            helloSender.send();
            Thread.sleep(1000L);
        }
    
        /**
         * one to N tests
         *
         * @throws Exception
         */
        @Test
        public void oneToN() throws Exception {
            for (int i = 0; i < 100; i++) {
                stephanieSender.send(i);
            }
            Thread.sleep(10000L);
        }
    
        /**
         * many to many tests
         *
         * @throws Exception
         */
        @Test
        public void manyToMany() throws Exception {
            for (int i = 0; i < 100; i++) {
                senderOne.send(i);
                senderTwo.send(i);
            }
            Thread.sleep(10000L);
        }
    
        /**
         * user test
         *
         * @throws Exception
         */
        @Test
        public void sendObject() throws Exception {
            User user = new User("Stephanie", "123");
            objectSender.send(user);
            Thread.sleep(1000L);
        }
    
        /**
         * 測試topic_rabbit
         *
         * @throws Exception
         */
        @Test
        public void topic() throws Exception {
            topicSender.send_one();
            Thread.sleep(5000L);
            System.out.println("-----send two-----");
            topicSender.send_two();
            Thread.sleep(1000L);
        }
    
        /**
         * fanout test
         *
         * @throws Exception
         */
        @Test
        public void fanoutSender() throws Exception {
            fanoutSender.send();
            Thread.sleep(1000L);
        }
    }
    
    

    在這裏插入圖片描述

  • 結果說明,綁定到 fanout 交換機上面的隊列都收到了消息

總結

  • RabbitMQ 一個非常高效的消息隊列組件,使⽤ RabbitMQ 可以方便的解耦項目之間的依賴,同時利用RabbitMQ 的特性可以做很多的解決方案
  • Spring Boot 爲 RabbitMQ 提供了支持組件 spring-boot-starter-amqp,加載的時候會自動進行配置,並且預置了 RabbitTemplate,可以讓我們在項目中方便的調用
  • 在測試使用的過程中發現,RabbitMQ 非常的靈活,可以使用各種策略將不同的發送者和接收者綁定在一起,這些特性在實際項目使用中非常的高效便利
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章