springboot整合rabbitMq

下载rabbitmq

下载地址:https://www.rabbitmq.com/install-windows.html

如果需要看到图形管理界面,还需要进行如下操作:

打开doc窗口,切换到rabbitmq的bin目录,执行:rabbitmq-plugins enable rabbitmq_management即可。

springboot整合rabbitmq

1.新建一个maven工程:

2.引入rabbitmq的依赖:

3.配置项目的端口以及整合rabbitmq的配置,找到resources目录下的application.properties文件,这里我将它改成了yml文件:

到这里,mq的整合就完成了,是不是很简单?因为springboot本身就对mq做了集成,所以配置才会很简单,下面来介绍一下rabbitmq的集中消息模式。

常量类:
 

package com.ymy.utils;

/**
 * 消息队列的常量
 */
public class RabbitConstant {

    /**
     * 普通的消息队列,参数为字符串
     */
    public static final String TEST_QUEUE = "test_queue";

    /**
     * 普通的消息队列,参数为对象
     */
    public static final String TEST_QUEUE_OBJECT = "test_queue_object";


    /**
     * 交换机----direct
     */
    public static final String EXCHANGE_DIRECT = "exchange_direct";


    /**
     * 绑定到叫环境(direct)的普通队列
     */
    public static final String TEST_QUEUE_BIND_DIRECT1 = "test_queue_bind_direct1";


    /**
     * 绑定到叫环境(direct)的普通队列
     */
    public static final String TEST_QUEUE_BIND_DIRECT2 = "test_queue_bind_direct2";


    /**
     * 交换机(direct)的路由key
     */
    public static final String DIRECT_EXCHANGE_ROUTING_KEY = "direct_exchange_routing_key";

    /**
     * 普通队列1(用户绑定到交换机fanout上)
     */
    public static final String TEST_QUEUE_TO_FANOUT1 = "test_queue_to_fanout1";

    /**
     * 普通队列2(用户绑定到交换机fanout上)
     */
    public static final String TEST_QUEUE_TO_FANOUT2 = "test_queue_to_fanout2";

    /**
     * 交换机(fanout)
     */
    public static final String FANOUT_EXCHANGE = "fanout_exchange";



    /**
     * 普通队列1(用户绑定到交换机topic上)
     */
    public static final String TEST_QUEUE_TO_TOPIC1 = "topic.message1";


    /**
     * 普通队列2(用户绑定到交换机topic上)
     */
    public static final String TEST_QUEUE_TO_TOPIC2 = "topic.message2";

    /**
     * 交换机(topic)
     */
    public static final String TOPIC_EXCHANGE = "topic_exchange";


    /**
     * 路由key(topic)
     */
    public static final String TOPIC_EXCHANGE_ROUTING_KEY = "topic.#";

}

 

 

一、普通消息:

1.创建普通队列:

/**
     * 创建一个发送字符串的普通消息
     * 参数1 name :队列名
     * 参数2 durable :是否持久化
     * 参数3 exclusive :仅创建者可以使用的私有队列,断开后自动删除
     * 参数4 autoDelete : 当所有消费客户端连接断开后,是否自动删除队列
     * @return
     */
    @Bean
    public Queue testQueue(){

        return new Queue(RabbitConstant.TEST_QUEUE,true,false,false);
    }
RabbitConstant.TEST_QUEUE:队列名称,字符串类型,自己命名

2.创建一个消息的生产者:

新建controller:

引入rabbitmq的操作工具类:

private RabbitTemplate rabbitTemplate;

    private TXMessage txMessage;

    @Autowired
    public  TestController(RabbitTemplate rabbitTemplate, TXMessage txMessage){
        this.rabbitTemplate = rabbitTemplate;
        this.txMessage = txMessage;
    }
RabbitTemplate:操作rabbitmq的工具类。
TXMessage:确认消息所需要的,这里可以忽略。

发送消息:

/**
     * 发送普通消息队列,参数为字符串
     */
    @GetMapping(value = "sendTestQueue")
    public String sendTestQueue() {

        rabbitTemplate.convertAndSend(RabbitConstant.TEST_QUEUE,"hello-bug");
        log.info("发送参数为字符串的普通消息完成!");

        return "Success!!!!";
    }

3.创建消费者:

/**
     * 接收普通消息队列,参数为字符串
     */
    @RabbitListener(queues = RabbitConstant.TEST_QUEUE)
    public void testQueue(String content){

        log.info("已经接收到消息,参数:{}",content);
    }
@RabbitListener:此注解就是用于监听mq上是否有生产者生产消息。
queues:制定队列的名称。

到此,普通的消息就创建完成了

二、广播订阅消息
广播订阅消息分为三种:
1.direct:通过路由key将消息分发到绑定此交换机上的队列。
2.fanout:发送绑定到交换机上的所有队列。
3.topic:匹配模式,将消息分发到匹配规则的队列上。

第一种:direct:

新建两个普通的队列:
 

 /**
     * 需要绑定到交换机(direct)上的普通队列
     * @return
     */
    @Bean
    public Queue testQueuebindDircet1(){

        return new Queue(RabbitConstant.TEST_QUEUE_BIND_DIRECT1,true,false,false);
    }
    /**
     * 需要绑定到交换机(direct)上的普通队列
     * @return
     */
    @Bean
    public Queue testQueuebindDircet2(){

        return new Queue(RabbitConstant.TEST_QUEUE_BIND_DIRECT2,true,false,false);
    }

新建交换机:
 

/**
     * 订阅模式----dircet
     *参数1 name :交互器名
     * 参数2 durable :是否持久化
     * 参数3 autoDelete :当所有消费客户端连接断开后,是否自动删除队列
     * @return
     */
    @Bean
    public DirectExchange directExchange() {
        return new DirectExchange(RabbitConstant.EXCHANGE_DIRECT,true,false);
    }

将队列通过路由绑定到交换机上:
 

/**
     * 将普通队列绑定到交换机(direct)上
     * @return
     */
    @Bean
    public Binding binding1() {
        //链式写法: 用指定的路由键将队列绑定到交换机
        return BindingBuilder.bind(testQueuebindDircet1()).to(directExchange()).with(RabbitConstant.DIRECT_EXCHANGE_ROUTING_KEY);
    }

    /**
     * 将普通队列绑定到交换机(direct)上
     * @return
     */
    @Bean
    public Binding binding2() {
        //链式写法: 用指定的路由键将队列绑定到交换机
        return BindingBuilder.bind(testQueuebindDircet2()).to(directExchange()).with(RabbitConstant.DIRECT_EXCHANGE_ROUTING_KEY);
    }

现在来创建生产者和消费者:
生产者:
 

/**
     * 发送订阅消息(direct)
     */
    @GetMapping(value = "sendDirect")
    public String sendDirect() {
        String content = "这是一条订阅消息(direct)";
        rabbitTemplate.convertAndSend(RabbitConstant.EXCHANGE_DIRECT,RabbitConstant.DIRECT_EXCHANGE_ROUTING_KEY,content);
        log.info("发送路由消息(direct)完成!");

        return "Success!!!!";
    }

消费者:
 

/**
     *接收订阅消息的队列1
     */
    @RabbitListener(queues = RabbitConstant.TEST_QUEUE_BIND_DIRECT1)
    public void test1(String content){

        log.info("这里是订阅队列1,已经接收到消息,参数:{}",content);
    }

    /**
     *接收订阅消息的队列2
     */
    @RabbitListener(queues = RabbitConstant.TEST_QUEUE_BIND_DIRECT2)
    public void test2(String content){

        log.info("这里是订阅队列2,已经接收到消息,参数:{}",content);
    }

第二种:Fanout
新建两个普通队列:
 

/**
     * 创建普通的消息队列1(用户绑定到交换机Fanout上)
     * @return
     */
    @Bean
    public Queue testQueuetoFanout1(){

        return new Queue(RabbitConstant.TEST_QUEUE_TO_FANOUT1,true,false,false);
    }

    /**
     * 创建普通的消息队列2(用户绑定到交换机Fanout上)
     * @return
     */
    @Bean
    public Queue testQueuetoFanout2(){

        return new Queue(RabbitConstant.TEST_QUEUE_TO_FANOUT2,true,false,false);
    }

新建交换机:
 

/**
     * 交换机(fanout)
     * @return
     */
    @Bean
    public FanoutExchange fanoutExchange() {
        return new FanoutExchange(RabbitConstant.FANOUT_EXCHANGE,true,false);
    }

将两个队列绑定到此交换机上,注意,不需要路由key:
 

/**
     * 将普通队列1绑定到叫环境(direct)上
     * @return
     */
    @Bean
    public Binding bindToFanout1() {
        //链式写法: 用指定的路由键将队列绑定到交换机
        return BindingBuilder.bind(testQueuetoFanout1()).to(fanoutExchange());
    }

    /**
     * 将普通队列2绑定到叫环境(direct)上
     * @return
     */
    @Bean
    public Binding bindToFanout2() {
        //链式写法: 用指定的路由键将队列绑定到交换机
        return BindingBuilder.bind(testQueuetoFanout2()).to(fanoutExchange());
    }

生产者:
 

 /**
     * 发送订阅消息(fanout)
     */
    @GetMapping(value = "sendFanout")
    public String sendFanout() {
        String content = "这是一条订阅消息(fanout)";
        rabbitTemplate.convertAndSend(RabbitConstant.FANOUT_EXCHANGE,"",content);
        log.info("发送路由消息(fanout)完成!");
        return "Success!!!!";
    }

这里需要注意一点:

这里的路由key必须要制定为空字符串,如果不指定,消费者将收不到消息

消费者:
 

/**
     *接收订阅消息的队列1
     */
    @RabbitListener(queues = RabbitConstant.TEST_QUEUE_TO_FANOUT1)
    public void test1(String content){

        log.info("这里是订阅队列1,已经接收到消息,参数:{}",content);
    }

    /**
     *接收订阅消息的队列2
     */
    @RabbitListener(queues = RabbitConstant.TEST_QUEUE_TO_FANOUT2)
    public void test2(String content){

        log.info("这里是订阅队列2,已经接收到消息,参数:{}",content);
    }

好了,下面就是第三种:topic,根据规则匹配:
新建一个普通队列:
 

/**
     * 创建普通的消息队列1(用户绑定到交换机topic上)
     * @return
     */
    @Bean
    public Queue testQueuetoTopic1(){

        return new Queue(RabbitConstant.TEST_QUEUE_TO_TOPIC1,true,false,false);
    }

 

创建交换机:
 

 /**
     * 交换机(topic)
     * @return
     */
    @Bean
    public TopicExchange topicExchange() {
        return new TopicExchange(RabbitConstant.TOPIC_EXCHANGE,true,false);
    }

最后将队列绑定到交换机上:
 

/**
     * 将普通队列1绑定到叫环境(Topic)上
     * @return
     */
    @Bean
    public Binding bindingTopic1(@Qualifier("testQueuetoTopic1")Queue queueMessages,TopicExchange exchange){
        return BindingBuilder.bind(queueMessages).to(exchange).with(RabbitConstant.TOPIC_EXCHANGE_ROUTING_KEY);
    }

请看路由key的格式居然是:".#",这里的意思就是只要发送topic开头的队列,都会、被此路由分发,需要注意一点,这里的“#”可以用“*”代替。

三种广播模式的消息介绍完成之后我在介绍一种消息模式:消息的确认机制。

什么是消息确认机制?

顾名思义,就是消息的发送成功与否、消息是否成功消费都需要一个确认。假如说有这么一个需求,有两个微服务:A(订单服服务)B(库存服务),当用户产生一条订单的时候,库存也应该相应的减一,如果你正好用的是mq来对两个服务解耦,那么有可能会出现这么一个问题,当A服务的订单已经生成,然后去发送消息告诉B服务,那如果再发送消息的时候,mq突然挂了,那就代表着消息不会被挂在到mq上,B服务的减库存也不会发生,这种情况是有可能的,所以mq做出了一种消息的确认机制,就是再发送消息的会有一个回调,告诉消息生产方消息投递是成功了还是失败了,消费方也有着同样的一个机制,要告诉mq这个消息是否被消费了,这就是mq的消息确认机制,如何实现呢?这部分我再源码里面有些,大家可以下载源码直接查看。
源码地址:https://github.com/361426201/springboot/tree/master/springboot-rabitmq

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章