rabbitmq
一、MQ简介
1. MQ(Message Quene) 翻译为消息队列,是典型的生产者和消费者模型。生产者不断向消息队列中生产消息,消费者不断的从队列中获取消息,MQ又被称为消息中间件;
2. 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)); } }

浙公网安备 33010602011771号