【RabbitMQ】-常见的交换机与消息转换器_转换器

Fanout交换机

交换机的作用主要是接收发送者发送的消息,并将消息路由到与其绑定的队列

常见交换机的类型有以下三种

  • Fanout:广播
  • Direct:定向
  • Topic:话题

【RabbitMQ】-常见的交换机与消息转换器_发送消息_02

Fanout Exchange会将接收到的消息路由到每一个跟其绑定的queue,所以也叫广播模式

【RabbitMQ】-常见的交换机与消息转换器_交换机_03

@RabbitListener(queues = "fanout.queue1")
    public void listenFanoutQueue1(String message){
        log.info("消费者1监听到fanout.queue1的消息:【{}】",message);
    }
  • 1.
  • 2.
  • 3.
  • 4.
@RabbitListener(queues = "fanout.queue2")
    public void listenFanoutQueue2(String message){
        log.info("消费者2监听到fanout.queue2的消息:【{}】",message);
    }
  • 1.
  • 2.
  • 3.
  • 4.
@Test
    public void testFanoutQueue(){

        //队列名
        String exchangeName = "hmall.fanout";
        //消息
        String message = "hello,everyone!";
        //发送消息
        rabbitTemplate.convertAndSend(exchangeName,null,message);

    }
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.

【RabbitMQ】-常见的交换机与消息转换器_发送消息_04

Direct交换机

Direct Exchange会将接收到的消息根据规则路由到指定的Queue,因此称为定向路由。

●每一个Queue都与 Exchange设置一个BindingKey

●发布者发送消息时,指定消息的RoutingKey

●Exchange将消息路 由到BindingKey与消息RoutingKey-致的队列

【RabbitMQ】-常见的交换机与消息转换器_发送消息_05

【RabbitMQ】-常见的交换机与消息转换器_发送消息_06

@RabbitListener(queues = "direct.queue1")
    public void listenDirectQueue1(String message){
        log.info("消费者1监听到direct.queue1的消息:【{}】",message);
    }


    @RabbitListener(queues = "direct.queue2")
    public void listenDirectQueue2(String message){
        log.info("消费者2监听到direct.queue2的消息:【{}】",message);
    }
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
@Test
    public void testDirectQueue(){

        //队列名
        String exchangeName = "hmall.direct";
        //消息
        String message = "红色:。。。。。。!";
        //发送消息
        rabbitTemplate.convertAndSend(exchangeName,"red",message);

    }
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.

【RabbitMQ】-常见的交换机与消息转换器_交换机_07

@Test
    public void testDirectQueue(){

        //队列名
        String exchangeName = "hmall.direct";
        //消息
        String message = "蓝色:。。。。。。!";
        //发送消息
        rabbitTemplate.convertAndSend(exchangeName,"blue",message);

    }
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.

【RabbitMQ】-常见的交换机与消息转换器_交换机_08

Topic交换机

TopicExchange也是基于RoutingKey做消息路由,但是routingKey通常是多个单词的组合,并且以。分割。

Queue与Exchange指定BindingKey时可以使用通配符:

  • #:代指0个或多个单词
  • *:代指一个单词

【RabbitMQ】-常见的交换机与消息转换器_交换机_09

【RabbitMQ】-常见的交换机与消息转换器_转换器_10

@RabbitListener(queues = "topic.queue1")
    public void listenTopicQueue1(String message){
        log.info("消费者1监听到topic.queue1的消息:【{}】",message);
    }


    @RabbitListener(queues = "topic.queue2")
    public void listenTopicQueue2(String message){
        log.info("消费者2监听到topic.queue2的消息:【{}】",message);
    }
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
@Test
    public void testTopicQueue(){

        //队列名
        String exchangeName = "hmall.topic";
        //消息
        String message = "蓝色:。。。。。。!";
        //发送消息
        rabbitTemplate.convertAndSend(exchangeName,"china.news",message);

    }
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.

【RabbitMQ】-常见的交换机与消息转换器_交换机_11

@Test
    public void testTopicQueue(){

        //队列名
        String exchangeName = "hmall.topic";
        //消息
        String message = "天气:。。。。。。!";
        //发送消息
        rabbitTemplate.convertAndSend(exchangeName,"china.weather",message);

    }
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.

【RabbitMQ】-常见的交换机与消息转换器_发送消息_12

声明队列交换机

SpringAMQP提供了几个类,用来声明队列、交换机及其绑定关系:

  • Queue:用于声明队列,可以用工厂类QueueBuilder构建
  • Exchange:用于声明交换机,可以用工厂类ExchangeBuilder构建
  • Binding:用于声明队列和交换机的绑定关系,可以用工厂类BindingBuilder构建

【RabbitMQ】-常见的交换机与消息转换器_交换机_13

例如

【RabbitMQ】-常见的交换机与消息转换器_发送消息_14

或者

【RabbitMQ】-常见的交换机与消息转换器_转换器_15

public class FanoutConfiguration {

    @Bean
    public FanoutExchange fanoutExchange(){
        return new FanoutExchange("hmall.fanout");
        //return ExchangeBuilder.fanoutExchange("hmall.fanout").build();
    }

    @Bean
    public Queue fanoutQueue1(){
        //return QueueBuilder.durable("fanout.queue1").build();
        return new Queue("fanout.queue1");
    }

    @Bean
    public Binding fanoutQueue1Binding(Queue fanoutQueue1,FanoutExchange fanoutExchange){
        return BindingBuilder.bind(fanoutQueue1).to(fanoutExchange);
    }

    @Bean
    public Queue fanoutQueue2(){
        //return QueueBuilder.durable("fanout.queue1").build();
        return new Queue("fanout.queue2");
    }

    @Bean
    public Binding fanoutQueue2Binding(Queue fanoutQueue2,FanoutExchange fanoutExchange){
        return BindingBuilder.bind(fanoutQueue2).to(fanoutExchange);
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.

【RabbitMQ】-常见的交换机与消息转换器_发送消息_16

SpringAMQP还提供了基于@RabbitListener注解来声明队列和交换机的方式:

【RabbitMQ】-常见的交换机与消息转换器_转换器_17

@RabbitListener(bindings = @QueueBinding(
            value = @Queue(name = "direct.queue1",durable = "true"),
            exchange = @Exchange(name = "hmall.direct",type = ExchangeTypes.DIRECT),
            key = {"red","blue"}
    ))
    public void listenDirectQueue1(String message){
        log.info("消费者1监听到direct.queue1的消息:【{}】",message);
    }


    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(name = "direct.queue2",durable = "true"),
            exchange = @Exchange(name = "hmall.direct",type = ExchangeTypes.DIRECT),
            key = {"red","yellow"}
    ))
    public void listenDirectQueue2(String message){
        log.info("消费者2监听到direct.queue2的消息:【{}】",message);
    }
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.

消息转换器

Spring的对消息对象的处理是由org.springframework.amqp.support.converter.MessageConverter来处理的。而默认实现是SimpleMessageConverter,基于JDK的ObjectOutputStream完成序列化。

存在下列问题:

  • JDK的序列化有安全 风险
  • JDK序列化的消息太大
  • JDK序列化的消息可读性差

建议采用JSON序列化代替默认的JDK序列化,要做两件事情:

在publisher和consumer中都要引入jackson依赖:

【RabbitMQ】-常见的交换机与消息转换器_交换机_18

在publisher和consumer中都要配置MessageConverter:

【RabbitMQ】-常见的交换机与消息转换器_发送消息_19

【RabbitMQ】-常见的交换机与消息转换器_转换器_20

【RabbitMQ】-常见的交换机与消息转换器_发送消息_21