Fanout交换机
交换机的作用主要是接收发送者发送的消息,并将消息路由到与其绑定的队列
常见交换机的类型有以下三种
- Fanout:广播
- Direct:定向
- Topic:话题
Fanout Exchange会将接收到的消息路由到每一个跟其绑定的queue,所以也叫广播模式
@RabbitListener(queues = "fanout.queue1")
public void listenFanoutQueue1(String message){
log.info("消费者1监听到fanout.queue1的消息:【{}】",message);
}
@RabbitListener(queues = "fanout.queue2")
public void listenFanoutQueue2(String message){
log.info("消费者2监听到fanout.queue2的消息:【{}】",message);
}
@Test
public void testFanoutQueue(){
//队列名
String exchangeName = "hmall.fanout";
//消息
String message = "hello,everyone!";
//发送消息
rabbitTemplate.convertAndSend(exchangeName,null,message);
}
Direct交换机
Direct Exchange会将接收到的消息根据规则路由到指定的Queue,因此称为定向路由。
●每一个Queue都与 Exchange设置一个BindingKey
●发布者发送消息时,指定消息的RoutingKey
●Exchange将消息路 由到BindingKey与消息RoutingKey-致的队列
@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);
}
@Test
public void testDirectQueue(){
//队列名
String exchangeName = "hmall.direct";
//消息
String message = "红色:。。。。。。!";
//发送消息
rabbitTemplate.convertAndSend(exchangeName,"red",message);
}
@Test
public void testDirectQueue(){
//队列名
String exchangeName = "hmall.direct";
//消息
String message = "蓝色:。。。。。。!";
//发送消息
rabbitTemplate.convertAndSend(exchangeName,"blue",message);
}
Topic交换机
TopicExchange也是基于RoutingKey做消息路由,但是routingKey通常是多个单词的组合,并且以。分割。
Queue与Exchange指定BindingKey时可以使用通配符:
- #:代指0个或多个单词
- *:代指一个单词
@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);
}
@Test
public void testTopicQueue(){
//队列名
String exchangeName = "hmall.topic";
//消息
String message = "蓝色:。。。。。。!";
//发送消息
rabbitTemplate.convertAndSend(exchangeName,"china.news",message);
}
@Test
public void testTopicQueue(){
//队列名
String exchangeName = "hmall.topic";
//消息
String message = "天气:。。。。。。!";
//发送消息
rabbitTemplate.convertAndSend(exchangeName,"china.weather",message);
}
声明队列交换机
SpringAMQP提供了几个类,用来声明队列、交换机及其绑定关系:
- Queue:用于声明队列,可以用工厂类QueueBuilder构建
- Exchange:用于声明交换机,可以用工厂类ExchangeBuilder构建
- Binding:用于声明队列和交换机的绑定关系,可以用工厂类BindingBuilder构建
例如
或者
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);
}
}
SpringAMQP还提供了基于@RabbitListener注解来声明队列和交换机的方式:
@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);
}
消息转换器
Spring的对消息对象的处理是由org.springframework.amqp.support.converter.MessageConverter来处理的。而默认实现是SimpleMessageConverter,基于JDK的ObjectOutputStream完成序列化。
存在下列问题:
- JDK的序列化有安全 风险
- JDK序列化的消息太大
- JDK序列化的消息可读性差
建议采用JSON序列化代替默认的JDK序列化,要做两件事情:
在publisher和consumer中都要引入jackson依赖:
在publisher和consumer中都要配置MessageConverter: