在已经大致了解了RabbitMQ的消息模式的基础上,可以研究RabbitMQ如何整合Spring和SpringBoot
1、RabbitMQ整合Spring
1.1、依赖
Spring整合RabbitMQ的依赖有两个,一个是spring-context,一个是spring-rabbit
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.amqp</groupId>
<artifactId>spring-rabbit</artifactId>
<version>2.1.5.RELEASE</version>
</dependency>
</dependencies>
1.2、编写RabbitMQ的配置文件
在配置文件中,配置rabbitmq-server的相关信息,包括host、port、username、password、virtualhosts。
rabbitmq.host: 192.168.127.131
rabbitmq.port: 5672
rabbitmq.username: admin
rabbitmq.password: 123456
rabbitmq.virtual-host: /
1.3、Producer
1.3.1、编写Spring的配置文件
在Spring配置文件中,将连接工厂、队列、交换机都托管到Spring容器中。
(1)创建连接工厂
<!-- 创建连接工程 -->
<context:property-placeholder location="classpath:rabbitmq.yaml"/>
<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"/>
(2)声明队列
<rabbit:queue id="队列类名" name="队列名称" auto-declare="true"/>
示例:
<rabbit:queue id="spring_fanout_queue_1" name="spring_fanout_queue_1" auto-declare="true"/>
(3)声明交换机,绑定交换机和队列
- fanout交换机:
<rabbit:交换机类型 id="交换机id" name="交换机名字" auto-declare="true">
<rabbit:bindings>
<rabbit:binding queue="绑定的队列名"/>
</rabbit:bindings>
</rabbit:fanout-exchange>
- direct交换机
<rabbit:交换机类型 id="交换机id" name="交换机名字" auto-declare="true">
<rabbit:bindings>
<rabbit:binding queue="绑定的队列名" key="路由"/>
</rabbit:bindings>
</rabbit:fanout-exchange>
- topic交换机
<rabbit:交换机类型 id="交换机id" name="交换机名字" auto-declare="true">
<rabbit:bindings>
<rabbit:binding queue="绑定的队列名" pattern="路由pattern"/>
</rabbit:bindings>
</rabbit:fanout-exchange>
示例:
<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>
<rabbit:binding queue="spring_fanout_queue_2"></rabbit:binding>
</rabbit:bindings>
</rabbit:fanout-exchange>
(4)创建template
最后别忘了创建rabbitmq template,用于发送消息
<rabbit:template id="rabbitTemplate" connection-factory="connectionFactory"/>
完整版(以topic交换机为例):
<?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.yaml"/>
<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"/>
<!-- topic模式 -->
<rabbit:queue id="spring_topic_queue_all" name="spring_topic_queue_all" auto-declare="true"></rabbit:queue>
<rabbit:queue id="spring_topic_queue_insert" name="spring_topic_queue_insert" auto-declare="true"></rabbit:queue>
<rabbit:queue id="spring_topic_queue_update" name="spring_topic_queue_update" auto-declare="true"></rabbit:queue>
<rabbit:topic-exchange id="spring_topic_exchange" name="spring_topic_exchange" auto-declare="true">
<rabbit:bindings>
<rabbit:binding pattern="test.*" queue="spring_topic_queue_all"></rabbit:binding>
<rabbit:binding pattern="#.insert" queue="spring_topic_queue_insert"></rabbit:binding>
<rabbit:binding pattern="*.update" queue="spring_topic_queue_update"></rabbit:binding>
</rabbit:bindings>
</rabbit:topic-exchange>
<!--定义rabbitTemplate对象操作可以在代码中方便发送消息-->
<rabbit:template id="rabbitTemplate" connection-factory="connectionFactory"/>
</beans>
1.3.2、发送消息
spring配置文件完成后,producer就可以发送消息到交换机了。
public class Start {
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext("spring-rabbitmq.xml");
RabbitTemplate rabbitTemplate = ac.getBean("rabbitTemplate",RabbitTemplate.class);
rabbitTemplate.convertAndSend("spring_topic_exchange","test.all","topic模式,发给all的");
rabbitTemplate.convertAndSend("spring_topic_exchange","test.insert","topic模式,发给all和insert的");
rabbitTemplate.convertAndSend("spring_topic_exchange","test.update","topic模式,发给all和update的");
}
}
1.4、Consumer
(1)创建连接工厂
<!-- 创建连接工程 -->
<context:property-placeholder location="classpath:rabbitmq.yaml"/>
<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"/>
(2)配置监听器
在Spring中,Consumer是通过监听器来监听队列的消息的。监听器要实现 MessageListener
接口,并且重写 onMessage
方法。
示例:
public class TopicListener01 implements MessageListener {
@Override
public void onMessage(Message message) {
try {
String msg = new String(message.getBody(),"utf-8");
System.out.printf("监听器:%s,交换机:%s, 队列:%s, 路由key:%s, 消息:%s\n",
"TopicListener01",
message.getMessageProperties().getReceivedExchange(),
message.getMessageProperties().getConsumerQueue(),
message.getMessageProperties().getReceivedRoutingKey(),
msg);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
}
(3)Spring配置文件中绑定队列和监听器
<bean id="xx" class="xx"/>
<rabbit:listener-container connection-factory="connectionFactory" auto-declare="true">
<rabbit:listener ref="监听器名" queuenames="队列名"/>
<rabbit:listener ref="监听器名" queuenames="队列名"/>
...
</rabbit:listener-container>
示例:
<bean id="TopicListener01" class="com.wxf.listener.TopicListener01"/>
<rabbit:listener-container connection-factory="connectionFactory" auto-declare="true">
<rabbit:listener ref="TopicListener01" queue-names="spring_topic_queue_all"/>
</rabbit:listener-container>
完整版:
<?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">
<bean id="TopicListener01" class="com.wxf.listener.TopicListener01"/>
<rabbit:listener-container connection-factory="connectionFactory" auto-declare="true">
<rabbit:listener ref="TopicListener01" queue-names="spring_topic_queue_all"/>
</rabbit:listener-container>
</beans>
最后在consumer的测试方法中写个 while(true){}
就可以让Consumer一直监听队列,获取消息啦。
2、RabbitMQ整合SpringBoot
RabbitMQ整合SpringBoot也非常快,和Spring也非常像,只是用注解简化了开发。
2.1、依赖
springboot和rabbitmq的相关依赖是 spring-boot-starter-amqp
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
<version>2.1.4.RELEASE</version>
</dependency>
2.2、rabbitMQ相关配置
同样在springboot的application.yaml中配置rabbitMQ的host、port、username、password、virtualhost信息。
spring:
rabbitmq:
host: 192.168.127.131
port: 5672
username: admin
password: 123456
virtual-host: /
2.3、Producer
2.3.1、配置类
在配置类里声明和绑定队列和交换机。
(1)声明交换机
交换机用 ExchangeBuilder
声明。其中:
fanout交换机的声明方法是
ExchangeBuilder.fanoutExchange(交换机名).durable(true).build();
direct交换机的声明方法是
ExchangeBuilder.directExchange(交换机名).durable(true).build();
topic交换机的声明方法是
ExchangeBuilder.topicExchange(交换机名).durable(true).build();
示例:
@Bean
public Exchange fanoutExchange(){
return ExchangeBuilder.fanoutExchange(FANOUT_EXCHANGE).durable(true).build();
}
@Bean
public Exchange directExchange(){
return ExchangeBuilder.directExchange(DIRECT_EXCHANGE).durable(true).build();
}
@Bean
public Exchange topicExchange(){
return ExchangeBuilder.topicExchange(TOPIC_EXCHANGE).durable(true).build();
}
(2)声明队列
@Bean
public Queue topicQueueAll(){
return QueueBuilder.durable("队列名称").build();
}
示例:
@Bean
public Queue topicQueueAll(){
return QueueBuilder.durable("spring_topic_queue_all").build();
}
(3) 绑定队列和交换机
@Bean
public Binding topicExchangeAll(@Qualifier("声明队列方法名")Queue queue,
@Qualifier("声明交换机方法名") Exchange exchange){
return BindingBuilder.bind(queue).to(exchange).with("路由").noargs();
}
示例:
@Bean
public Binding topicExchangeAll(@Qualifier("topicQueueAll")Queue queue,
@Qualifier("topicExchange") Exchange exchange){
return BindingBuilder.bind(queue).to(exchange).with("test.*").noargs();
}
完整版:
@Configuration
public class ProducerConfig {
public static final String TOPIC_EXCHANGE = "springboot_topic-exchange";
public static final String TOPIC_QUEUE_ALL = "springboot_topic_queue_all";
public static final String TOPIC_QUEUE_INSERT = "springboot_topic_queue_insert";
@Bean
public Exchange topicExchange(){
return ExchangeBuilder.topicExchange(TOPIC_EXCHANGE).durable(true).build();
}
@Bean
public Queue directQueueUpdate(){
return QueueBuilder.durable(DIRECT_QUEUE_UPDATE).build();
}
@Bean
public Queue topicQueueInsert(){
return QueueBuilder.durable(TOPIC_QUEUE_INSERT).build();
}
@Bean
public Binding topicExchangeInsert(@Qualifier("topicQueueInsert")Queue queue,
@Qualifier("topicExchange") Exchange exchange){
return BindingBuilder.bind(queue).to(exchange).with("#.insert").noargs();
}
@Bean
public Binding topicExchangeAll(@Qualifier("topicQueueAll")Queue queue,
@Qualifier("topicExchange") Exchange exchange){
return BindingBuilder.bind(queue).to(exchange).with("test.*").noargs();
}
}
2.3.2、发送消息
注入 RabbitTemplate
,用 convertAndSend
方法发送消息。
@SpringBootTest(classes = Start.class)
@RunWith(SpringRunner.class)
public class Test {
@Resource
private RabbitTemplate rabbitTemplate;
@org.junit.Test
public void test01(){
rabbitTemplate.convertAndSend(ProducerConfig.TOPIC_EXCHANGE,"test.insert","发送给topic:insert和all");
rabbitTemplate.convertAndSend(ProducerConfig.TOPIC_EXCHANGE,"test.all","发送给topic:all");
}
}
2.4、Consumer
2.4.1、配置监听器
用 @RabbitListener
绑定监听器和队列。
@Component
public class MyListener {
@RabbitListener(queues = "springboot_topic_queue_insert")
public void myListener5(String message){
System.out.println("消费者接收到的消息为:" + message);
}
@RabbitListener(queues = "springboot_topic_queue_all")
public void myListener6(String message){
System.out.println("消费者接收到的消息为:" + message);
}
}
2.4.2、测试
在测试类中注入 RabbitTemplate
,然后同样写个 while(true){}
就可以一直监听队列的消息了。