SpringBoot整合中间件RabbitMQ(四)

1.测试(单播)

com.invi.Springboot02AmqpApplicationTests中注入:RabbitTemplate

    @Autowired
    RabbitTemplate rabbitTemplate;
  • 调用 rabbitTemplate#rabbitTemplate.send(exchange, routingKey, message);方法。

    message需要自己构造,可以定制消息体内容和消息头

    构建Message:

    源码Path:org.springframework.amqp.core.Message#Message

    public Message(byte[] body, MessageProperties messageProperties) { //NOSONAR
            this.body = body; //NOSONAR
            this.messageProperties = messageProperties;
        }
    
  • OR 调用 rabbitTemplate#convertAndSend(exchange, routingKey, object);方法。

    object默认当做消息体,只需要传入需要发送的对象,自动序列化保存发送给RabbitMQ。

2.发送(单播)

发送点对点消息

  • 使用#convertAndSend(exchange, routingKey, object);

  • 点对点的交换器是:exchange.direct

  • exchange.direct的路由键信息:

    To Routing key
    unionpaysmart unionpaysmart
    unionpaysmart.news unionpaysmart.news
    invi invi
    invi.emps invi.emps
    invi.idea invi.idea
    invi.news invi.news
  1. 编码:
    @Autowired
    RabbitTemplate rabbitTemplate;

  //单播(点对点)
    @Test
    public void test1() {
        //message需要自己构造,可以定制消息体内容和消息头
        //rabbitTemplate.send(exchange, routingKey, message);
        Object object = null;
        Map map = new HashMap<>();
        map.put("1", "第一个消息");
        map.put("1", Arrays.asList("123", "qwe", true));
        
        rabbitTemplate.convertAndSend("exchange.direct", "invi.news", map);
    }

将消息发送给队列:invi.news

  1. 查看队列信息:
Overview Messages Message rates +/-
Name Features State Ready Unacked Total incoming deliver / get ack
unionpaysmart D idle 0 0 0 0.00/s 0.00/s 0.00/s
unionpaysmart.news D idle 0 0 0 0.00/s 0.00/s 0.00/s
invi D idle 0 0 0 0.00/s 0.00/s 0.00/s
invi.emps D idle 0 0 0 0.00/s 0.00/s 0.00/s
invi.idea D idle 0 0 0 0.00/s 0.00/s 0.00/s
invi.news D idle 1 0 1 0.00/s 0.00/s 0.00/s

invi.news 有一条消息。

详情:

The server reported 0 messages remaining.

Exchange exchange.direct
Routing Key invi.news
Redelivered
Properties priority:0delivery_mode:2headers:content_type:application/x-java-serialized-object
Payload254 bytesEncoding: base64 rO0ABXNyABFqYXZhLnV.....

对象默认使用Java序列化后发送出去。

原因:

messageConverter消息转换器默认用的SimpleMessageConverter,而SimpleMessageConverter序列化时用的就是JDK的序列化工具,将对象按照字节数据序列化。

org.springframework.amqp.rabbit.core.RabbitTemplate#messageConverter

org.springframework.amqp.support.converter.SimpleMessageConverter#fromMessage

如何更换 序列化工具:

至此 点对点消息发送成功!

代码地址:com.invi.Springboot02AmqpApplicationTests#testExchangeDirect

3.接收(单播)

接收点对点消息

  • 使用#receiveAndConvert(exchange, routingKey, object); 将接收的消息自动转为对象。
  • invi.news 队列中已经有一个消息。

编码:

    //接受-单播(点对点)
    @Test
    public void testExchangeReceive() {

        Object o = rabbitTemplate.receiveAndConvert("invi.news");
        System.out.println("o type:" + o.getClass());
        System.out.println("o data:" + o);
    }

运行:

2019-03-04 15:02:58.061  INFO 40283 --- [           main] o.s.a.r.c.CachingConnectionFactory       : Attempting to connect to: [localhost:5672]

2019-03-04 15:02:58.108  INFO 40283 --- [           main] o.s.a.r.c.CachingConnectionFactory       : Created new connection: rabbitConnectionFactory#4525d1d3:0/SimpleConnection@56ccd751 [delegate=amqp://[email protected]:5672/, localPort= 51010]

o type:class java.util.HashMap
o data:{1=[123, qwe, true]}

至此 点对点消息接受成功!

4.更换序列化

使用:org.springframework.amqp.support.converter.Jackson2JsonMessageConverter

只需要添加配置:

package com.invi.config;

import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MyAMQPConfig {

    @Bean
    public MessageConverter messageConverter() {
        return new Jackson2JsonMessageConverter();
    }

}

添加完成即可,使用。

原因,我们已经自定义了MessageConverter,在注入RabbitTemplate组件时将替换原有MessageConverter。

源码:org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration.RabbitTemplateConfiguration#rabbitTemplate

      @Bean
      @ConditionalOnSingleCandidate(ConnectionFactory.class)
      @ConditionalOnMissingBean(RabbitTemplate.class)
      public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
          ......
          if (messageConverter != null) {
              rabbitTemplate.setMessageConverter(messageConverter);
          }
          
          ......
      }

再次发送消息,查看队列中的消息:

The server reported 0 messages remaining.

Exchange exchange.direct
Routing Key invi.news
Redelivered
Properties priority:0delivery_mode:2headers:ContentTypeId:java.lang.Object__KeyTypeId__:java.lang.Object__TypeId__:java.util.HashMapcontent_encoding:UTF-8content_type:application/json
Payload46 bytesEncoding: string {"1":"第一个消息","2":["123","qwe",true]}

至此,已经消息已经完成JSON序列换。

在此接收消息,也一定没有问题。

5.自定义对象

创建一个对象:

package com.invi.bean;

public class Book {
    private String name;
    private String author;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Book() {
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public Book(String name, String author) {
        this.name = name;
        this.author = author;
    }
}

  • 发送对象
    @Autowired
    RabbitTemplate rabbitTemplate;


    //发送-单播(点对点)
    @Test
    public void testExchangeDirect() {
        rabbitTemplate.convertAndSend("exchange.direct", "invi.news", new Book("《挪威森林》", "村上春树"));
    }

查看对象:

The server reported 0 messages remaining.

Exchange exchange.direct
Routing Key invi.news
Redelivered
Properties priority:0delivery_mode:2headers:TypeId:com.invi.bean.Bookcontent_encoding:UTF-8content_type:application/json
Payload53 bytesEncoding: string {"name":"《挪威森林》","author":"村上春树"}

由此可见,只需要把自定义对象当做一般参树,发送即可。

  • 接收:
o type:class com.invi.bean.Book
o data:com.invi.bean.Book@5c92166b

返回对象为:Book 。

接收完成。

6.发送(广播)

发送点对点消息

  • 使用#convertAndSend(exchange, routingKey, object);

  • 广播的交换器是:exchanges.fanout

  • exchanges.fanout的路由键信息:

    To Routing key
    unionpaysmart unionpaysmart
    unionpaysmart.news unionpaysmart.news
    invi invi
    invi.emps invi.emps
    invi.idea invi.idea
    invi.news invi.news
    1. 编码:
        @Autowired
        RabbitTemplate rabbitTemplate;
    
      //发送-广播
        //广播不需要指定:routingKey也可以
        @Test
        public void testExchangeFanout() {
            Object object = null;
            Map map = new HashMap<>();
            map.put("1", "第一个广播消息");
            map.put("2", Arrays.asList("广播", "广播消息", false));
            //此处手误多了个s
            //rabbitTemplate.convertAndSend("exchanges.fanout", "invi.news", map);
            //等同于
            rabbitTemplate.convertAndSend("exchanges.fanout", "", map);
    
        }
    

    将消息发送给队列:invi.news,其实所有的都会收到。

    Overview Messages Message rates +/-
    Name Features State Ready Unacked Total incoming deliver / get ack
    unionpaysmart D idle 1 0 1 0.00/s 0.00/s 0.00/s
    unionpaysmart.news D idle 1 0 1 0.00/s 0.00/s 0.00/s
    invi D idle 1 0 1 0.00/s 0.00/s 0.00/s
    invi.emps D idle 1 0 1 0.00/s 0.00/s 0.00/s
    invi.idea D idle 1 0 1 0.00/s 0.00/s 0.00/s
    invi.news D idle 1 0 1 0.20/s 0.00/s 0.00/s

    所有的队列都收到消息。

    • 单播,广播的发送/接收方法一样,只要将修改为指定的交换器、队列即可。

你可能感兴趣的:(SpringBoot整合中间件RabbitMQ(四))