Spring Boot 技术探索

Spring Boot makes it easy to create stand-alone, production-grade Spring based Applications that you can "just run".

30、Spring Boot之RabbitMQ的使用

平台环境:

名称

版本号

Mac OS X

10.15.1

JDK

1.8.0_201

Apache Maven

3.6.0

IntelliJ IDEA

2019.3 (Ultimate Edition)

Spring Boot

2.2.1.RELEASE

RabbitMQ

3.8.1

 

  什么是AMQP?

  AMQP即Advanced Message Queuing Protocol,其目标是成为所有消息中间件之间交互的标准协议。基于此协议的客户端与消息中间件可传递消息,并不受客户端/中间件不同产品,不同的开发语言等条件的限制。

  

  什么是RabbitMQ?

  RabbitMQ是AMQP的一个实现。

 

  五个主要概念:

  • Sender(发送者),负责发送消息(就像火车站)。
  • Message(消息),可以是字符也可以是对象(就像车厢)。
  • Exchange(交换机),负责路由与过滤消息到指定的队列(就像带哨卡的调度站)。
  • Queue(队列),负责承载消息(就像铁轨)。
  • Receiver(接收者),负责接收消息(就像火车站)。

 

  其他概念:

  • routingKey(路由键),负责指明消息要送达的目的地,支持自定义规则(就像火车票)。
  • Queue name(队列名称),负责标明此队列的目的地(铁轨通向哪里)。
  • binding(绑定),负责将Exchange(交换机)与Queue(队列)连接到一起。

 

安装

brew install rabbitmq

######################################################################## 100.0%
==> /usr/bin/unzip -qq -j /usr/local/Cellar/rabbitmq/3.8.1/plugins/rabbitmq_mana
==> Caveats
Management Plugin enabled by default at http://localhost:15672

Bash completion has been installed to:
  /usr/local/etc/bash_completion.d

To have launchd start rabbitmq now and restart at login:
  brew services start rabbitmq
Or, if you don't want/need a background service you can just run:
  rabbitmq-server
==> Summary
  /usr/local/Cellar/rabbitmq/3.8.1: 279 files, 20MB, built in 1 minute 3 seconds

 

启动

brew services start rabbitmq

 

停止

brew services stop rabbitmq

 

如果不想后台服务模式,就这样启动:

/usr/local/Cellar/rabbitmq/3.8.1/sbin/rabbitmq-server

也可以把当前目录加入环境变量中,之后就可以之际用rabbitmq-server启动了
export PATH=$PATH:/usr/local/opt/rabbitmq/sbin

 

查看运行状态

ps -ef|grep rabbitmq

 

启动成功

wangdeMacBook-Pro:~ wang$ rabbitmq-server
-bash: rabbitmq-server: command not found
wangdeMacBook-Pro:~ wang$ /usr/local/Cellar/rabbitmq/3.8.1/sbin/rabbitmq-server 
 
  ##  ##      RabbitMQ 3.8.1
  ##  ##
  ##########  Copyright (c) 2007-2019 Pivotal Software, Inc.
  ######  ##
  ##########  Licensed under the MPL 1.1. Website: https://rabbitmq.com

  Doc guides: https://rabbitmq.com/documentation.html
  Support:    https://rabbitmq.com/contact.html
  Tutorials:  https://rabbitmq.com/getstarted.html
  Monitoring: https://rabbitmq.com/monitoring.html

  Logs: /usr/local/var/log/rabbitmq/rabbit@localhost.log
        /usr/local/var/log/rabbitmq/rabbit@localhost_upgrade.log

  Config file(s): (none)

  Starting broker... completed with 6 plugins.

 

服务启动成功之后可以访问此地址打开控制管理界面http://localhost:15672

输入用户名和密码:guest,guest,默认guest就是超级管理员权限。

 

登录之后看到管理界面

 

账号配置

## 列出全部账号
./rabbitmqctl list_users

## 列出账号权限
./rabbitmqctl list_permissions

## 添加账号
./rabbitmqctl add_user admin admin

## 添加访问权限
./rabbitmqctl set_permissions -p "/" admin ".*" ".*" ".*"

## 设置超级权限
./rabbitmqctl set_user_tags admin administrator

 

 

 

接下来开始通过Spring Boot操作RabbitMQ

 

交换机有四种模式:

  • Direct
  • Topic
  • Fanout
  • Headers

 

Direct模式

先从最简单的Direct模式(也是RabbitMQ默认的交换机模式)开始。

这种模式只要sender和receiver的routing_key匹配成功就能发送与接收消息。

pom.xml

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-amqp</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
        <exclusions>
            <exclusion>
                <groupId>org.junit.vintage</groupId>
                <artifactId>junit-vintage-engine</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>org.springframework.amqp</groupId>
        <artifactId>spring-rabbit-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

 

application.properties

spring.rabbitmq.host=127.0.0.1
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest

 

定义队列

RabbitConfig.java

package com.example.demo.rabbit;


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 helloQueue()
    {
        return new Queue("hello");
    }
}

 

发送者

HelloSender.java

package com.example.demo.rabbit.hello;


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
{
    private AmqpTemplate rabbitTemplate;


    @Autowired
    public void setRabbitTemplate(AmqpTemplate rabbitTemplate)
    {
        this.rabbitTemplate = rabbitTemplate;
    }


    public void send()
    {
        String context = "Send hello " + new Date();
        System.out.println("Sender: " + context);
        this.rabbitTemplate.convertAndSend("hello", context);
    }


    public void send(int i)
    {
        String context = "Send hello " + i;
        System.out.println("Sender: " + context);
        this.rabbitTemplate.convertAndSend("hello", context);
    }
}

 

接收者

HelloReceiver.java

package com.example.demo.rabbit.hello;


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("Receiver: " + hello);
    }
}

 

测试

HelloTest.java

package com.example.demo.rabbit;


import com.example.demo.rabbit.hello.HelloSender;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;


@SpringBootTest
class HelloTest
{
    @Autowired
    HelloSender helloSender;


    @Test
    void hello() throws Exception
    {
        helloSender.send();
        Thread.sleep(1000L);
    }
}

 

执行测试hello()

Sender: Send hello Fri Dec 06 10:41:51 CST 2019
Receiver: Send hello Fri Dec 06 10:41:51 CST 2019

 

再新建一个接收者2

HelloReceiver2.java

package com.example.demo.rabbit.hello;


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 HelloReceiver2
{
    @RabbitHandler
    public void process(String hello)
    {
        System.out.println("Receiver2: " + hello);
    }
}

 

增加测试方法

@Test
void oneToMany() throws Exception
{
    for (int i = 0; i < 30; i++)
    {
        helloSender.send(i);
    }
    Thread.sleep(1000L);
}

 

执行测试oneToMany()

Sender: Send hello 0
Sender: Send hello 1
Sender: Send hello 2
Sender: Send hello 3
Sender: Send hello 4
Sender: Send hello 5
Sender: Send hello 6
Sender: Send hello 7
Sender: Send hello 8
Sender: Send hello 9
Sender: Send hello 10
Sender: Send hello 11
Sender: Send hello 12
Sender: Send hello 13
Sender: Send hello 14
Sender: Send hello 15
Sender: Send hello 16
Sender: Send hello 17
Sender: Send hello 18
Sender: Send hello 19
Sender: Send hello 20
Sender: Send hello 21
Sender: Send hello 22
Sender: Send hello 23
Sender: Send hello 24
Sender: Send hello 25
Sender: Send hello 26
Sender: Send hello 27
Sender: Send hello 28
Sender: Send hello 29
Receiver: Send hello 0
Receiver2: Send hello 1
Receiver: Send hello 2
Receiver2: Send hello 3
Receiver: Send hello 4
Receiver2: Send hello 5
Receiver: Send hello 6
Receiver2: Send hello 7
Receiver: Send hello 8
Receiver2: Send hello 9
Receiver: Send hello 10
Receiver: Send hello 12
Receiver2: Send hello 11
Receiver: Send hello 14
Receiver2: Send hello 13
Receiver: Send hello 16
Receiver2: Send hello 15
Receiver: Send hello 18
Receiver2: Send hello 17
Receiver: Send hello 20
Receiver2: Send hello 19
Receiver: Send hello 22
Receiver2: Send hello 21
Receiver: Send hello 24
Receiver2: Send hello 23
Receiver: Send hello 26
Receiver2: Send hello 25
Receiver: Send hello 28
Receiver2: Send hello 27
Receiver2: Send hello 29

可以看到,此模式下:一条消息只能发送给一个接收者,多个接收者接收同一个队列的消息时会自动均匀分配接收。

 

如果有两个sender会怎么样?

新建HelloSender2.java

package com.example.demo.rabbit.hello;


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 HelloSender2
{
    private AmqpTemplate rabbitTemplate;


    @Autowired
    public void setRabbitTemplate(AmqpTemplate rabbitTemplate)
    {
        this.rabbitTemplate = rabbitTemplate;
    }


    public void send(int i)
    {
        String context = "Send2 hello " + i;
        System.out.println("Sender2: " + context);
        this.rabbitTemplate.convertAndSend("hello", context);
    }
}

 

增加测试方法

@Test
void manyToMany() throws Exception
{
    for (int i = 0; i < 30; i++)
    {
        helloSender.send(i);
        helloSender2.send(i);
    }
    Thread.sleep(1000L);
}

 

测试manyToMany()

Sender: Send hello 0
Sender2: Send2 hello 0
Sender: Send hello 1
Sender2: Send2 hello 1
Sender: Send hello 2
Sender2: Send2 hello 2
Sender: Send hello 3
Sender2: Send2 hello 3
Sender: Send hello 4
Sender2: Send2 hello 4
Sender: Send hello 5
Sender2: Send2 hello 5
Sender: Send hello 6
Sender2: Send2 hello 6
Sender: Send hello 7
Sender2: Send2 hello 7
Sender: Send hello 8
Sender2: Send2 hello 8
Sender: Send hello 9
Sender2: Send2 hello 9
Sender: Send hello 10
Sender2: Send2 hello 10
Sender: Send hello 11
Sender2: Send2 hello 11
Sender: Send hello 12
Sender2: Send2 hello 12
Sender: Send hello 13
Sender2: Send2 hello 13
Sender: Send hello 14
Sender2: Send2 hello 14
Sender: Send hello 15
Sender2: Send2 hello 15
Sender: Send hello 16
Sender2: Send2 hello 16
Sender: Send hello 17
Sender2: Send2 hello 17
Sender: Send hello 18
Sender2: Send2 hello 18
Sender: Send hello 19
Sender2: Send2 hello 19
Sender: Send hello 20
Sender2: Send2 hello 20
Sender: Send hello 21
Sender2: Send2 hello 21
Sender: Send hello 22
Sender2: Send2 hello 22
Sender: Send hello 23
Sender2: Send2 hello 23
Sender: Send hello 24
Sender2: Send2 hello 24
Sender: Send hello 25
Sender2: Send2 hello 25
Sender: Send hello 26
Sender2: Send2 hello 26
Sender: Send hello 27
Sender2: Send2 hello 27
Sender: Send hello 28
Sender2: Send2 hello 28
Sender: Send hello 29
Sender2: Send2 hello 29
Receiver2: Send2 hello 0
Receiver: Send hello 0
Receiver: Send hello 1
Receiver2: Send2 hello 1
Receiver: Send hello 2
Receiver2: Send2 hello 2
Receiver: Send hello 3
Receiver2: Send2 hello 3
Receiver: Send hello 4
Receiver2: Send2 hello 4
Receiver: Send hello 5
Receiver2: Send2 hello 5
Receiver: Send hello 6
Receiver2: Send2 hello 6
Receiver: Send hello 7
Receiver2: Send2 hello 7
Receiver: Send hello 8
Receiver2: Send2 hello 8
Receiver2: Send2 hello 9
Receiver: Send hello 9
Receiver: Send hello 10
Receiver2: Send2 hello 10
Receiver: Send hello 11
Receiver2: Send2 hello 11
Receiver: Send hello 12
Receiver2: Send2 hello 12
Receiver: Send hello 13
Receiver2: Send2 hello 13
Receiver: Send hello 14
Receiver2: Send2 hello 14
Receiver: Send hello 15
Receiver2: Send2 hello 15
Receiver2: Send2 hello 16
Receiver: Send hello 16
Receiver2: Send2 hello 17
Receiver: Send hello 17
Receiver2: Send2 hello 18
Receiver: Send hello 18
Receiver2: Send2 hello 19
Receiver: Send hello 19
Receiver2: Send2 hello 20
Receiver: Send hello 20
Receiver2: Send2 hello 21
Receiver: Send hello 21
Receiver2: Send2 hello 22
Receiver: Send hello 22
Receiver2: Send2 hello 23
Receiver: Send hello 23
Receiver2: Send2 hello 24
Receiver: Send hello 24
Receiver2: Send2 hello 25
Receiver: Send hello 25
Receiver2: Send2 hello 26
Receiver2: Send2 hello 27
Receiver: Send hello 26
Receiver2: Send2 hello 28
Receiver: Send hello 27
Receiver2: Send2 hello 29
Receiver: Send hello 28
Receiver: Send hello 29

可以看到,仍然是一条消息只能发送给一个接收者,多个接收者接收同一个队列的消息时会自动均匀分配接收。

 

接下来试试能不能发送一个object类型的消息。

修改RabbitConfig,增加一个object队列

package com.example.demo.rabbit;


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 helloQueue()
    {
        return new Queue("hello");
    }


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

 

Object发送者

ObjectSender.java

package com.example.demo.rabbit.object;


import com.example.demo.Model.User;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;


@Component
public class ObjectSender
{
    private AmqpTemplate rabbitTemplate;


    @Autowired
    public void setRabbitTemplate(AmqpTemplate rabbitTemplate)
    {
        this.rabbitTemplate = rabbitTemplate;
    }


    public void send(User user)
    {
        System.out.println("Sender object: " + user.toString());
        this.rabbitTemplate.convertAndSend("object", user);
    }
}

 

Object接收者

ObjectReceiver.java

package com.example.demo.rabbit.object;


import com.example.demo.Model.User;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;


@Component
@RabbitListener(queues = "object")
public class ObjectReceiver
{
    @RabbitHandler
    public void process(User user)
    {
        System.out.println("Receiver: " + user);
    }
}

 

测试

package com.example.demo.rabbit;


import com.example.demo.Model.User;
import com.example.demo.rabbit.object.ObjectSender;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;


@SpringBootTest
class ObjectTest
{
    @Autowired
    private ObjectSender objectSender;


    @Test
    void sendObject() throws Exception
    {
        User user = new User();
        user.setUserName("用户名");
        user.setPassWord("12345678");


        objectSender.send(user);
        Thread.sleep(1000L);
    }
}

 

测试sendObject()

Sender object: User{id=null,userName=用户名,passWord=12345678}
Receiver: User{id=null,userName=用户名,passWord=12345678}

 

Topic模式

这种模式会在sender与receiver之间增加一层过滤规则,只有符合规则的消息才允许通过交换机。

 

配置

TopicRabbitConfig.java

package com.example.demo.rabbit;


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
{
    // 定义队列
    @Bean
    public Queue queueMessage()
    {
        return new Queue("topic.message");
    }


    @Bean
    public Queue queueMessages()
    {
        return new Queue("topic.messages");
    }


    // 定义交换机
    @Bean
    TopicExchange exchange()
    {
        return new TopicExchange("topicExchange");
    }


    // 将队列与交换机绑定
    @Bean
    Binding bindingExchangeMessage(Queue queueMessage, TopicExchange exchange)
    {
        return BindingBuilder.bind(queueMessage).to(exchange).with("topic.msg");
    }


    @Bean
    Binding bindingExchangeMessages(Queue queueMessages, TopicExchange exchange)
    {
        return BindingBuilder.bind(queueMessages).to(exchange).with("topic.#");
    }
}

 

TopicSender.java

package com.example.demo.rabbit.topic;


import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;


@Component
public class TopicSender
{
    private AmqpTemplate rabbitTemplate;


    @Autowired
    public void setRabbitTemplate(AmqpTemplate rabbitTemplate)
    {
        this.rabbitTemplate = rabbitTemplate;
    }


    public void send1()
    {
        String context = "hi, i am message 1";
        System.out.println("Sender : " + context);
        this.rabbitTemplate.convertAndSend("topicExchange", "topic.msg", context);
    }


    public void send2()
    {
        String context = "hi, i am messages 2";
        System.out.println("Sender : " + context);
        this.rabbitTemplate.convertAndSend("topicExchange", "topic.msgABC", context);
    }
}

 

TopicReceiver.java

package com.example.demo.rabbit.topic;


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 TopicReceiver
{
    @RabbitHandler
    public void process(String message)
    {
        System.out.println("Topic Receiver1  : " + message);
    }
}

 

TopicReceiver2.java

package com.example.demo.rabbit.topic;


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 TopicReceiver2
{
    @RabbitHandler
    public void process(String message)
    {
        System.out.println("Topic Receiver2  : " + message);
    }
}

 

测试

package com.example.demo.rabbit;


import com.example.demo.rabbit.topic.TopicSender;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;


@SpringBootTest
public class TopicTest
{
    @Autowired
    private TopicSender sender;


    @Test
    public void topic1() throws Exception
    {
        sender.send1();
        Thread.sleep(1000l);
    }


    @Test
    public void topic2() throws Exception
    {
        sender.send2();
        Thread.sleep(1000l);
    }
}

 

测试topic1()

这个send1()的routingKey是"topic.msg",与交换机中的routingKey"topic.msg","topic.#”均能匹配通过,所以两个队列都会收到消息。

Sender : hi, i am message 1
Topic Receiver2  : hi, i am message 1
Topic Receiver1  : hi, i am message 1

 

测试topic2()

这个send2()的routingKey是"topic.msgABC",与交换机中的routingKey"topic.msg"不匹配,与"topic.#”匹配通过,所以只有"topic.messages"队列收到消息。

Sender : hi, i am messages 2
Topic Receiver2  : hi, i am messages 2

 

控制界面观察

打开浏览器,访问http://127.0.0.1:15672/#/exchanges

 

点击topicExchange之后,可以清楚地看到此交换机与队列的绑定映射关系。

This exchange ==> To 消息队列且必须与相应的Routing key匹配通过。

 

 

Fanout模式

就是所谓的广播模式,只要是绑定到这个交换机的所有队列都能收到消息。

 

配置

FanoutRabbitConfig.java

package com.example.demo.rabbit;


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);
    }
}

 

FanoutSender.java

package com.example.demo.rabbit.fanout;


import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;


@Component
public class FanoutSender
{
    private AmqpTemplate rabbitTemplate;


    @Autowired
    public void setRabbitTemplate(AmqpTemplate rabbitTemplate)
    {
        this.rabbitTemplate = rabbitTemplate;
    }


    public void send()
    {
        String context = "hi, fanout msg ";
        System.out.println("Sender : " + context);
        this.rabbitTemplate.convertAndSend("fanoutExchange", "", context);
    }
}

 

FanoutReceiverA.java

package com.example.demo.rabbit.fanout;


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);
    }
}

 

FanoutReceiverB.java

package com.example.demo.rabbit.fanout;


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);
    }
}

 

FanoutReceiverC.java

package com.example.demo.rabbit.fanout;


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 com.example.demo.rabbit;


import com.example.demo.rabbit.fanout.FanoutSender;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;


@SpringBootTest
public class FanoutTest
{
    @Autowired
    private FanoutSender sender;


    @Test
    public void fanoutSender() throws Exception
    {
        sender.send();
        Thread.sleep(1000l);
    }
}

 

测试fanoutSender()

Sender : hi, fanout msg 
fanout Receiver A: hi, fanout msg 
fanout Receiver C: hi, fanout msg 
fanout Receiver B: hi, fanout msg

 

再去控制界面观察

打开浏览器,访问http://127.0.0.1:15672/#/exchanges

点击fanoutExchange之后,可以清楚地看到此交换机与队列的绑定映射关系。

可以看到,广播模式的交换机是不存在Routing key的。

 

 

Bootstrap Thumbnail Second
MySQL

MySQL is the world's most popular open source database.

GO

Bootstrap Thumbnail Third
算法基础

本书介绍了什么是计算机算法,如何描述它们,以及如何来评估它们。

GO