(1)JMS(Java Message Service)JAVA消息服务:
基于JVM消息代理的规范。ActiveMQ、HornetMQ是JMS实现
(2)AMQP(Advanced Message Queuing Protocol)
高级消息队列协议,也是一个消息代理的规范,兼容JMS
RabbitMQ是AMQP的实现
RabbitMQ是一个由erlang开发的AMQP(Advanved Message Queue Protocol)的开源实现。
Exchange分发消息时根据类型的不同分发策略有区别,目前共四种类型:direct、fanout、topic、headers 。headers 匹配 AMQP 消息的 header 而不是路由键, headers 交换器和 direct 交换器完全一致,但性能差很多,目前几乎用不到了,所以直接看另外三种类型:
(1)direct
消息中的路由键(routing key)如果和 Binding 中的 binding key 一致, 交换器就将消息发到对应的队列中。路由键与队列名完全匹配,如果一个队列绑定到交换机要求路由键为“dog”,则只转发 routing key 标记为“dog”的消息,不会转发“dog.puppy”,也不会转发“dog.guard”等等。它是完全匹配、单播的模式。
(2)fanout
每个发到 fanout 类型交换器的消息都会分到所有绑定的队列上去。fanout 交换器不处理路由键,只是简单的将队列绑定到交换器上,每个发送到交换器的消息都会被转发到与该交换器绑定的所有队列上。很像子网广播,每台子网内的主机都获得了一份复制的消息。fanout 类型转发消息是最快的。
(3)topic
topic 交换器通过模式匹配分配消息的路由键属性,将路由键和某个模式进行匹配,此时队列需要绑定到一个模式上。它将路由键和绑定键的字符串切分成单词,这些单词之间用点隔开。它同样也会识别两个通配符:符号“#”和符号“*”。#匹配0个或多个单词,*匹配一个单词。
docker pull rabbitmq:3.8.9-management
-- 带management的是有管理界面的docker run -d -p 5672:5672 -p 15672:15672 --name myrabbitmq id
-- 5672是通信端口,15672是管理界面端口(2)添加Queues
(3)Exchange绑定Queues
Topic Exchange
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
RabbitAutoConfiguration
自动配置了连接工厂ConnectionFactory
RabbitProperties封装了RabbitMQ的配置
RabbitTemplate:给RabbitMQ发送和接收消息
AmqpAdmin:RabbitMQ系统管理功能组件
创建和删除Queue,Exchange,Binding
@Autowired
AmqpAdmin amqpAdmin;
@Test
void testAmqpAdmin() {
amqpAdmin.declareExchange(new DirectExchange("amqpadmin.exchange"));
amqpAdmin.declareQueue(new Queue("amqpadmin.queue"));
amqpAdmin.declareBinding(new Binding("amqpadmin.queue", Binding.DestinationType.QUEUE,"amqpadmin.exchange","amqp.haha",null));
}
@Service
public class BookServiceImpl implements BookService {
@RabbitListener(queues = "wu.news")
public void sellBook() { //消息内容可以使用参数对象自动封装或者用Message参数获取消息对象
System.out.println("sell");
}
}
//Message需要自己构造一个;定义消息体内容和消息头
rabbitTemplate.send(exchange,routeKey,message);
//object默认被当成消息体,只需要传入要发送的对象,自动序列化发送给RabbitMQ
rabbitTemplate.convertAndSend(exchange,routeKey,object);
(1)点对点
其他模式也一样,广播情况下不需要路由键参数
//发送消息
Map<String,Object> map = new HashMap<String,Object>();
map.put("msg","这是第一个消息");
map.put("data", Arrays.asList("wu",123,true));
rabbitTemplate.convertAndSend("exchange.direct","wu.news",map);
//接收消息
Object o = rabbitTemplate.receiveAndConvert("atguigu.news");
自定义序列化机制
@Configuration
public class MyAMQPConfig {
@Bean
public MessageConverter messageConverter() {
return new Jackson2JsonMessageConverter();
}
}