SpringBoot整合RabbitMq
参考博客:https://blog.csdn.net/qq_33547169/article/details/78124294
1.介绍
1.1 RabbitMQ
MQ全称为Message Queue,即消息队列, RabbitMQ是由erlang语言开发,基于AMQP(Advanced Message
Queue 高级消息队列协议)协议实现的消息队列,它是一种应用程序之间的通信方法,消息队列在分布式系统开
发中应用非常广泛。RabbitMQ官方地址:http://www.rabbitmq.com/
开发中消息队列通常有如下应用场景:
1、任务异步处理。
将不需要同步处理的并且耗时长的操作由消息队列通知消息接收方进行异步处理。提高了应用程序的响应时间。
2、应用程序解耦合
MQ相当于一个中介,生产方通过MQ与消费方交互,它将应用程序进行解耦合。
市场上还有哪些消息队列?
ActiveMQ,RabbitMQ,ZeroMQ,Kafka,MetaMQ,RocketMQ、Redis。
为什么使用RabbitMQ呢?
1、使得简单,功能强大。
2、基于AMQP协议。
3、社区活跃,文档完善。
4、高并发性能好,这主要得益于Erlang语言。
5、Spring Boot默认已集成RabbitMQ
1.2rabbitmq工作原理
组成部分说明如下:
Broker:消息队列服务进程,此进程包括两个部分:Exchange和Queue。
Exchange:消息队列交换机,按一定的规则将消息路由转发到某个队列,对消息进行过虑。
Queue:消息队列,存储消息的队列,消息到达队列并转发给指定的消费方。
Producer:消息生产者,即生产方客户端,生产方客户端将消息发送到MQ。
Consumer:消息消费者,即消费方客户端,接收MQ转发的消息。
消息发布接收流程:
-----发送消息-----
1、生产者和Broker建立TCP连接。
2、生产者和Broker建立通道。
3、生产者通过通道消息发送给Broker,由Exchange将消息进行转发。
4、Exchange将消息转发到指定的Queue(队列)
3.安装与使用
1)下载erlang
地址如下:
http://erlang.org/download/otp_win64_20.3.exe
以管理员方式运行此文件,安装。
2)安装RabbitMQ
https://github.com/rabbitmq/rabbitmq-server/releases/tag/v3.7.4
安装完成后可在服务中启动
当然也可以进入安装目录以命令行的方式启动
打开浏览器访问rabbitmq若出现这个界面说明可以正常使用了账号密码默认为guest
2.SpringBoot整合的RabbitMq(Direct模式)
1.首先创建maven工程并引入依赖坐标
<?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>
<groupId>com.paic</groupId>
<artifactId>rabbitmq-producer</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.1.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
<version>2.0.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>
2.创建配置文件
#对于rabbitMQ的支持
spring.rabbitmq.host=127.0.0.1
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
3.创建一个启动类
package com.paic;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @ProjectName: rabbitmq
* @Package: com.paic
* @ClassName: RabbitMqApplication
* @Author: Administrator
* @Description: ${description}
* @Version: 1.0
*/
@SpringBootApplication
public class RabbitMqApplication {
public static void main(String[] args) {
SpringApplication.run(RabbitMqApplication.class);
}
}
4.创建一个生产者
package com.paic.producer;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Date;
/**
* @ProjectName: rabbitmq
* @Package: com.paic.producer
* @ClassName: Producer
* @Author: Administrator
* @Description: ${description}
* @Version: 1.0
*/
@Component
public class Producer {
@Autowired
private AmqpTemplate rabbitTemplate;
public void send(){
String sendMsg = "hello world"+ new Date();
this.rabbitTemplate.convertAndSend("one2one", sendMsg);
}
}
5.创建一个消费者
package com.paic.consumer;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
/**
* @ProjectName: rabbitmq
* @Package: com.paic.consumer
* @ClassName: Consumer
* @Author: Administrator
* @Description: ${description}
* @Version: 1.0
*/
@Component
@RabbitListener(queues = "one2one")
public class Consumer {
@RabbitHandler
public void process(String hello) {
System.out.println("one2one 消息消费者消费消息 : " + hello);
}
}
6.创建配置类配置一个队列
package com.paic.config;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
/**
* @ProjectName: rabbitmq
* @Package: com.paic.config
* @ClassName: Config
* @Author: Administrator
* @Description: ${description}
* @Version: 1.0
*/
@Component
public class Config {
final static String ONE2ONE = "one2one";
@Bean
public Queue queueOne2One() {
return new Queue(ONE2ONE);
}
}
7.创建一个Controller进行调用
package com.paic.controller;
import com.paic.producer.Producer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @ProjectName: rabbitmq
* @Package: com.paic.controller
* @ClassName: One2OneController
* @Author: Administrator
* @Description: ${description}
* @Version: 1.0
*/
@RestController
public class One2OneController {
@Autowired
private Producer oneProducer;
@RequestMapping("/one2one")
public String one2OneSend(){
oneProducer.send();
return "ok";
}
}
8.测试
运行启动类然后在浏览器中输入请求路径
控制台输出如下
说明这个最简单的一对一的消息生产获取已经实现了
一对多模式与多对多模式与一对一模式区别就在于创建多个生产者、消费者
我们多对多的运行结果,这里创建2个生产者和2个消费者,生产20条消息,发现两个消费者各消费了10条消息
3.SpringBoot整合的RabbitMq(Topic模式)
1.编写配置类
package com.paic.config;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @ProjectName: rabbitmq
* @Package: com.paic.config
* @ClassName: TopicConfig
* @Author: Administrator
* @Description: ${description}
* @Version: 1.0
*/
@Configuration
public class TopicConfig {
final static String MESSAGE = "topic.message";
final static String MESSAGES = "topic.messages";
@Bean
public Queue queueMessage() {
return new Queue(MESSAGE);
}
@Bean
public Queue queueMessages() {
return new Queue(MESSAGES);
}
@Bean
TopicExchange exchange() {
return new TopicExchange("exchange");
}
/**
* 将队列topic.message与exchange绑定,binding_key为topic.message,就是完全匹配
* @param queueMessage
* @param exchange
* @return
*/
@Bean
Binding bindingExchangeMessage(Queue queueMessage, TopicExchange exchange) {
return BindingBuilder.bind(queueMessage).to(exchange).with("topic.message");
}
/**
* 将队列topic.messages与exchange绑定,binding_key为topic.#,模糊匹配
* @param queueMessages
* @param exchange
* @return
*/
@Bean
Binding bindingExchangeMessages(Queue queueMessages, TopicExchange exchange) {
return BindingBuilder.bind(queueMessages).to(exchange).with("topic.#");
}
}
这里配置了一个完全匹配和一个模糊匹配
2.配置消息生产者
package com.paic.producer;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* @ProjectName: rabbitmq
* @Package: com.paic.producer
* @ClassName: TopicExchangeProducer
* @Author: Administrator
* @Description: ${description}
* @Version: 1.0
*/
@Component
public class TopicExchangeProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
public void send() {
rabbitTemplate.convertAndSend("exchange", "topic.message", "topic.message");
rabbitTemplate.convertAndSend("exchange", "topic.messages", "topic.messages");
}
}
3.配置两个消息消费者
package com.paic.consumer;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
/**
* @ProjectName: rabbitmq
* @Package: com.paic.consumer
* @ClassName: MessageCustomer
* @Author: Administrator
* @Description: ${description}
* @Version: 1.0
*/
@Component
@RabbitListener(queues = "topic.message")
public class MessageCustomer {
@RabbitHandler
public void process(String msg){
System.out.println("topicexchange message 消费者 : " +msg);
}
}
@Component
@RabbitListener(queues = "topic.messages")
public class MessagesCustomer {
@RabbitHandler
public void process(String msg){
System.out.println("topicexchange messages 消费者 : " +msg);
}
}
4.创建controller
package com.paic.controller;
import com.paic.producer.TopicExchangeProducer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @ProjectName: rabbitmqproducer
* @Package: com.paic.controller
* @ClassName: TopicExchangeProducer
* @Author: Administrator
* @Description: ${description}
* @Date: 2019/6/23 17:53
* @Version: 1.0
*/
@RestController
public class TopicExchangeController {
@Autowired
private TopicExchangeProducer topicExchangeProducer;
@RequestMapping("/topicexchange")
public String topicExchange(){
topicExchangeProducer.send();
return "ok";
}
}
5.按上面方法进行测试
结果发现队列topic.messages为模糊匹配被消费了两次
4.SpringBoot整合的RabbitMq(Fanout Exchange模式)
1.老套路先来个配置类
package com.paic.config;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.FanoutExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @ProjectName: rabbitmq
* @Package: com.paic.config
* @ClassName: FanoutConfig
* @Author: Administrator
* @Description: ${description}
* @Version: 1.0
*/
@Configuration
public class FanoutConfig {
@Bean
public Queue AMessage() {
return new Queue("fanout.A");
}
@Bean
public Queue BMessage() {
return new Queue("fanout.B");
}
@Bean
public Queue CMessage() {
return new Queue("fanout.C");
}
@Bean
FanoutExchange fanoutExchange() {
return new FanoutExchange("fanoutExchange");
}
@Bean
Binding bindingExchangeA(Queue AMessage, FanoutExchange fanoutExchange) {
return BindingBuilder.bind(AMessage).to(fanoutExchange);
}
@Bean
Binding bindingExchangeB(Queue BMessage, FanoutExchange fanoutExchange) {
return BindingBuilder.bind(BMessage).to(fanoutExchange);
}
@Bean
Binding bindingExchangeC(Queue CMessage, FanoutExchange fanoutExchange) {
return BindingBuilder.bind(CMessage).to(fanoutExchange);
}
}
2.接下来是生产者
package com.paic.producer;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* @ProjectName: rabbitmq
* @Package: com.paic.producer
* @ClassName: FanoutProducer
* @Author: Administrator
* @Description: ${description}
* @Version: 1.0
*/
@Component
public class FanoutProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
public void send(){
//论证广播模式和routingkey参数无关
rabbitTemplate.convertAndSend("fanoutExchange","abcd.ee","--------------");
rabbitTemplate.convertAndSend("fanoutExchange","abcd.aa","==============");
rabbitTemplate.convertAndSend("fanoutExchange","***************");
}
}
3.再创建3个消费者
package com.paic.consumer;
/**
* @ProjectName: rabbitmq
* @Package: com.paic.consumer
* @ClassName: FanoutCustomerA
* @Author: Administrator
* @Description: ${description}
* @Version: 1.0
*/
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
/**
* Fanout Exchange 消费者
*/
@Component
@RabbitListener(queues = "fanout.A")
public class FanoutCustomerA {
@RabbitHandler
public void process(String msg){
System.out.println("FanoutReceiverA : " + msg);
}
}
@Component
@RabbitListener(queues = "fanout.B")
public class FanoutCustomerB {
@RabbitHandler
public void process(String msg){
System.out.println("FanoutReceiverB : " + msg);
}
}
@Component
@RabbitListener(queues = "fanout.C")
public class FanoutCustomerC {
@RabbitHandler
public void process(String msg){
System.out.println("FanoutReceiverC : " + msg);
}
}
4.最后是controller
package com.paic.controller;
import com.paic.producer.FanoutProducer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @ProjectName: rabbitmq
* @Package: com.paic.controller
* @ClassName: FanoutExchangeController
* @Author: Administrator
* @Description: ${description}
* @Version: 1.0
*/
@RestController
public class FanoutExchangeController {
@Autowired
private FanoutProducer fanoutProducer;
@RequestMapping("/fanoutsend")
public String fanoutSend(){
fanoutProducer.send();
return "ok";
}
}
5.测试结果
5.RabbitMq的回调函数使用
1.配置类
package com.paic.config;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
/**
* @ProjectName: rabbitmq
* @Package: com.paic.config
* @ClassName: CallBackConfig
* @Author: Administrator
* @Description: ${description}
* @Version: 1.0
*/
@Configuration
public class CallBackConfig {
final static String CALLBACK = "callback";
@Bean
public Queue callBackQueue() {
return new Queue(CALLBACK);
}
@Autowired
private ConnectionFactory connectionFactory;
@Bean
/** 因为要设置回调类,所以应是prototype类型,如果是singleton类型,则回调类为最后一次设置 */
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public RabbitTemplate rabbitTemplatenew() {
RabbitTemplate template = new RabbitTemplate(connectionFactory);
return template;
}
}
2.生产者
package com.paic.producer;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.support.CorrelationData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* @ProjectName: rabbitmq
* @Package: com.paic.producer
* @ClassName: CallBackProducer
* @Author: Administrator
* @Description: ${description}
* @Version: 1.0
*/
@Component
public class CallBackProducer implements RabbitTemplate.ConfirmCallback, RabbitTemplate.ReturnCallback {
@Autowired
private RabbitTemplate rabbitTemplate;
public void send() {
rabbitTemplate.setReturnCallback(this);
rabbitTemplate.setConfirmCallback(this);
rabbitTemplate.convertAndSend("callback", "回调函数:生产者发出的消息");
}
/**
* 发送后的回调函数
*
* @param correlationData
* @param b
* @param s
*/
@Override
public void confirm(CorrelationData correlationData, boolean b, String s) {
System.out.println("回调函数:" + "b=" + b);
}
/**
* 消息发送失败的回调函数(未测试)
*
* @param message
* @param replyCode
* @param replyText
* @param exchange
* @param routingKey
*/
@Override
public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
System.out.println("发送消息失败");
}
}
3.消费者
package com.paic.consumer;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
/**
* @ProjectName: rabbitmq
* @Package: com.paic.consumer
* @ClassName: CallBackCustomer
* @Author: Administrator
* @Description: ${description}
* @Version: 1.0
*/
@Component
public class CallBackCustomer {
@RabbitListener(queues = "callback")
@RabbitHandler
public void process(String msg){
System.out.println("回调函数-消费者:"+msg);
}
}
4.controller
package com.paic.controller;
import com.paic.producer.CallBackProducer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @ProjectName: rabbitmq
* @Package: com.paic.controller
* @ClassName: CallBackController
* @Author: Administrator
* @Description: ${description}
* @Version: 1.0
*/
@RestController
public class CallBackController {
@Autowired
private CallBackProducer callBackProducer;
@RequestMapping("/callback")
public void send(){
callBackProducer.send();
}
}
5.测试结果
更多关于rabbitmq的知识https://www.liangzl.com/get-article-detail-21195.html