springboot整合rabbitmq的五種模式示例以及詳解

1.基本消息模型:生產者–>隊列–>一個消費者
2.work消息模型:生產者–>隊列–>多個消費者共同消費
3.訂閱模型-Fanout:廣播,將消息交給所有綁定到交換機的隊列,每個消費者都可以收到同一條消息
4.訂閱模型-Direct:定向,把消息交給符合指定 rotingKey 的隊列(路由模式)
5.訂閱模型-Topic:通配符,把消息交給符合routing pattern(主題模式) 的隊列
(3、4、5這三種都屬於訂閱模型,只不過進行路由的方式不同。)

添加依賴 mq 

   <!--mq-->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-amqp</artifactId>
      <version>2.5.4</version>
    </dependency>

簡單隊列(模式)

一個生產者對應一個消費者
生產者

/*簡單隊列(模式)*/
 @Test
    public void contextLoads(){
        String msg = "這是一個簡單隊列模式";

        amqpTemplate.convertAndSend("spring.simple.queue", msg );

    }

消費者

@Component
public class SimpleListener {

    // 通過註解自動創建 spring.simple.queue 隊列
    @RabbitListener(queuesToDeclare = @Queue("spring.simple.queue"))
    public void listen(String msg) {
        System.out.println("簡單隊列 接收到消息:" + msg);
    }
}

Work模式

一個生產者對應多個消費者
生產者

/*work 模式*/
    @Test
    public void work() throws InterruptedException {
        String msg = "這是一個work模式";
        for (int i = 0; i < 10; i++) {
            amqpTemplate.convertAndSend("spring.work.queue", msg + i);
        }
        Thread.sleep(5000);
    }

消費者

@Component
public class WorkListener {

    // 通過註解自動創建 spring.work.queue 隊列
    @RabbitListener(queuesToDeclare = @Queue("spring.work.queue"))
    public void listen(String msg) {
        System.out.println("work模式 接收到消息:" + msg);
    }

    // 創建兩個隊列共同消費
    @RabbitListener(queuesToDeclare = @Queue("spring.work.queue"))
    public void listen2(String msg) {
        System.out.println("work模式二 接收到消息:" + msg);
    }
}

消費者

@Component
public class FanoutListener {

    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = "spring.fanout.queue", durable = "true"),
            exchange = @Exchange(
                    value = "spring.fanout.exchange",
                    ignoreDeclarationExceptions = "true",
                    type = ExchangeTypes.FANOUT
            )
    ))
    public void listen(String msg) {
        System.out.println("訂閱模式1 接收到消息:" + msg);
    }

    // 隊列2(第二個人),同樣能接收到消息
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = "spring.fanout2.queue", durable = "true"),
            exchange = @Exchange(
                    value = "spring.fanout.exchange",
                    ignoreDeclarationExceptions = "true",
                    type = ExchangeTypes.FANOUT
            )
    ))
    public void listen2(String msg) {
        System.out.println("訂閱模式2 接收到消息:" + msg);
    }
}

訂閱模型-Direct (路由模式)
在Fanout模式中,一條消息,會被所有訂閱的隊列都消費。但是,在某些場景下,我們希望不同的消息被不同的隊列消費。這時就要用到Direct類型的Exchange。給特定的消費者消費
在Direct模型下:

1.隊列與交換機的綁定,不能是任意綁定了,而是要指定一個RoutingKey(路由key)
2.消息的發送方在 向 Exchange發送消息時,也必須指定消息的 RoutingKey。
3.Exchange不再把消息交給每一個綁定的隊列,而是根據消息的Routing Key進行判斷,只有隊列的 Routingkey與消息的 Routing key完全一致,纔會接收到消息
生產者

/*訂閱模型-Direct (路由模式)*/
    @Test
    public void direct() throws InterruptedException {
        String msg = "路由模式";
        for (int i = 0; i < 10; i++) {
            amqpTemplate.convertAndSend("spring.direct.exchange", "direct", msg + i);
        }
        Thread.sleep(5000);
    }

消費者

@Component
public class DirectListener {

    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = "spring.direct.queue", durable = "true"),
            exchange = @Exchange(
                    value = "spring.direct.exchange",
                    ignoreDeclarationExceptions = "true"
            ),
            key = {"direct"}
    ))
    public void listen(String msg) {
        System.out.println("路由模式1 接收到消息:" + msg);
    }

    // 隊列2(第二個人),key值不同,接收不到消息
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = "spring.direct2.queue", durable = "true"),
            exchange = @Exchange(
                    value = "spring.direct.exchange",
                    ignoreDeclarationExceptions = "true"
            ),
            key = {"direct-test"}
    ))
    public void listen2(String msg) {
        System.out.println("路由模式2 接收到消息:" + msg);
    }
}

訂閱模型-Topic (主題模式)
Topic類型的Exchange與Direct相比,都是可以根據RoutingKey把消息路由到不同的隊列。只不過Topic類型Exchange可以讓隊列在綁定Routing key 的時候使用通配符!

Routingkey 一般都是有一個或多個單詞組成,多個單詞之間以”.”分割,例如: user.insert

通配符規則    舉例
#:匹配一個或多個詞    person.#:能夠匹配person.insert.save 或者 person.insert
*:匹配不多不少恰好1個詞    person.*:只能匹配person.insert

生產者

/* 訂閱模型-Topic (主題模式)*/
    @Test
    public void topic() throws InterruptedException {
        amqpTemplate.convertAndSend("spring.topic.exchange", "person.insert", "增加人員");
        amqpTemplate.convertAndSend("spring.topic.exchange", "person.delete", "刪除人員");
        amqpTemplate.convertAndSend("spring.topic.exchange", "money.insert", "加錢");
        amqpTemplate.convertAndSend("spring.topic.exchange", "money.delete", "減錢");
        Thread.sleep(5000);
    }

消費者

@Component
public class TopicListener {

    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = "spring.topic.queue", durable = "true"),
            exchange = @Exchange(
                    value = "spring.topic.exchange",
                    ignoreDeclarationExceptions = "true",
                    type = ExchangeTypes.TOPIC
            ),
            key = {"person.*"}
    ))
    public void listen(String msg) {
        System.out.println("person 接收到消息:" + msg);
    }

    // 通配規則不同,接收不到消息
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = "spring.topic.queue", durable = "true"),
            exchange = @Exchange(
                    value = "spring.topic.exchange",
                    ignoreDeclarationExceptions = "true",
                    type = ExchangeTypes.TOPIC
            ),
            key = {"money.*"}
    ))
    public void listen2(String msg) {
        System.out.println("money Student 接收到消息:" + msg);
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章