文章目录
- 消息队列补充
- RabbitMQ 补充
- 整合 RabbitMQ
消息队列补充
大多数应用中,可以通过消息服务中间件来提升系统异步通信、扩展解耦能力。
而消息服务中两个重要的概念:
- 消息代理
- 目的地
当消息发送者发送消息以后,将由消息代理接管,消息代理保证消息传递到指定目的地。
消息队列主要有两种形式的目的地:
- 队列(queue):点对点消息通信。
一个消息只有唯一的发送者和接收者。 - 主题(topic):发布(publish)/订阅(subscribe)消息通信。
一个消息可以有多个接收者。
两种消息代理规范
- JMS: Java Message Service,即 Java 消息服务,是基于 JVM 消息代理的规范。实现:ActiveMQ 。
- AMQP: Advanced Message Queuing Protocol,即高级消息队列协议,也是一个消息代理的规范,兼容 JMS。实现:RabbitMQ。
Spring中对消息队列的支持
- spring-jms提供了对JMS的支持
- spring-rabbit提供了对AMQP的支持
- 需要ConnectionFactory的实现来连接消息代理
- 提供JmsTemplate、RabbitTemplate来发送消息
- @JmsListener(JMS)、@RabbitListener(AMQP)注解在方法上监听消息代理发布的消息
- @EnableJms、@EnableRabbit开启支持
相关的两个自动配置
- JmsAutoConfiguration
- RabbitAutoConfiguration
RabbitMQ 补充
RabbitMQ的各个组件:
AMQP相比JMS增加了 Exchange 和 Binding,生产者把消息发给 Broker,Broker 会将消息给到合适的 Exchange,而 Binding 决定交换器的消息应该发送到的队列,消息最终到达队列并被消费者接收。
整合 RabbitMQ
本地 RabbitMQ 的安装可以参考上面的补充,这里主要讲 SpringBoot 中对 RabbitMQ 的配置和使用。
RabbitMQ 后台中添加我们的交换器以及消息队列,并进行关联绑定:
- 交换器
- 消息队列
- 绑定并指定路由键
配置好 RabbitMQ 后,我们就可以在 SpringBoot 中操作我们定义的消息队列,在补充中我们操作 RabbitMQ 之前需要通过连接工厂获取连接,这些都在 RabbitAutoConfiguration 帮我们配置好了。
所以我们可以勾选需要的模块快速创建 SpringBoot 应用,并在配置文件中进行必要配置:
spring:
rabbitmq:
host: localhost
username: guest
password: guest
port: 5672
在 RabbitAutoConfiguration 中还给我们提供了 RabbitTemplate(收发消息) 以及 AmqpAdmin(系统管理组件)。
通过 RabbitTemplate 进行操作:
@Autowired
private RabbitTemplate rabbitTemplate;
@Test
void contextLoads() {
//Message消息对象,要发送的消息
Map<String,Object> map = new HashMap<String,Object>();
map.put("msg","测试消息");
map.put("data", Arrays.asList("1",2,3));
//发送指明交换器,路由键,消息体
rabbitTemplate.convertAndSend("myexchange.direct","user",map);
}
@Test
void receiveMsg(){
Object ob = rabbitTemplate.receiveAndConvert("userqueue");
System.out.println(ob.getClass());
System.out.println(ob);
}
同样的我们可以通过编写配置文件修改一些配置,比如 RabbitTemplate 默认的序列化机制:
@Configuration
public class AMQPConfig {
@Bean
public MessageConverter myMessageConverter(){
return new Jackson2JsonMessageConverter();
}
}
RabbitListener
一般我们不会通过上面的方法来直接获取队列中的消息,而是会使用监听器来监听队列中是否有消息并进行必要的处理。
注:需要开启基于注解的 RabbitMQ 模式,main 上加 @EnableRabbit
@Service
public class BookService {
@RabbitListener(queues = "userqueue")
public void receive(User user){
System.out.println(user);
}
}
AmqpAdmin
前面我是通过 RabbitMQ 后台页面进行交换器以及队列的创建,其实我们还可以通过 AmqpAdmin 进行定义。
@Autowired
private AmqpAdmin amqpAdmin;
@Test
void createExchange(){
amqpAdmin.declareExchange(new FanoutExchange("myexchange.fanout"));//定义交换器
amqpAdmin.declareQueue(new Queue("xfdgqueue",true));//定义消息队列
amqpAdmin.declareBinding(new Binding("xfdgqueue",Binding.DestinationType.QUEUE,"myexchange.fanout","",null));//绑定
}