rabbitmq

一、MQ简介

1. MQ(Message Quene) 翻译为消息队列,是典型的生产者和消费者模型。生产者不断向消息队列中生产消息,消费者不断的从队列中获取消息,MQ又被称为消息中间件;
2. MQ中消息的生产和消费都是异步的,并且只关心消息的发送和接收,没有业务逻辑的侵入,可实现系统间解耦;
3. 消息的传递与接收高效且可靠;
4. 消息的传递与平台无关。

二、主流MQ简介

1. ActiveMQ:由Apache出品,最流行的,能力强劲的开源消息总线,完全支持JMS规范。有丰富的API,多种集群架构模式让ActiveMQ在业界成为老牌的消息中间件,受众与中小型企业。

2. Kafka:由LinkedIn开源的分布式发布-订阅消息系统,目前归属于Apache顶级项目。Kafka主要特点是基于Pull的模式来处理消息消费,追求高吞吐量,一开始的目的就是用于日志收集和传输。0.8版本开始支持复制,不支持事务,对消息的重复、丢失、错误没有严格要求,适合大量数据收集场景。比如ELK日志收集。

3. RocketMQ:是阿里开源的消息中间件,它是纯Java开发,具有高吞吐量、高可用性、适合大规模分布式系统应用的特点RocketMQ思路起源于Kafka,但并不是Kafka的一个Copy,它对消息的可靠传输及事务性做了优化,目前在阿里集团被广泛应用于交易、充值、流计算、消息推送、日志流式处理、binglog分发等场景。

4. RabbitMQ:使用Erlang语言开发的开源消息队列系统,基于AMQP协议来实现。AMQP的主要特征是面向消息、队列、路由、可靠性高、安全。AMQP协议更多用在企业系统内对数据一致性、稳定性和可靠性要求很高的场景。

三、rabbitmq安装

1. 下载安装包

(1)erlang版本与mq版本匹配列表:https://www.rabbitmq.com/which-erlang.html
(2)下载地址:
  • erlang内存管理依赖包:http://vault.centos.org/7.9.2009/os/Source/SPackages/socat-1.7.3.2-2.el7.src.rpm
(3)安装包获取:https://pan.baidu.com/s/1uwhYU__BJrpI_QAb-A-iAg 提取码:80jy
 2. 安装压缩包
(1)解压并安装准备好的安装包
rpm -ivh erlang-22.0.7-1.el7.x86_64.rpm
rpm -ivh socat-1.7.3.2-2.el7.x86_64.rpm
rpm -ivh rabbitmq-server-3.7.18-1.el7.noarch.rpm
(2)构建rabbitmq配置文件
 
cp /usr/share/doc/rabbitmq-server-3.7.18/rabbitmq.config.example /etc/rabbitmq/rabbitmq.config
vim /etc/rabbitmq/rabbitmq.config
sed -i '/{loopback_users, \[\]},/ s/%% {loopback_users, \[\]},/{loopback_users, \[\]}/g'
/etc/rabbitmq/rabbitmq.config

三、启动rabbitmq-serverg

1. 启动mq插件管理
 
rabbitmq-plugins enable rabbitmq_management
2. 启动RabbitMQ服务
systemctl start rabbitmq-server
systemctl restart rabbitmq-server
systemctl stop rabbitmq-server

 3. 关闭防火墙服务

systemctl status firewalld.service    #查看防火墙状态
service firewalld stop                #关闭防火墙      
systemctl disable firewalld.service   #禁用防火墙
4. 验证rabbitmq-server是否启动成
浏览器访问路径:http://192.168.1.20:15672/
用户密码:guest/guest

 四、浏览器页面简单操作

1. 创建用户

 

  • Admin——超级管理员用户
  • Monitoring——监控者用户
  • Policymaker——策略制定者
  • Management——普通用户:仅可以登录管理控制台,无法查看节点其他信息

2. 创建虚拟机Vhost

3. 为新创建的用户设置Vhost访问权限

  • 点击新创建的用户
  • 将新建的虚拟注解为新建用户设置

 

3. 页面创建交换机Exchange

 

4. 页面创建队列Queue

5. 页面交换机Exchange与队列Queue绑定
6. 页面向交换机Exchange发送消息

 

结论:发送成功,但是消息没有路由到队列,原因是default Exchange绑定那些没显式绑定的队列,又default Exchange是dirent类型交换机,消息携带rounting-key是队列名才可路由到队列上。

 

消息发送成功!

(2)direct Exchange

 (3)fanout Exchange

(4)topic Exchange

五、测试mq三种EX

1. maven依赖
    <dependencies>
        <dependency>
            <groupId>com.rabbitmq</groupId>
            <artifactId>amqp-client</artifactId>
            <version>5.7.2</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.10</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.3</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

 2. 创建mq工具类

package priv.yqs.rabbitmq_demo01.utils;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
import java.util.Properties;

@Slf4j
public class RabbitMQUntil {

    private static ConnectionFactory factory;

    static {
        try {  //优点:重量资源类加载只创建一次
            factory = new ConnectionFactory();
            Properties prop = new Properties();
            prop.load(RabbitMQUntil.class.getClassLoader().getResourceAsStream("rabbitMQ.properties"));
            //  初始化工厂,设置host、port、virtual-host、user、password、queue参数
            factory.setHost(prop.getProperty("ip"));
            factory.setPort(Integer.parseInt(prop.getProperty("port")));
            factory.setVirtualHost(prop.getProperty("virtualHost"));
            factory.setUsername(prop.getProperty("username"));
            factory.setPassword(prop.getProperty("password"));
            log.debug("ConnectionFactory [" + factory + "] 初始化成功!");
        } catch (IOException e) { e.printStackTrace();
            log.error("ConnectionFactory初始化失败!");
        }
    }
    
    /*
     * @Description: 由ConnectionFactory对象创建Connection对象
     * @Param []
     * @return com.rabbitmq.client.Connection
     * @Date 0:30 2021/3/4    */
    public static Connection getConnection() {
        try {
            return factory.newConnection();
        } catch (Exception e) { e.printStackTrace();
            return null;
        }
    }

    /*
     * @Description: 关闭资源(切记声明的变量没有意义,当外部调用initQueue后,声明的变量就被定义了,此时声明的变量就由意义了)
     * @Param: []
     * @return: void
     * @Date: 2021/3/3
     */
    public static void closes(Connection connection, Channel channel) {
        try {
            if (channel != null) { log.debug("channel的值: [" + channel+"]");channel.close(); }
            if (connection != null) { log.debug("connection的值: [" + connection+"]");connection.close(); }
        } catch (Exception e) { e.printStackTrace();
        log.error("资源关闭失败!"); 
        }
    }
}

 3. 配置文件

ip=192.168.1.20
port=5672
virtualHost=/mqVirtualHost
username=mqServerUser
password=mqServerUser
testQueue00=rabbitMqQueue_00
testQueue01=rabbitMqQueue_01
testQueue02=rabbitMqQueue_02
testQueue03=rabbitMqQueue_03
routingKing00=aa.rout.bb
routingKing01=rout.cc
routingKing02=aa.rout
routingKing03=aa.bb.cc
defaultEX=
directEX=amq.direct
fanoutEX=amq.fanout
topicEX=amq.topic

 

4. 消息MsgSend
package priv.yqs.rabbitmq_demo01;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import lombok.extern.slf4j.Slf4j;
import priv.yqs.rabbitmq_demo01.utils.RabbitMQUntil;
import java.io.IOException;
import java.util.Properties;

@Slf4j
public class MsgSend {

    public static void msgSend(String msg) {

        Channel channel = null;
        Connection connection = null;

        try {
            Properties prop = new Properties();
            prop.load(RabbitMQUntil.class.getClassLoader().getResourceAsStream("rabbitMQ.properties"));
            connection = RabbitMQUntil.getConnection();
            assert connection != null;
            channel = connection.createChannel();
            String[] queues = new String[]{prop.getProperty("testQueue00"), prop.getProperty("testQueue01"),
                    prop.getProperty("testQueue02"), prop.getProperty("testQueue03")};
            String[] routingKeys = new String[]{prop.getProperty("routingKing00"), prop.getProperty("routingKing01"),
                    prop.getProperty("routingKing02"), prop.getProperty("routingKing03")};
            assert channel != null;
            for (int i = 0; i < 4; i++) {
                /*
                 * @Description: queueDeclare()方法用于声明队列相关信息,若队列不存在则创建,若已存在队列与声明队列信息不同,则会报错;
                 *               声明队列这个方法并不是每次发消息都需执行,已存在队列可以直接发消息
                 * @Param [queue:队列名称
                 *         durable: 是否持久化,true表消息代理重启该队列仍存在,false表非持久化
                 *         exclusive: 是否独占连接,true表队列只被本连接访问,连接关闭则队列自动删除。临时队列一般设置该参数为true
                 *         autoDelete: 是否自动删除,true表队列不再使用时,会被自动删除。临时队列一般设置该参数为true
                 *         args: 扩展参数,可以为队列设置其他参数。如:设置队列存活时间
                 *         ]
                 * @return void
                 * @Date 0:41 2021/3/4    **/
                channel.queueDeclare(queues[1], true, false, false, null);
                log.info("队列: [" + queues[1] + "] 声明完成");
            }

            /*
             * @Description:
             * @Param [exchange: 交换机exchange名,不指定则默认绑定default exchange(默认binding-key就是队列名)
             *         routing-key:路由键,消息层面的参数,binding-key是在绑定队列时候传入的参数,代码里无需指定
             *         props:消息其他属性
             *         body:消息内容
             *         ]
             * @return void
             * @Date 0:49 2021/3/4    **/
            // type=Default 预测队列 rabbitMqQueue_03 收到消息
            channel.basicPublish(prop.getProperty("defaultEX"), queues[3], null, msg.getBytes());
            // type = Direct 预测队列 rabbitMqQueue_02 收到消息
            channel.basicPublish(prop.getProperty("directEX"), routingKeys[0], null, msg.getBytes());
            // type=Direct 预测队列 rabbitMqQueue_02和03  收到消息
            channel.basicPublish(prop.getProperty("fanoutEX"), routingKeys[1], null, msg.getBytes());
            // type=Fanout 预测队列 rabbitMqQueue_0~3 收到消息
            channel.basicPublish(prop.getProperty("fanoutEX"), "", null, msg.getBytes());
            // type=Topic 预测队列 rabbitMqQueue_02和03  收到消息
            channel.basicPublish(prop.getProperty("topicEX"), routingKeys[2], null, msg.getBytes());
            // type=Topic 预测队列 rabbitMqQueue_00~1和03  收到消息
            channel.basicPublish(prop.getProperty("topicEX"), routingKeys[3], null, msg.getBytes());
            log.info("消息发送完毕!");
        } catch (IOException e) { e.printStackTrace();
            log.error("消息发送失败");
        } finally {
            RabbitMQUntil.closes(connection, channel);
        }
    }
}

 5. 消费方ConsumerCli

package priv.yqs.rabbitmq_demo01.consumerClient;
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException;

/**
* @Description: Consumer接口定义了消费者,定义了handleDelivery()方法,该方法在接收消息后被调用
* @Date: 2021/3/3
*/
@Slf4j
public class ConsumerCli extends DefaultConsumer {

    public ConsumerCli(Channel channel) {
        super(channel);
    }

    /**
     * @Description: 将消费者MsgConsumer对象传入basicConsume()方法,当消费者接收到消息后,handleDelivery()方法被调用
     * @Param:  consumerTag: 消费者标签,用来标识消费者
     *          envelope: 信封,可以获取当前mq相关信息:getDeliveryTag(可用于消息手动确认已接收)、getExchange、getRoutingKey、isRedeliver
     *          properties: 消息属性,在basicPublish()消息发布方法中BasicProperties props参数用于设置消息属性,此处的AMQP.BasicProperties properties用于接收这些属性
     *          body: 消息
     * @return: void
     * @Date: 2021/3/3  */
    @Override
    public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
        super.handleDelivery(consumerTag, envelope, properties, body);
        log.info("消息: ["+new String(body,"utf-8")+"] 接收成功!");
        log.debug("消息标识:"+consumerTag);
        log.debug("交换机是:"+envelope.getExchange());
        log.debug("路由键是:"+envelope.getRoutingKey());
    }
}

 

6. 消息MsgRecv
package priv.yqs.rabbitmq_demo01;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import lombok.extern.slf4j.Slf4j;
import priv.yqs.rabbitmq_demo01.consumerClient.ConsumerCli;
import priv.yqs.rabbitmq_demo01.utils.RabbitMQUntil;
import java.util.Properties;

@Slf4j
class MsgRecv {

    static void msgRecv() {
        Properties prop = new Properties();
        Connection connection = RabbitMQUntil.getConnection();
        Channel channel = null;
        try {
            assert connection != null;
            channel = connection.createChannel();
            ConsumerCli consumerCli = new ConsumerCli(channel);
            prop.load(MsgRecv.class.getClassLoader().getResourceAsStream("rabbitMQ.properties"));
            //队列已存在则无需声明队列
            channel.queueDeclare(prop.getProperty("testQueue00"), true, false, false, null);
            /*
             * @Description: 接收消息方法
             * @Param: [queue:队列名称
             *          autoAck:自动回复,true表队列会自动回复mq消息已接收,false表需要消费方主动回复mq消息已接收
             *          consumer:消费者,消费方接收到消息后需要执行的方法,Consumer是一个接口,其DefaultConsumer实现类创建需要传入参数Channel对象
             *                   basicConsume()方法将消费者传入作为参数,会调用其basicConsume()方法。
             *         ]
             * @return: void
             * @Date: 2021/3/3  **/
            channel.basicConsume(prop.getProperty("testQueue00"), true, consumerCli);
            Thread.sleep(100);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("消息接收失败!");
        }finally {
            RabbitMQUntil.closes(connection,channel);
        }
    }

    static void clearAllQueueMsg() {
        Properties prop = new Properties();
        Connection connection;
        try {
            prop.load(MsgRecv.class.getClassLoader().getResourceAsStream("rabbitMQ.properties"));
            String[] queues = new String[]{prop.getProperty("testQueue00"), prop.getProperty("testQueue01"),
                    prop.getProperty("testQueue02"), prop.getProperty("testQueue03")};
            for (int i = 0; i < 4; i++) {
                connection = RabbitMQUntil.getConnection();
                assert connection != null;
                Channel channel = connection.createChannel();
                ConsumerCli consumerCli = new ConsumerCli(channel);
                channel.basicConsume(queues[i], true, consumerCli);
                log.info("-----------------------队列 [" + queues[i] + "] 已清理完成 ------------------------");
                Thread.sleep(10);
                log.info("channel : " + channel + "");
                log.info("connection : " + connection + "");
                channel.close();
                connection.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("消息接收失败!");
        }
    }
}

 6. 编写测试类

package priv.yqs.rabbitmq_basic;

public class SendMsgTest {
    public static void main(String[] args) {
        MsgSend.msgSend("6666666");
    }
}
package priv.yqs.rabbitmq_basic;

public class RecvMsgTest {
    public static void main(String[] args) {

//        MsgRecv.msgRecv();
        MsgRecv.clearAllQueueMsg();
    }
}

 

 六、Springboot_DefaultEX

1. 依赖坐标展示

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.3</version>
        <relativePath/>
    </parent>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <groupId>priv.yqs</groupId>
    <artifactId>rabbitmq_springboot</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

 

2. Application.properties

spring.application.name=RabbitmqDemo
server.port=1000
#mq参数
spring.rabbitmq.username=mqServerUser
spring.rabbitmq.password=mqServerUser
spring.rabbitmq.virtual-host=/mqServerVirtualHost
spring.rabbitmq.addresses=192.168.1.20
spring.rabbitmq.port=5672
#自定义参数
logging.level.org.springframework.boot.autoconfigure=error
3. 测试rabbitmqTemplate

package priv.yqs.rabbitmq_demo02;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import priv.yqs.rabbitmq_demo02.config.RabbitMqConfig;
@SpringBootTest(classes = RabbitmqDemo02Application.class)
@Slf4j
public class RabbitmqDemo02ApplicationTests {
    @Autowired
    public RabbitTemplate rabbitTemplate;
    /*
     * @Description: DefaultEX中队列与消费者一对一便是Hello模型,当一对多时便是work模型(轮询分发给多个消费者)
     * @Date 1:57 2021/3/5  **/
    @Test
    public void testHello() {
        for (int i = 0; i < 10; i++) {
            String msg = "一条爆射";
            rabbitTemplate.convertAndSend(RabbitMqConfig.HELLO_QUEUE_NAME, msg);
        }
    }
    @Test
    public void testWork() {
        for (int i = 0; i < 100; i++) {
            String msg = "一条爆射";
            rabbitTemplate.convertAndSend(RabbitMqConfig.WORK_QUEUE_NAME, msg);
        }
    }
}
4. 常量定义配置文件
package priv.yqs.rabbitmq_springboot.config;
import org.springframework.beans.factory.annotation.Configurable;
/**
 * @author 青山
 */
@Configurable
public class RabbitMqConfig {
    public static final String HELLO_QUEUE_NAME ="springboot_hello";
    public static final String WORK_QUEUE_NAME ="springboot_work";
}

 5. 创建消费者

(1)hello模型
package priv.yqs.rabbitmq_demo02.consumer;

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.stereotype.Component;
import priv.yqs.rabbitmq_demo02.config.RabbitMqConfig;

/*
 * @description: HelloModel是默认交换中消费者与队列一对一模式
 * @author 青山
 * @date 2021/3/5 12:20  **/
@Slf4j
@Component
public class HelloModel {
    
    /*
     * @RabbitListener注解:目标方法来作为消费消息的方法
     *                     声明绑定指定的队列,声明后监听该队列
     *                     通过注解参数指定所监听的队列或者Binding
     * 参数:queuesToDeclare声明一个队列,若队列不存在则创建该队列
     *       containerFactory可设置一个自定义值的RabbitListenerContainerFactory对象
     * @date 2021/3/5 12:28  **/
    @RabbitListener(queuesToDeclare = @Queue(RabbitMqConfig.HELLO_QUEUE_NAME))
    public void helloModelRecv(String message) {
        log.info("workModelRecv1 <----接收  " +
                "队列: [" + RabbitMqConfig.HELLO_QUEUE_NAME + "] 消费消息: " + message);
    }
}

 (2)work模型

package priv.yqs.rabbitmq_demo02.consumer;

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
import priv.yqs.rabbitmq_demo02.config.RabbitMqConfig;

/*
 * @description: WorkModel是默认交换中消费者与队列一对多模式,队列为轮询分发消息到消费者
 * @author 青山
 * @date 2021/3/5 12:20  **/
@Slf4j
@Component
public class WorkModel {

    @RabbitListener(queuesToDeclare = @Queue(RabbitMqConfig.WORK_QUEUE_NAME))
    public void workModelRecv1(String message) {
        log.info("workModelRecv1 <----接收  " +
                "队列: [" + RabbitMqConfig.WORK_QUEUE_NAME + "] 消费消息: " + message);
    }

    @RabbitListener(queuesToDeclare = @Queue(RabbitMqConfig.WORK_QUEUE_NAME))
    public void workModelRecv2(String message) {
        log.info("workModelRecv2 <----接收  " +
                "队列: [" + RabbitMqConfig.WORK_QUEUE_NAME + "] 消费消息: " + message);
    }

    @RabbitListener(queuesToDeclare = @Queue(RabbitMqConfig.WORK_QUEUE_NAME))
    public void workModelRecv3(String message) {
        log.info("workModelRecv3 <----接收  " +
                "队列: [" + RabbitMqConfig.WORK_QUEUE_NAME + "] 消费消息: " + message);
    }
}

 

七. Springboot_其他Ex

工程创建见第六节

1.配置类

(1) 定义静态常量
package priv.yqs.rabbitmq_springboot.config;
import org.springframework.context.annotation.Configuration;

/**
 * @Author 青山
 * @Description //定义静态常量
 * @Date $ $
 **/
@Configuration
public class DefineConst {

    public static final String QUEUE_HELLO = "springboot_hello";
    public static final String QUEUE_WORK = "springboot_work";
    public static final String QUEUE_01 = "rabbitMqQueue_01";
    public static final String QUEUE_02 = "rabbitMqQueue_02";
    public static final String QUEUE_03 = "rabbitMqQueue_03";
    public static final String QUEUE_04 = "rabbitMqQueue_04";

    public static final String EXCHANGE_DIRECT = "test.amq.direct";
    public static final String EXCHANGE_FANOUT = "test.amq.fanout";
    public static final String EXCHANGE_TOPIC = "test.amq.topic";

    public static final String ROUTINGKEY_A = "aa.rout";
    public static final String ROUTINGKEY_B = "rout.bb";
    public static final String ROUTINGKEY_C = "rout.*";
    public static final String ROUTINGKEY_D = "*.rout";
    public static final String ROUTINGKEY_E = "#";
}
(2)Direct配置类

package priv.yqs.rabbitmq_springboot.config;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @Date 14:49 2021/3/6
 **/
@Configuration
public class DirectMqConfig {

    // 第一步:将队列bean和交换机bean添加到spring容器中
    /* @Description: 定义direct类型交换机
     * @MethodHead: DirectExchange(String name, boolean durable, boolean autoDelete, Map<String, Object> arguments)
     *              DirectExchange(String name, boolean durable, boolean autoDelete)
     *              DirectExchange(String name)
     **/
    @Bean(name = "directEx")
    DirectExchange getDirectExchange() {
        return new DirectExchange(DefineConst.EXCHANGE_DIRECT, true, false);
    }

    /* @Description: 定义队列并传入相应参数
     * @MethodHead: Queue(String name, boolean durable, boolean exclusive, boolean autoDelete, @Nullable Map<String, Object> arguments)
     *              Queue(String name, boolean durable, boolean exclusive, boolean autoDelete)
     *              Queue(String name) 默认durable、exclusive、autoDelete都为false
     **/
    @Bean(name = "queue_01")
    Queue getQueue_01() {
        return new Queue(DefineConst.QUEUE_01, true);
    }

    @Bean(name = "queue_02")
    Queue getQueue_02() {
        return new Queue(DefineConst.QUEUE_02, true);
    }

    // 第二部:将队列bean与交换机bean进行关联
    @Bean
    Binding bindingDirectEx_01(@Qualifier("queue_01") Queue queue, @Qualifier("directEx") DirectExchange ex) {
        return BindingBuilder.bind(queue).to(ex).with(DefineConst.ROUTINGKEY_A);
    }
    @Bean
    Binding bindingDirectEx_02() {
        return BindingBuilder.bind(getQueue_02()).to(getDirectExchange()).with(DefineConst.ROUTINGKEY_B);
    }
}
(3)Fanout配置类

package priv.yqs.rabbitmq_springboot.config;
import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**@Date 14:49 2021/3/6  **/
@Configuration
public class FanoutMqConfig {

    /*
     * @Description: 定义fanout类型交换机
     * @MethodHead: FanoutExchange(String name, boolean durable, boolean autoDelete, Map<String, Object> arguments)
     *              FanoutExchange(String name, boolean durable, boolean autoDelete)
     *              FanoutExchange(String name)
     * @return org.springframework.amqp.core.DirectExchange
     * @Date 18:47 2021/3/6    **/
    @Bean
    FanoutExchange getFanoutExchange() {
        return new FanoutExchange(DefineConst.EXCHANGE_FANOUT, true, false);
    }

    /*
     * @Description: 定义队列并传入相应参数
     * @MethodHead: Queue(String name, boolean durable, boolean exclusive, boolean autoDelete, @Nullable Map<String, Object> arguments)
     *              Queue(String name, boolean durable, boolean exclusive, boolean autoDelete)
     *              Queue(String name) 默认durable、exclusive、autoDelete都为false
     * @return Queue
     * @Date 18:51 2021/3/6    **/
    @Bean
    Queue getQueue_03() {
        return new Queue(DefineConst.QUEUE_03, true);
    }

    @Bean
    Queue getQueue_04() {
        return new Queue(DefineConst.QUEUE_04, true);
    }

    /*
     * @Description: 绑定队列和交换机
     * @return org.springframework.amqp.core.Binding
     * @Date 19:00 2021/3/6    **/
    @Bean
    Binding bindingFanoutEx_01() {
        return BindingBuilder.bind(getQueue_03()).to(getFanoutExchange());
    }

    @Bean
    Binding bindingFanoutEx_02() {
        return BindingBuilder.bind(getQueue_04()).to(getFanoutExchange());
    }
}
(4)Topic配置类

package priv.yqs.rabbitmq_springboot.config;
import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/*** @Date 14:49 2021/3/6  **/
@Configuration
public class TopicMqConfig {

    /*
     * @Description: 定义topic类型交换机
     * @MethodHead: TopicExchange(String name, boolean durable, boolean autoDelete, Map<String, Object> arguments)
     *              TopicExchange(String name, boolean durable, boolean autoDelete)
     *              TopicExchange(String name)
     * @return org.springframework.amqp.core.DirectExchange
     * @Date 18:47 2021/3/6    **/
    @Bean
    TopicExchange getTopicExchange() {
        return new TopicExchange(DefineConst.EXCHANGE_TOPIC, true, false);
    }

    /*
     * @Description: 定义队列并传入相应参数
     * @MethodHead: Queue(String name, boolean durable, boolean exclusive, boolean autoDelete, @Nullable Map<String, Object> arguments)
     *              Queue(String name, boolean durable, boolean exclusive, boolean autoDelete)
     *              Queue(String name) 默认durable、exclusive、autoDelete都为false
     * @return Queue
     * @Date 18:51 2021/3/6    **/
    @Bean
    Queue getQueue_hello() {
        return new Queue(DefineConst.QUEUE_HELLO, true);
    }

    @Bean
    Queue getQueue_work() {
        return new Queue(DefineConst.QUEUE_WORK, true);
    }

    /*
     * @Description: 绑定队列和交换机
     * @return org.springframework.amqp.core.Binding
     * @Date 19:00 2021/3/6    **/
    @Bean
    Binding bindingTopicEx_01() {
        return BindingBuilder.bind(getQueue_hello()).to(getTopicExchange()).with(DefineConst.ROUTINGKEY_D);
    }

    @Bean
    Binding bindingTopicEx_02() {
        return BindingBuilder.bind(getQueue_work()).to(getTopicExchange()).with(DefineConst.ROUTINGKEY_E);
    }
}
2.测试发送数据
(1)MsgUtil

package priv.yqs.rabbitmq_springboot.util;

import java.util.Random;

/**
 * @Author 青山
 * @Description //生成随机消息
 * @Date $ $
 **/
public class MsgUtil {

    //length用户要求产生字符串的长度
    public static String getMsg(int length){
        String str="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        Random random=new Random();
        StringBuffer sb=new StringBuffer();
        for(int i=0;i<length;i++){
            int number=random.nextInt(62);
            sb.append(str.charAt(number));
        }
        return sb.toString();
    }
}
(2)测试发送数据

package priv.yqs.rabbitmq_springboot;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import priv.yqs.rabbitmq_springboot.config.DefineConst;
import priv.yqs.rabbitmq_springboot.config.MsgUtil;

@SpringBootTest(classes = RabbitmqSpringbootApplication.class)
@RunWith(SpringRunner.class)
@Slf4j
public class RabbitmqSpringbootApplicationTests {

    @Autowired
    public RabbitTemplate rabbitTemplate;
    @Test
    public void testSend() {
        /* @Description: 发送消息,convertAndSend()方法或者@RabbitListener注解,都可以定义配置类里的组件
         * @MethodHead: convertAndSend(String exchange, String routingKey, Object object)
         * @Date 23:49 2021/3/6    **/
        rabbitTemplate.convertAndSend(DefineConst.EXCHANGE_DIRECT, DefineConst.ROUTINGKEY_A, MsgUtil.getMsg(25));
    }
}

 

 

posted @ 2021-03-10 01:43  yinqingshan  阅读(123)  评论(0)    收藏  举报