springboot集成rabbitmq

余生颓废 提交于 2020-01-30 19:03:18

RabbitMQ简介

RabbitMQ使用Erlang语言开发的开源消息队列系统,基于AMQP协议来实现(AMQP的主要特征是面向消息、队列、路由、可靠性、安全)。支持多种客户端,如:Python、Ruby、.NET、Java、JMS、C、PHP、ActionScript、XMPP、STOMP等,支持AJAX。用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现很出色。

相关概念

消息队列通常有三个概念:发送消息(生产者)、队列、接收消息(消费者)。RabbitMQ在这个基本概念之上,多做了一层抽象,在发送消息和队列之间,加入了交换机。这样发送消息和队列就没有直接关系,而是通过交换机来做转发,交换机会根据分发策略把消息转给队列。

RabbitMQ比较重要的几个概念:

虚拟主机:RabbitMQ支持权限控制,但是最小控制粒度为虚拟主机。一个虚拟主机可以包含多个交换机、队列、绑定。

交换机:RabbitMQ分发器,根据不同的策略将消息分发到相关的队列。

队列:缓存消息的容器。

绑定:设置交换机与队列的关系。

交换机(Exchange)

交换机的主要作用是接收相应的消息并且绑定到指定的队列.交换机有四种类型,分别为Direct,topic,headers,Fanout.

  Direct是RabbitMQ默认的交换机模式,也是最简单的模式.即创建消息队列的时候,指定一个BindingKey.当发送者发送消息的时候,指定对应的Key.当Key和消息队列的BindingKey一致的时候,消息将会被发送到该消息队列中.

  topic转发信息主要是依据通配符,队列和交换机的绑定主要是依据一种模式(通配符+字符串),而当发送消息的时候,只有指定的Key和该模式相匹配的时候,消息才会被发送到该消息队列中.

  headers也是根据一个规则进行匹配,在消息队列和交换机绑定的时候会指定一组键值对规则,而发送消息的时候也会指定一组键值对规则,当两组键值对规则相匹配的时候,消息会被发送到匹配的消息队列中.

  Fanout是路由广播的形式,将会把消息发给绑定它的全部队列,即便设置了key,也会被忽略.

sprinboot集成RabbitMQ

添加maven依赖

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
    <!--rabbitmq依赖-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-amqp</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

添加rabbitmq服务配置(application.yml)

#RabbitMQ的配置
spring:
  rabbitmq:
    host: ****
    port: 5672
    username: admin
    password: tonyzhang

通用的静态变量

package com.theeternity.rabbitmq.constant;

/**
 * @program: ApiBoot
 * @description: rabbitMQ常量
 * @author: TheEternity Zhang
 * @create: 2019-02-26 14:36
 */
public class RabbitConstant {

    //bean name
    public static final String DIRECT_QUEUE_BEAN = "direct_queue_bean";
    public static final String TOPIC_QUEUE_MESSAGE_BEAN = "topic_queue_message_bean";
    public static final String TOPIC_QUEUE_MESSAGES_BEAN = "topic_queue_messages_bean";
    public static final String FANOUT_FIRST_MESSAGE_BEAN = "fanout_first_message_bean";
    public static final String FANOUT_SECOND_MESSAGE_BEAN = "fanout_second_message_bean";
    public static final String FANOUT_THIRD_MESSAGE_BEAN = "fanout_third_message_bean";


    //queue
    public static final String DIRECT_QUEUE = "direct_queue";
    public static final String TOPIC_QUEUE_MESSAGE = "topic.message";
    public static final String TOPIC_QUEUE_MESSAGES = "topic.messages";
    public static final String FANOUT_FIRST_MESSAGE = "fanout.first";
    public static final String FANOUT_SECOND_MESSAGE = "fanout.second";
    public static final String FANOUT_THIRD_MESSAGE = "fanout.third";


    //exchange
    public static final String DIRECT_EXCHANGE = "direct_exchange";
    public static final String TOPIC_EXCHANGE = "topic_exchange";
    public static final String FANOUT_EXCHANGE = "fanout_exchange";


    //routing-key
    public static final String DIRECT_KEY = "direct_key";
    public static final String TOPIC_QUEUE_MESSAGE_KEY = "topic.message.key";
    public static final String TOPIC_QUEUE_MESSAGES_KEY = "topic.messages.key";
    public static final String TOPIC_KEY = "topic.#";

}

集成Direct交换机

将用到的消息队列及交换机注入到容器,并且进行绑定
package com.theeternity.rabbitmq.config;

import com.theeternity.rabbitmq.constant.RabbitConstant;
import org.springframework.amqp.core.*;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


/**
 * @program: ApiBoot
 * @description: rabbit配置类
 * @author: TheEternity Zhang
 * @create: 2019-02-21 16:34
 */
@Configuration
public class RabbitConfig {

    /**
     * @Description: direct模式
     * @Param: []
     * @return: org.springframework.amqp.core.Queue
     * @Author: TheEternity Zhang
     * @Date: 2019-02-26 14:50
     */
    @Bean(name = RabbitConstant.DIRECT_QUEUE_BEAN)
    public Queue Queue() {
        return new Queue(RabbitConstant.DIRECT_QUEUE);
    }

    @Bean
    public DirectExchange directExchange() {
        return new DirectExchange(RabbitConstant.DIRECT_EXCHANGE, true, false);
    }

    @Bean
    Binding bindingDirectExchangeMessage(@Qualifier(RabbitConstant.DIRECT_QUEUE_BEAN) Queue queue,
                                         DirectExchange directExchange) {
        return BindingBuilder.bind(queue).to(directExchange).with(RabbitConstant.DIRECT_KEY);
    }
}
编辑发送逻辑
package com.theeternity.rabbitmq.sender;

import com.theeternity.rabbitmq.constant.RabbitConstant;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * @program: ApiBoot
 * @description:
 * @author: TheEternity Zhang
 * @create: 2019-02-21 16:37
 */
@Component
@Slf4j
public class DirectSender {
    @Autowired
    private AmqpTemplate rabbitTemplate;

    public <T>void  send(T t) {
        log.info("接收到的信息",t.toString());
        this.rabbitTemplate.convertAndSend(RabbitConstant.DIRECT_EXCHANGE,RabbitConstant.DIRECT_KEY, t.toString());
    }
}
编辑接收逻辑
package com.theeternity.rabbitmq.receiver;

import com.theeternity.rabbitmq.constant.RabbitConstant;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

/**
 * @program: ApiBoot
 * @description:
 * @author: TheEternity Zhang
 * @create: 2019-02-21 16:38
 */
@Component
@Slf4j
public class DirectReceiver {

    @RabbitListener(queues = RabbitConstant.DIRECT_QUEUE)
    @RabbitHandler
    public void process(String hello) {
        log.info("Receiver  : " + hello);
    }
}

集成Topic交换机

将用到的消息队列及交换机注入到容器,并且进行绑定
package com.theeternity.rabbitmq.config;

import com.theeternity.rabbitmq.constant.RabbitConstant;
import org.springframework.amqp.core.*;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


/**
 * @program: ApiBoot
 * @description: rabbit配置类
 * @author: TheEternity Zhang
 * @create: 2019-02-21 16:34
 */
@Configuration
public class RabbitConfig {

    /**
     * @Description: topic模式
     * @Param: []
     * @return: org.springframework.amqp.core.Queue
     * @Author: TheEternity Zhang
     * @Date: 2019-02-26 14:50
     */
    @Bean
    public Queue queueMessage() {
        return new Queue(RabbitConstant.TOPIC_QUEUE_MESSAGE);
    }

    @Bean
    public Queue queueMessages() {
        return new Queue(RabbitConstant.TOPIC_QUEUE_MESSAGES);
    }

    @Bean
    public TopicExchange exchange() {
        return new TopicExchange(RabbitConstant.TOPIC_EXCHANGE);
    }

    @Bean
    Binding bindingExchangeMessage(Queue queueMessage, TopicExchange exchange) {
        return BindingBuilder.bind(queueMessage).to(exchange).with(RabbitConstant.TOPIC_QUEUE_MESSAGE_KEY);
    }

    @Bean
    Binding bindingExchangeMessages(Queue queueMessages, TopicExchange exchange) {
        //*表示一个词,#表示零个或多个词
        return BindingBuilder.bind(queueMessages).to(exchange).with(RabbitConstant.TOPIC_KEY);
    }
}
发送逻辑
package com.theeternity.rabbitmq.sender;

import com.theeternity.rabbitmq.constant.RabbitConstant;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * @program: ApiBoot
 * @description: topic模式消息发送
 * @author: TheEternity Zhang
 * @create: 2019-02-25 13:46
 */
@Component
@Slf4j
public class TopicSender {
    @Autowired
    private AmqpTemplate rabbitTemplate;

    public void send() {
        log.info("topic-message发送");
        rabbitTemplate.convertAndSend(RabbitConstant.TOPIC_EXCHANGE,RabbitConstant.TOPIC_QUEUE_MESSAGE_KEY,"hello,rabbit");

    }

    public void send1() {
        log.info("topic-messages发送");
        rabbitTemplate.convertAndSend(RabbitConstant.TOPIC_EXCHANGE,RabbitConstant.TOPIC_QUEUE_MESSAGES_KEY,"hello,rabbits");
    }
}
接收监听逻辑
package com.theeternity.rabbitmq.receiver;

import com.theeternity.rabbitmq.constant.RabbitConstant;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

/**
 * @program: ApiBoot
 * @description: topic模式消息监听接收
 * @author: TheEternity Zhang
 * @create: 2019-02-25 13:47
 */
@Component
@Slf4j
public class TopicReceiver {
    //监听器监听指定的Queue
    @RabbitListener(queues= RabbitConstant.TOPIC_QUEUE_MESSAGE)
    @RabbitHandler
    public void process1(String str) {
        log.info("message:"+str);
    }

    //监听器监听指定的Queue
    @RabbitListener(queues=RabbitConstant.TOPIC_QUEUE_MESSAGES)
    @RabbitHandler
    public void process2(String str) {
        log.info("messages:"+str);
    }
}
++==知识点==++:
TopicExchange交换机支持使用通配符*、#

*号只能向后多匹配一层路径。

#号可以向后匹配多层路径。
备注:

topic交换机上面的方法在queue上面没有设置bean的别名,如果没有设置的情况下,在绑定的时候,传入得queue名字需要跟对应queue方法名相同,为了造成不必要的麻烦,建议直接在queue上设置别名然后再绑定的时候,直接使用@Qualifier按照名字进行注入,如下:

/**
     * @Description: topic模式
     * @Param: []
     * @return: org.springframework.amqp.core.Queue
     * @Author: TheEternity Zhang
     * @Date: 2019-02-26 14:50
     */
    @Bean(name = RabbitConstant.TOPIC_QUEUE_MESSAGE_BEAN)
    public Queue queueMessage() {
        return new Queue(RabbitConstant.TOPIC_QUEUE_MESSAGE);
    }

    @Bean(name = RabbitConstant.TOPIC_QUEUE_MESSAGES_BEAN)
    public Queue queueMessages() {
        return new Queue(RabbitConstant.TOPIC_QUEUE_MESSAGES);
    }

    @Bean
    public TopicExchange exchange() {
        return new TopicExchange(RabbitConstant.TOPIC_EXCHANGE);
    }

    @Bean
    Binding bindingExchangeMessage(@Qualifier(RabbitConstant.TOPIC_QUEUE_MESSAGE_BEAN) Queue queueMessage, TopicExchange exchange) {
        return BindingBuilder.bind(queueMessage).to(exchange).with(RabbitConstant.TOPIC_QUEUE_MESSAGE_KEY);
    }

    @Bean
    Binding bindingExchangeMessages(@Qualifier(RabbitConstant.TOPIC_QUEUE_MESSAGES_BEAN) Queue queueMessages, TopicExchange exchange) {
        //*表示一个词,#表示零个或多个词
        return BindingBuilder.bind(queueMessages).to(exchange).with(RabbitConstant.TOPIC_KEY);
    }

集成Fanout交换机

将用到的消息队列及交换机注入到容器,并且进行绑定
package com.theeternity.rabbitmq.config;

import com.theeternity.rabbitmq.constant.RabbitConstant;
import org.springframework.amqp.core.*;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


/**
 * @program: ApiBoot
 * @description: rabbit配置类
 * @author: TheEternity Zhang
 * @create: 2019-02-21 16:34
 */
@Configuration
public class RabbitConfig {

    /**
     * @Description: fanout模式,无需routingkey
     * @Param: []
     * @return: org.springframework.amqp.core.Queue
     * @Author: TheEternity Zhang
     * @Date: 2019-02-26 14:50
     */
    @Bean(name = RabbitConstant.FANOUT_FIRST_MESSAGE_BEAN)
    public Queue firstMessage() {
        return new Queue(RabbitConstant.FANOUT_FIRST_MESSAGE);
    }


    @Bean(name = RabbitConstant.FANOUT_SECOND_MESSAGE_BEAN)
    public Queue secondMessage() {
        return new Queue(RabbitConstant.FANOUT_SECOND_MESSAGE);
    }

    @Bean(name = RabbitConstant.FANOUT_THIRD_MESSAGE_BEAN)
    public Queue thirdMessage() {
        return new Queue(RabbitConstant.FANOUT_THIRD_MESSAGE);
    }

    @Bean
    FanoutExchange fanoutExchange() {
        //配置广播路由器
        return new FanoutExchange(RabbitConstant.FANOUT_EXCHANGE);
    }

    @Bean
    Binding bindingExchangeA(@Qualifier(RabbitConstant.FANOUT_FIRST_MESSAGE_BEAN) Queue firstMessage, FanoutExchange fanoutExchange) {
        return BindingBuilder.bind(firstMessage).to(fanoutExchange);
    }

    @Bean
    Binding bindingExchangeB(@Qualifier(RabbitConstant.FANOUT_SECOND_MESSAGE_BEAN) Queue secondMessage, FanoutExchange fanoutExchange) {
        return BindingBuilder.bind(secondMessage).to(fanoutExchange);
    }

    @Bean
    Binding bindingExchangeC(@Qualifier(RabbitConstant.FANOUT_THIRD_MESSAGE_BEAN) Queue thirdMessage, FanoutExchange fanoutExchange) {
        return BindingBuilder.bind(thirdMessage).to(fanoutExchange);
    }
}
发送逻辑
package com.theeternity.rabbitmq.sender;

import com.theeternity.rabbitmq.constant.RabbitConstant;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * @program: ApiBoot
 * @description: Fanout模式消息发送
 * @author: TheEternity Zhang
 * @create: 2019-02-25 13:47
 */
@Component
@Slf4j
public class FanoutSender {

    @Autowired
    private AmqpTemplate rabbitTemplate;

    public void send() {
        log.info("fanout-message发送");
        rabbitTemplate.convertAndSend(RabbitConstant.FANOUT_EXCHANGE,"","hello,rabbit");

    }

}
接收监听逻辑
package com.theeternity.rabbitmq.receiver;

import com.theeternity.rabbitmq.constant.RabbitConstant;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

/**
 * @program: ApiBoot
 * @description: Fanout模式消息监听接收
 * @author: TheEternity Zhang
 * @create: 2019-02-25 13:48
 */
@Component
@Slf4j
public class FanoutReceiver {

    @RabbitListener(queues = RabbitConstant.FANOUT_FIRST_MESSAGE)
    public void processA(String str) {
        log.info("firstReceive:" + str);
    }

    @RabbitListener(queues = RabbitConstant.FANOUT_SECOND_MESSAGE)
    public void processB(String str) {
        log.info("secondReceive:" + str);
    }

    @RabbitListener(queues = RabbitConstant.FANOUT_THIRD_MESSAGE)
    public void processC(String str) {
        log.info("thirdReceive:" + str);
    }

}

备注:

实际上RabbitMQ还可以支持发送对象:当然由于涉及到序列化和反序列化,该对象要实现Serilizable接口,例如:

package com.theeternity.core.AutoGenerator.entity;

import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import java.time.LocalDateTime;
import java.io.Serializable;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;

/**
 * @author TheEternity Zhang
 * @since 2019-02-01
 */
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("we_user")
public class WeUserEntity implements Serializable {

    private static final long serialVersionUID = 1L;

    @TableId(value = "user_id", type = IdType.AUTO)
    private Integer userId;

    private String userName;

    private String password;

    private LocalDateTime createdTime;

    private LocalDateTime updateTime;
    
}

配置文件整体:

package com.theeternity.rabbitmq.config;

import com.theeternity.rabbitmq.constant.RabbitConstant;
import org.springframework.amqp.core.*;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


/**
 * @program: ApiBoot
 * @description: rabbit配置类
 * @author: TheEternity Zhang
 * @create: 2019-02-21 16:34
 */
@Configuration
public class RabbitConfig {

    /**
     * @Description: direct模式
     * @Param: []
     * @return: org.springframework.amqp.core.Queue
     * @Author: TheEternity Zhang
     * @Date: 2019-02-26 14:50
     */
    @Bean(name = RabbitConstant.DIRECT_QUEUE_BEAN)
    public Queue Queue() {
        return new Queue(RabbitConstant.DIRECT_QUEUE);
    }

    @Bean
    public DirectExchange directExchange() {
        return new DirectExchange(RabbitConstant.DIRECT_EXCHANGE, true, false);
    }

    @Bean
    Binding bindingDirectExchangeMessage(@Qualifier(RabbitConstant.DIRECT_QUEUE_BEAN) Queue queue,
                                         DirectExchange directExchange) {
        return BindingBuilder.bind(queue).to(directExchange).with(RabbitConstant.DIRECT_KEY);
    }

    /**
     * @Description: topic模式
     * @Param: []
     * @return: org.springframework.amqp.core.Queue
     * @Author: TheEternity Zhang
     * @Date: 2019-02-26 14:50
     */
    @Bean(name = RabbitConstant.TOPIC_QUEUE_MESSAGE_BEAN)
    public Queue queueMessage() {
        return new Queue(RabbitConstant.TOPIC_QUEUE_MESSAGE);
    }

    @Bean(name = RabbitConstant.TOPIC_QUEUE_MESSAGES_BEAN)
    public Queue queueMessages() {
        return new Queue(RabbitConstant.TOPIC_QUEUE_MESSAGES);
    }

    @Bean
    public TopicExchange exchange() {
        return new TopicExchange(RabbitConstant.TOPIC_EXCHANGE);
    }

    @Bean
    Binding bindingExchangeMessage(@Qualifier(RabbitConstant.TOPIC_QUEUE_MESSAGE_BEAN) Queue queueMessage, TopicExchange exchange) {
        return BindingBuilder.bind(queueMessage).to(exchange).with(RabbitConstant.TOPIC_QUEUE_MESSAGE_KEY);
    }

    @Bean
    Binding bindingExchangeMessages(@Qualifier(RabbitConstant.TOPIC_QUEUE_MESSAGES_BEAN) Queue queueMessages, TopicExchange exchange) {
        //*表示一个词,#表示零个或多个词
        return BindingBuilder.bind(queueMessages).to(exchange).with(RabbitConstant.TOPIC_KEY);
    }

    /**
     * @Description: fanout模式,无需routingkey
     * @Param: []
     * @return: org.springframework.amqp.core.Queue
     * @Author: TheEternity Zhang
     * @Date: 2019-02-26 14:50
     */
    @Bean(name = RabbitConstant.FANOUT_FIRST_MESSAGE_BEAN)
    public Queue firstMessage() {
        return new Queue(RabbitConstant.FANOUT_FIRST_MESSAGE);
    }


    @Bean(name = RabbitConstant.FANOUT_SECOND_MESSAGE_BEAN)
    public Queue secondMessage() {
        return new Queue(RabbitConstant.FANOUT_SECOND_MESSAGE);
    }

    @Bean(name = RabbitConstant.FANOUT_THIRD_MESSAGE_BEAN)
    public Queue thirdMessage() {
        return new Queue(RabbitConstant.FANOUT_THIRD_MESSAGE);
    }

    @Bean
    FanoutExchange fanoutExchange() {
        //配置广播路由器
        return new FanoutExchange(RabbitConstant.FANOUT_EXCHANGE);
    }

    @Bean
    Binding bindingExchangeA(@Qualifier(RabbitConstant.FANOUT_FIRST_MESSAGE_BEAN) Queue firstMessage, FanoutExchange fanoutExchange) {
        return BindingBuilder.bind(firstMessage).to(fanoutExchange);
    }

    @Bean
    Binding bindingExchangeB(@Qualifier(RabbitConstant.FANOUT_SECOND_MESSAGE_BEAN) Queue secondMessage, FanoutExchange fanoutExchange) {
        return BindingBuilder.bind(secondMessage).to(fanoutExchange);
    }

    @Bean
    Binding bindingExchangeC(@Qualifier(RabbitConstant.FANOUT_THIRD_MESSAGE_BEAN) Queue thirdMessage, FanoutExchange fanoutExchange) {
        return BindingBuilder.bind(thirdMessage).to(fanoutExchange);
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!