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
- 编码:
@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
- 查看队列信息:
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 - 编码:
@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 所有的队列都收到消息。
- 单播,广播的发送/接收方法一样,只要将修改为指定的交换器、队列即可。