RabbitMQ消息中间件
第一章:消息中间件的概述了解
我了解到的是,mq(message queue)既消息队列,他可以加速消息的传输,举个例子。例如:在淘宝网买手机,一时间有成千上万的提交量,这时候就会用到mq,可以完成大量数据的交易,保证订单的无误性。
第二章:rabbitMQ工作原理!!!
省去了http网络传输协议的3次握手,4次挥手。Mq直接使用一个长连接进行链接数据。
第三章:Java创建mq的链接
在Java中创建mq的链接是在maven工程下进行的创建,在pom.xml中引入mq的依赖,如下:
<dependencies>
<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
<version>5.6.0</version>
</dependency>
</dependencies>
在main中的java里创建链接,创建的步骤如下:
// 1.创建链接工厂
// 2.创建长连接
// 3.创建channel
// 声明队列
// 4.发消息
// 5.关闭链接
第一部分:在java中创建producer
第一步:创建链接工厂(Java中mq链接的)
第二步:建立长连接(固定不变)
第三步:完成队列声明,发送消息,关闭链接
第四步:执行完,可以在网页查看到消息
如图:
第二部分:在Java中创建consumer
第一步:和producer一样。创建链接工厂(Java中mq链接的)
第二步:和producer一样。建立长连接(固定不变)
第三步:建立消费者的逻辑业务
// 声明队列
channel.queueDeclare(QUEUE,true,false,false,null);
//5.创建消费者,并设置消息处理
DefaultConsumer defaultConsumer = new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
//真实的业务逻辑
//现在的业务逻辑
//消费者标签
System.out.println("消费者标签为:" + consumerTag);
//路由key
System.out.println("路由key为:" + envelope.getRoutingKey());
//交换机
System.out.println("交换机为:" + envelope.getExchange());
//消息id
System.out.println("消息id为:" + envelope.getDeliveryTag());
//收到的消息
System.out.println("接收到的消息为:" + new String(body, "utf-8"));
}
};
//监听消息
channel.basicConsume(QUEUE,true,defaultConsumer);
}
第四章:RabbitMQ工作模式--重点
- Work queue工作模式
就像是有多个work一样,举个例子,就像是搬砖,一堆砖有两个人板。
- publish/subscribe订阅发布模式(微博)
代码结构:
有两个监听者,和一个发布者,例如:一个up主,2个粉丝的关系。
代码细节1:producer_pubsub代码(增加加部分如下:)
第一部分:此处添加交换机名和对列名。
第二部分:添加交换机,添加队列(这里有一个交换机和两个队列)
第三部分:消息发送后关闭资源
代码细节2:Consumer1代码(增加部分)
第一部分:此处添加交换机名和对列名。
第二部分:添加交换机,添加队列(这里有一个交换机和两个队列)
第三部分:创建消费者!!!(这里就区别了生产者与消费者的关系了)
另一个consumer2与consumer1的区别就是监听消息里FANOUT_QUEUE_1与FANOUT_QUEUE_2的区别了
第四部分:(运行结果)
- Routing路由模式(分布式日志收集系统)
模式说明:
队列与交换机的绑定,不能是任意绑定了,而需要指定RoutingKey(路由key),如图,发送者端代码:
消费端代码:
结果:
- Topics通配符模式
在此中模式下,主要在声明交换机的时候BuiltinExchangeType.TOPIC,和绑定交换机时routingkey为相应的模式,此处如图为:
Producer的更改点为:
Consumer的更改点为:在前面通配和producer一样的同时,最后的调用如下图:
第五章:spring整合Rabbit
一、创建producer
- 构建springboot_rabbitmq_producer项目
先建立maven工程。在maven下的xml中导入springboot的配置类等如下:
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.amqp</groupId>
<artifactId>spring-rabbit</artifactId>
<version>2.1.8.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.1.7.RELEASE</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
- 再在resources导入properties和xml文件:
内容如下图:
文件的配置内容:
Properties中的文件内容:
Xml中的内容:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:rabbit="http://www.springframework.org/schema/rabbit"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/rabbit
http://www.springframework.org/schema/rabbit/spring-rabbit.xsd">
<!--加载配置文件-->
<context:property-placeholder location="classpath:rabbitmq.properties"/>
<!-- 定义rabbitmq connectionFactory -->
<rabbit:connection-factory id="connectionFactory"
host="${rabbitmq.host}"
port="${rabbitmq.port}"
username="${rabbitmq.username}"
password="${rabbitmq.password}"
virtual-host="${rabbitmq.virtual-host}"/>
<!--定义管理交换机、队列-->
<rabbit:admin connection-factory="connectionFactory"/>
<!--定义持久化队列,不存在则自动创建;不绑定到交换机则绑定到默认交换机
默认交换机类型为direct,名字为:"",路由键为队列的名称
-->
<rabbit:queue id="ydlqueue" name="ydlqueue" auto-declare="true"/>
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~广播;所有队列都能收到消息~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<!--定义广播交换机中的持久化队列,不存在则自动创建-->
<rabbit:queue id="spring_fanout_queue_1" name="spring_fanout_queue_1" auto-declare="true" auto-delete="false" durable="true"/>
<!--定义广播交换机中的持久化队列,不存在则自动创建-->
<rabbit:queue id="spring_fanout_queue_2" name="spring_fanout_queue_2" auto-declare="true"/>
<!--定义广播类型交换机;并绑定上述两个队列-->
<rabbit:fanout-exchange id="spring_fanout_exchange" name="spring_fanout_exchange" auto-declare="true">
<rabbit:bindings>
<rabbit:binding queue="spring_fanout_queue_1"/>
<rabbit:binding queue="spring_fanout_queue_2"/>
</rabbit:bindings>
</rabbit:fanout-exchange>
<!-- routing 模式-->
<rabbit:queue id="spring_direct_queue_1" name="spring_direct_queue_1" auto-declare="true"/>
<rabbit:queue id="spring_direct_queue_2" name="spring_direct_queue_2" auto-declare="true"/>
<rabbit:direct-exchange id="spring_direct_exchange" name="spring_direct_exchange" auto-declare="true">
<rabbit:bindings>
<rabbit:binding queue="spring_direct_queue_1" key="error"></rabbit:binding>
<rabbit:binding queue="spring_direct_queue_2" key="info"></rabbit:binding>
<rabbit:binding queue="spring_direct_queue_2" key="error"></rabbit:binding>
<rabbit:binding queue="spring_direct_queue_2" key="warning"></rabbit:binding>
</rabbit:bindings>
</rabbit:direct-exchange>
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~通配符;*匹配一个单词,#匹配多个单词 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<rabbit:queue id="spring_topic_queue_1" name="spring_topic_queue_1" auto-declare="true"/>
<rabbit:queue id="spring_topic_queue_2" name="spring_topic_queue_2" auto-declare="true"/>
<rabbit:topic-exchange id="spring_topic_exchange" name="spring_topic_exchange">
<rabbit:bindings>
<rabbit:binding queue="spring_topic_queue_1" pattern="ydlclass.taiyuan.*.*"></rabbit:binding>
<rabbit:binding queue="spring_topic_queue_2" pattern="ydlclass.*.caiwubu.*"></rabbit:binding>
</rabbit:bindings>
</rabbit:topic-exchange>
<!--定义rabbitTemplate对象操作可以在代码中方便发送消息-->
<rabbit:template id="rabbitTemplate" connection-factory="connectionFactory"/>
</beans>
上述文件,就直接配置了链接厂又配置了通道,部分也有路由模式等需要配置的东西。
3.编写测试类
如下是配置头部分的固定代码:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:spring-rabbitmq.xml")
public class ProducerTest {
@Autowired
RabbitTemplate rabbitTemplate;
普通测试类:
……
路由模式:
注意在xml中要添加相应的配置
<!-- routing 模式-->
<rabbit:queue id="spring_direct_queue_1" name="spring_direct_queue_1" auto-declare="true"/>
<rabbit:queue id="spring_direct_queue_2" name="spring_direct_queue_2" auto-declare="true"/>
<rabbit:direct-exchange id="spring_direct_exchange" name="spring_direct_exchange" auto-declare="true">
<rabbit:bindings>
<rabbit:binding queue="spring_direct_queue_1" key="error"></rabbit:binding>
<rabbit:binding queue="spring_direct_queue_2" key="info"></rabbit:binding>
<rabbit:binding queue="spring_direct_queue_2" key="error"></rabbit:binding>
<rabbit:binding queue="spring_direct_queue_2" key="warning"></rabbit:binding>
</rabbit:bindings>
</rabbit:direct-exchange>
……
- 创建消费者工程
- 搭建工程
如图为项目结构:
图中的pom.xml、rabbitmq.properties都和生产着(producer)一样。Spring-rabbit.xml中的内容为:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:rabbit="http://www.springframework.org/schema/rabbit"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/rabbit
http://www.springframework.org/schema/rabbit/spring-rabbit.xsd">
<!--加载配置文件-->
<context:property-placeholder location="classpath:rabbitmq.properties"/>
<!-- 定义rabbitmq connectionFactory -->
<rabbit:connection-factory id="connectionFactory"
host="${rabbitmq.host}"
port="${rabbitmq.port}"
username="${rabbitmq.username}"
password="${rabbitmq.password}"
virtual-host="${rabbitmq.virtual-host}"/>
<bean id="springQueueListener" class="com.ydlclass.rabbitmq.listener.SpringQueueListener"/>
<!-- <bean id="fanoutListener1" class="com.ydlclass.rabbitmq.listener.FanoutListener1"/>-->
<!-- <bean id="fanoutListener2" class="com.ydlclass.rabbitmq.listener.FanoutListener2"/>-->
<!-- <bean id="topicListenerStar" class="com.ydlclass.rabbitmq.listener.TopicListenerStar"/>-->
<!-- <bean id="topicListenerWell" class="com.ydlclass.rabbitmq.listener.TopicListenerWell"/>-->
<!-- <bean id="topicListenerWell2" class="com.ydlclass.rabbitmq.listener.TopicListenerWell2"/>-->
<rabbit:listener-container connection-factory="connectionFactory" auto-declare="true">
<rabbit:listener ref="springQueueListener" queue-names="ydlqueue"/>
<!-- <rabbit:listener ref="fanoutListener1" queue-names="spring_fanout_queue_1"/>-->
<!-- <rabbit:listener ref="fanoutListener2" queue-names="spring_fanout_queue_2"/>-->
<!-- <rabbit:listener ref="topicListenerStar" queue-names="spring_topic_queue_star"/>-->
<!-- <rabbit:listener ref="topicListenerWell" queue-names="spring_topic_queue_well"/>-->
<!-- <rabbit:listener ref="topicListenerWell2" queue-names="spring_topic_queue_well2"/>-->
</rabbit:listener-container>
</beans>
可以看到此xml文件和producer的xml文件,极为相似,其中的加载配置文件、定义工厂为固定内容。
- 进行业务测试
编写两个测试类,如图:
SpringQueueListener是业务类,里面是监听的业务,代码如下:
业务出来了但存在一个问题,消费者是一直启动的,所以怎么实现呢,就是通过test文件夹下的ConsumerTest类实现,至于为什么非要写到test中,这个是固定的,写那里其实无所谓但是写到test是普遍认同的。代码如下:
第六章:springboot整合Rabbit
第一部分:Springboot中生产者的创建
第一步:添加依赖
在xml中添加依赖:
<?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 http://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.1.4.RELEASE</version>
</parent>
<groupId>com.ydlclass</groupId>
<artifactId>springboot-rabbitmq-producer</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<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>
</dependency>
</dependencies>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
</project>
项目结构:
第二步:application.yml
其中application.yml中就是一些配置信息如图:
第三步:ProducerApp:
ProducerApp是Springboot的启动类:
内容如下:
第四步:RobbitConfig
RobbitConfig是一些通道的配置,这里也体现了springboot的便捷,可以不用配置工厂。 内容如下:
第五步:ProducerTest:
ProducerTest的内容如下:
通过上述的配置,就可以实现生产者的功能。