RabbitMQ

71 阅读2分钟

Springboot整合RabbitMQ--基本使用

前提:添加Spring AMQP依赖与配置文件

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
            <version>2.7.6</version>
        </dependency>
        
        
spring:
  rabbitmq:
    host: 124.220.69.168 # 主机名
    port: 5672 # 端口
    virtual-host: / # 虚拟主机
    username: guest # 用户名
    password: guest # 密码

1.Fanout模式

在广播模式下,消息发送流程是这样的:

  • 1) 可以有多个队列
  • 2) 每个队列都要绑定到Exchange(交换机)
  • 3) 生产者发送的消息,只能发送到交换机,交换机来决定要发给哪个队列,生产者无法决定
  • 4) 交换机把消息发送给绑定过的所有队列
  • 5) 订阅队列的消费者都能拿到消息

生产者代码

    @Test
    public void testFanout(){
        //消息
        String msg = "hello fanout consume";
        //交换机名称
        String exchange = "lin.fanout";
        //发送消息--第二个参数为空字符串(必须指定,否则无法发送到队列中)
        rabbitTemplate.convertAndSend(exchange,"",msg);
        System.out.println("fanout生产者执行完毕");
    }

消费者代码

这里我创建了两个消费者,但没有指定routingKey

@Component
public class FanoutListener {
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(name="lin.fanout.queue1"),
            exchange = @Exchange(name = "lin.fanout",type = ExchangeTypes.FANOUT)
    ))
    public void fanoutConsume1(String msg){
        System.out.println("消费者1执行:"+msg);
    }

    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(name="lin.fanout.queue2"),
            exchange = @Exchange(name = "lin.fanout",type = ExchangeTypes.FANOUT)
    ))
    public void fanoutConsume2(String msg){
        System.out.println("消费者2执行:"+ msg);
    }
}

2.Direct模式

在这里插入图片描述 在Direct模式中,需要指定具体routingKey来将消息投放到具体的消费队列中,而消费者的可以指定多个routingKey(若两个消费者都监听到了相同的routingKey消息,则两个消费者都执行)。

生产者代码

    @Test
    public void testDirect(){
        //消息
        String msg = "hello direct consume";
        //交换机
        String exchange = "lin.direct";
        //发送消息
        rabbitTemplate.convertAndSend(exchange,"blue",msg);
        System.out.println("direct生产者执行完毕");
    }

消费者代码

这里依旧创建了两个消费者,但他们的routingKey有所不同

@Component
public class DirectListener {
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(name = "lin.direct.queue1"),
            exchange = @Exchange(name = "lin.direct",type = ExchangeTypes.DIRECT),
            key = {"red","green"}
    ))
    public void directQueue1(String msg){
        System.out.println("消费者1执行:"+msg);
    }

    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(name = "lin.direct.queue2"),
            exchange = @Exchange(name = "lin.direct",type = ExchangeTypes.DIRECT),
            key = {"red","blue"}
    ))
    public void directQueue2(String msg){
        System.out.println("消费者2执行:"+msg);
    }
}

3.Topic模式

在这里插入图片描述

生产者代码

    @Test
    public void testTopic(){
        //消息
        String msg = "hello topic consume";
        //交换机
        String exchange = "lin.topic";
        //发送消息
        rabbitTemplate.convertAndSend(exchange,"china.news",msg);
        System.out.println("topic生产者执行完毕");
    }

消费者代码

这里我依旧创建两个消费者,使用通配符的方式进行指定routingKey,若这两个消费者都监听到符合的消息时,都会执行。

@Component
public class TopicListener {

    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(name = "lin.topic.queue1"),
            exchange = @Exchange(name = "lin.topic",type = ExchangeTypes.TOPIC),
            key = {"china.#"}
    ))
    public void topicQueue1(String msg){
        System.out.println("消费者1执行:"+msg);
    }

    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(name = "lin.topic.queue2"),
            exchange = @Exchange(name = "lin.topic",type = ExchangeTypes.TOPIC),
            key = {"#.news"}
    ))
    public void topicQueue2(String msg){
        System.out.println("消费者2执行:"+msg);
    }
}

4.配置消息转换器--用来发送对象形式数据

引入依赖(生产者和消费者都需要引入)

<dependency>
    <groupId>com.fasterxml.jackson.dataformat</groupId>
    <artifactId>jackson-dataformat-xml</artifactId>
    <version>2.9.10</version>
</dependency>

在启动类中添加一个Bean

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