RabbitMQ简介

RabbitMQ是一个在AMQP基础上完整的,可复用的企业消息系统 
MQ全称为Message Queue, 消息队列(MQ)是一种应用程序对应用程序的通信方法。应用程序通过读写出入队列的消息(针对应用程序的数据)来通信,而无需专用连接来链接它们。消息传递指的是程序之间通过在消息中发送数据进行通信,而不是通过直接调用彼此来通信,直接调用通常是用于诸如远程过程调用的技术。排队指的是应用程序通过 队列来通信。队列的使用除去了接收和发送应用程序同时执行的要求。

AMQP就是一个协议,是一个高级抽象层消息通信协议。

虽然在同步消息通讯的世界里有很多公开标准(如 COBAR的 IIOP ,或者是 SOAP 等),但是在异步消息处理中却不是这样,只有大企业有一些商业实现(如微软的 MSMQ ,IBM 的 Websphere MQ 等),因此,在 2006 年的 6 月,Cisco 、Redhat、iMatix 等联合制定了 AMQP 的公开标准。也就是说AMQP是异步通讯的一个协议。

RabbitMQ使用场景

在项目中,将一些无需即时返回且耗时的操作提取出来,进行了异步处理,而这种异步处理的方式大大的节省了服务器的请求响应时间,从而提高了系统的吞吐量。不过大多数不仅仅是无需即时返回,甚至是执行是否成功都无所谓。如果需要即时返回则可以使用Dubbo,Spring boot与Dubbo集成可以去看Spring boot 集成Dubbox

RabbitMQ依赖

RabbitMQ并不是直接一个简单的jar包(Jar包只是提供一个基本的与RabbitMQ本身通讯的一些功能),和Dubbo相同,RabbitMQ也需要其他软件来运行,以下是RabbitMQ运行所需要的软件

1、Erlang

由于RabbitMQ软件本身是基于Erlang开发的,所以想要运行RabbitMQ必须要先按照Erlang

Erlang官网

Erlang下载地址

RabbitMQ

RabbitMQ才是实现消息队列的核心 
RabbitMQ官网

RabbitMQ下载

配置RabbitMQ

安装完成后,需要完成一些配置才能使用RabbitMQ,可以直接用cmd到RabbitMQ的安装目录下的sbin目录通过命令配置,也可以直接在开始菜单中直接找到RabbitMQ Command Prompt (sbin dir)运行直接到达RabbitMQ的安装目录的sbin,为了方便,我们先启用管理插件,执行命令

  1. rabbitmq-plugins.bat enable rabbitmq_management

即可,注意,这是在Windows下面,如果是Linux则没有bat后缀 然后我们添加一个用户,因为在外网环境没有用户的情况下是不能连接成功的,执行添加用户命令

  1. rabbitmqctl.bat add_user springboot password

springboot是用户名,password是密码 
然后为了方便演示,我们给springboot赋予管理员权限,方便登录管理页面

  1. rabbitmqctl.bat set_user_tags springboot administrator

给账号赋予虚拟主机权限

  1. rabbitmqctl.bat set_permissions -p / springboot .* .* .*

然后启动RabbitMQ服务 访问RabbitMQ管理页面http://localhost:15672即可看见登录页面,如果没有创建用户则可以用guest,guest登录,如果有创建用户则用创建的用户登录

创建Springboot项目

因为创建spring boot项目在前面的文章已经说过很多次了,所以这里就不多说了,如果不会可以去看其他关于spring boot的博客

添加RabbitMQ相关依赖

  1. <!-- rabbitmq -->
  2. <dependency>
  3. <groupId>org.springframework.boot</groupId>
  4. <artifactId>spring-boot-starter-amqp</artifactId>
  5. </dependency>

每错,就是点配置,不过这样可能有点不理解,我还是把全部配置贴出来吧

  1. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  2. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  3. <modelVersion>4.0.0</modelVersion>
  4. <groupId>wang.raye.rabbitmq</groupId>
  5. <artifactId>demo1</artifactId>
  6. <version>0.0.1-SNAPSHOT</version>
  7. <packaging>jar</packaging>
  8. <name>demo1</name>
  9. <url>http://maven.apache.org</url>
  10. <properties>
  11. <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  12. </properties>
  13. <parent>
  14. <groupId>org.springframework.boot</groupId>
  15. <artifactId>spring-boot-starter-parent</artifactId>
  16. <version>1.4.0.RELEASE</version>
  17. </parent>
  18. <dependencies>
  19. <dependency>
  20. <groupId>junit</groupId>
  21. <artifactId>junit</artifactId>
  22. <version>3.8.1</version>
  23. <scope>test</scope>
  24. </dependency>
  25. <!-- Springboot -->
  26. <dependency>
  27. <groupId>org.springframework.boot</groupId>
  28. <artifactId>spring-boot-starter-web</artifactId>
  29. </dependency>
  30. <!-- rabbitmq -->
  31. <dependency>
  32. <groupId>org.springframework.boot</groupId>
  33. <artifactId>spring-boot-starter-amqp</artifactId>
  34. </dependency>
  35. </dependencies>
  36. </project>

因为没有做其他操作,所以目前项目主要是依赖2个模块,一个Sprig boot,一个RabbitMQ

添加配置类

  1. package wang.raye.rabbitmq.demo1;
  2. import org.springframework.amqp.core.AcknowledgeMode;
  3. import org.springframework.amqp.core.Binding;
  4. import org.springframework.amqp.core.BindingBuilder;
  5. import org.springframework.amqp.core.DirectExchange;
  6. import org.springframework.amqp.core.Message;
  7. import org.springframework.amqp.core.Queue;
  8. import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
  9. import org.springframework.amqp.rabbit.connection.ConnectionFactory;
  10. import org.springframework.amqp.rabbit.core.ChannelAwareMessageListener;
  11. import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
  12. import org.springframework.context.annotation.Bean;
  13. import org.springframework.context.annotation.Configuration;
  14. /**
  15. * rabbitmq 的配置类
  16. *
  17. * @author Raye
  18. * @since 2016年10月12日10:57:44
  19. */
  20. @Configuration
  21. public class RabbitMQConfig {
  22. /** 消息交换机的名字*/
  23. public static final String EXCHANGE = "my-mq-exchange";
  24. /** 队列key1*/
  25. public static final String ROUTINGKEY1 = "queue_one_key1";
  26. /** 队列key2*/
  27. public static final String ROUTINGKEY2 = "queue_one_key2";
  28. /**
  29. * 配置链接信息
  30. * @return
  31. */
  32. @Bean
  33. public ConnectionFactory connectionFactory() {
  34. CachingConnectionFactory connectionFactory = new CachingConnectionFactory("127.0.0.1",5672);
  35. connectionFactory.setUsername("springboot");
  36. connectionFactory.setPassword("password");
  37. connectionFactory.setVirtualHost("/");
  38. connectionFactory.setPublisherConfirms(true); // 必须要设置
  39. return connectionFactory;
  40. }
  41. /**
  42. * 配置消息交换机
  43. * 针对消费者配置
  44. FanoutExchange: 将消息分发到所有的绑定队列,无routingkey的概念
  45. HeadersExchange :通过添加属性key-value匹配
  46. DirectExchange:按照routingkey分发到指定队列
  47. TopicExchange:多关键字匹配
  48. */
  49. @Bean
  50. public DirectExchange defaultExchange() {
  51. return new DirectExchange(EXCHANGE, true, false);
  52. }
  53. /**
  54. * 配置消息队列1
  55. * 针对消费者配置
  56. * @return
  57. */
  58. @Bean
  59. public Queue queue() {
  60. return new Queue("queue_one", true); //队列持久
  61. }
  62. /**
  63. * 将消息队列1与交换机绑定
  64. * 针对消费者配置
  65. * @return
  66. */
  67. @Bean
  68. public Binding binding() {
  69. return BindingBuilder.bind(queue()).to(defaultExchange()).with(RabbitMQConfig.ROUTINGKEY1);
  70. }
  71. /**
  72. * 配置消息队列2
  73. * 针对消费者配置
  74. * @return
  75. */
  76. @Bean
  77. public Queue queue1() {
  78. return new Queue("queue_one1", true); //队列持久
  79. }
  80. /**
  81. * 将消息队列2与交换机绑定
  82. * 针对消费者配置
  83. * @return
  84. */
  85. @Bean
  86. public Binding binding1() {
  87. return BindingBuilder.bind(queue1()).to(defaultExchange()).with(RabbitMQConfig.ROUTINGKEY2);
  88. }
  89. /**
  90. * 接受消息的监听,这个监听会接受消息队列1的消息
  91. * 针对消费者配置
  92. * @return
  93. */
  94. @Bean
  95. public SimpleMessageListenerContainer messageContainer() {
  96. SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory());
  97. container.setQueues(queue());
  98. container.setExposeListenerChannel(true);
  99. container.setMaxConcurrentConsumers(1);
  100. container.setConcurrentConsumers(1);
  101. container.setAcknowledgeMode(AcknowledgeMode.MANUAL); //设置确认模式手工确认
  102. container.setMessageListener(new ChannelAwareMessageListener() {
  103. public void onMessage(Message message, com.rabbitmq.client.Channel channel) throws Exception {
  104. byte[] body = message.getBody();
  105. System.out.println("收到消息 : " + new String(body));
  106. channel.basicAck(message.getMessageProperties().getDeliveryTag(), false); //确认消息成功消费
  107. }
  108. });
  109. return container;
  110. }
  111. /**
  112. * 接受消息的监听,这个监听会接受消息队列1的消息
  113. * 针对消费者配置
  114. * @return
  115. */
  116. @Bean
  117. public SimpleMessageListenerContainer messageContainer2() {
  118. SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory());
  119. container.setQueues(queue1());
  120. container.setExposeListenerChannel(true);
  121. container.setMaxConcurrentConsumers(1);
  122. container.setConcurrentConsumers(1);
  123. container.setAcknowledgeMode(AcknowledgeMode.MANUAL); //设置确认模式手工确认
  124. container.setMessageListener(new ChannelAwareMessageListener() {
  125. public void onMessage(Message message, com.rabbitmq.client.Channel channel) throws Exception {
  126. byte[] body = message.getBody();
  127. System.out.println("queue1 收到消息 : " + new String(body));
  128. channel.basicAck(message.getMessageProperties().getDeliveryTag(), false); //确认消息成功消费
  129. }
  130. });
  131. return container;
  132. }
  133. }

注意,为了更好的展示如何配置,我配置了2个消息队列,而本类除了链接配置哪里,其他都是针对消息消费者的,当然不管消息消费者和消息生产者都需要配置链接信息,而为了方便,所以本项目的消息消费者和生产者都在本项目,一般实际项目中不会在同一项目,由于注释很详细,我就不多说了

发送消息

为了方便发送消息,所以我直接写了一个Controller,通过访问接口的形式来调用发送消息的方法,话不多说,上代码

  1. package wang.raye.rabbitmq.demo1;
  2. import java.util.UUID;
  3. import org.springframework.amqp.rabbit.core.RabbitTemplate;
  4. import org.springframework.amqp.rabbit.support.CorrelationData;
  5. import org.springframework.web.bind.annotation.RequestMapping;
  6. import org.springframework.web.bind.annotation.RestController;
  7. /**
  8. * 测试RabbitMQ发送消息的Controller
  9. * @author Raye
  10. *
  11. */
  12. @RestController
  13. public class SendController implements RabbitTemplate.ConfirmCallback{
  14. private RabbitTemplate rabbitTemplate;
  15. /**
  16. * 配置发送消息的rabbitTemplate,因为是构造方法,所以不用注解Spring也会自动注入(应该是新版本的特性)
  17. * @param rabbitTemplate
  18. */
  19. public SendController(RabbitTemplate rabbitTemplate){
  20. this.rabbitTemplate = rabbitTemplate;
  21. //设置消费回调
  22. this.rabbitTemplate.setConfirmCallback(this);
  23. }
  24. /**
  25. * 向消息队列1中发送消息
  26. * @param msg
  27. * @return
  28. */
  29. @RequestMapping("send1")
  30. public String send1(String msg){
  31. String uuid = UUID.randomUUID().toString();
  32. CorrelationData correlationId = new CorrelationData(uuid);
  33. rabbitTemplate.convertAndSend(RabbitMQConfig.EXCHANGE, RabbitMQConfig.ROUTINGKEY1, msg,
  34. correlationId);
  35. return null;
  36. }
  37. /**
  38. * 向消息队列2中发送消息
  39. * @param msg
  40. * @return
  41. */
  42. @RequestMapping("send2")
  43. public String send2(String msg){
  44. String uuid = UUID.randomUUID().toString();
  45. CorrelationData correlationId = new CorrelationData(uuid);
  46. rabbitTemplate.convertAndSend(RabbitMQConfig.EXCHANGE, RabbitMQConfig.ROUTINGKEY2, msg,
  47. correlationId);
  48. return null;
  49. }
  50. /**
  51. * 消息的回调,主要是实现RabbitTemplate.ConfirmCallback接口
  52. * 注意,消息回调只能代表成功消息发送到RabbitMQ服务器,不能代表消息被成功处理和接受
  53. */
  54. public void confirm(CorrelationData correlationData, boolean ack, String cause) {
  55. System.out.println(" 回调id:" + correlationData);
  56. if (ack) {
  57. System.out.println("消息成功消费");
  58. } else {
  59. System.out.println("消息消费失败:" + cause+"\n重新发送");
  60. }
  61. }
  62. }

需要注意的是消息回调只能代表消息成功发送到RabbitMQ服务器

然后我们启动项目,访问http://localhost:8082/send1?msg=aaaa 会发现控制台输出了

  1. 收到消息 : aaaa
  2. 回调id:CorrelationData [id=37e6e913-835a-4eca-98d1-807325c5900f]
  3. 消息成功消费

当然回调id可能不同,如果我们访问http://localhost:8082/send2?msg=bbbb 则输出

  1. queue1 收到消息 : bbbb
  2. 回调id:CorrelationData [id=0cec7500-3117-4aa2-9ea5-4790879812d4]
  3. 消息成功消费

最后说两句

因为本文主要是说明如何从零到springboot集成RabbitMQ,所以对于RabbitMQ的很多信息和用法没有说明,如果对RabbitMQ本身不太熟悉的可以去看看其他关于RabbitMQ的文章,附上本文demo

Spring boot集成RabbitMQ(山东数漫江湖)的更多相关文章

  1. Spring Boot 集成 RabbitMQ 实战

    Spring Boot 集成 RabbitMQ 实战 特别说明: 本文主要参考了程序员 DD 的博客文章<Spring Boot中使用RabbitMQ>,在此向原作者表示感谢. Mac 上 ...

  2. 85. Spring Boot集成RabbitMQ【从零开始学Spring Boot】

    这一节我们介绍下Spring Boot整合RabbitMQ,对于RabbitMQ这里不过多的介绍,大家可以参考网络上的资源进行安装配置,本节重点是告诉大家如何在Spring Boot中使用Rabbit ...

  3. RabbitMQ(3) Spring boot集成RabbitMQ

    springboot集成RabbitMQ非常简单,如果只是简单的使用配置非常少,springboot提供了spring-boot-starter-amqp项目对消息各种支持. 资源代码:练习用的代码. ...

  4. spring boot集成RabbitMQ

    原文:https://www.jianshu.com/p/e1258c004314 RabbitMQ作为AMQP的代表性产品,在项目中大量使用.结合现在主流的spring boot,极大简化了开发过程 ...

  5. Spring Boot 集成RabbitMQ

    在Spring Boot中整合RabbitMQ是非常容易的,通过在Spring Boot应用中整合RabbitMQ,实现一个简单的发送.接收消息的例子. 首先需要启动RabbitMQ服务,并且add一 ...

  6. spring boot 集成 rabbitmq 指南

    先决条件 rabbitmq server 安装参考 一个添加了 web 依赖的 spring boot 项目 我的版本是 2.5.2 添加 maven 依赖 <dependency> &l ...

  7. spring boot 集成 rabbitmq

    1.使用默认的AmqpTemplate生产消费pojo时,pojo需要implement Serializable,否则会抛出org.springframework.amqp.AmqpExceptio ...

  8. Spring 事务管理(山东数漫江湖)

    最新又重新学习了一遍Spring的事务,这里做点总结,不做如何一步步配置的流水账. 1. 关键类 public interface PlatformTransactionManager { Trans ...

  9. Spring归纳小结(山东数漫江湖)

    前言 如果说有什么框架是Java程序员必然会学习.使用到的,那么Spring肯定是其中之一.本篇博客,将根据博主在日常工作中对Spring的使用做一个系统的归纳小结. Spring的一些概念和思想 S ...

随机推荐

  1. ubuntu下修改MySQL的配置文件my.cnf

    先sudo su转换成root,再用cd转到/etc/MySQL目录下,用chmod修改权限(chmod 755 my.cnf),但这样还不能修改,再用vi命令(vi my.cnf),通过上下方向键将 ...

  2. node必学的Hello World实现--服务器实现

    node是JavaScript运行在后端的一种实现.而后端语言,不管是php,java都需要一个服务器才能跑起来,node如是. node的服务器较php而言,少了单独安装服务器的步骤,node的服务 ...

  3. djano modles values+ajax实现无页面刷新更新数据

    做项目的过程中想通过不刷新页面的方式来进行页面数据刷新,开始使用http://www.cnblogs.com/ianduin/p/7761400.html方式将查询结果数据进行序列化.发现可以行,但是 ...

  4. Chrome 的扩展功能

    chrome浏览器修改cookie edit this cookie chrome插件是一款专为谷歌内核浏览器打造的cookie插件,安装谷歌浏览器edit this cookie插件后你就可以在浏览 ...

  5. docker配置网络

    1.暂停服务,删除旧网桥#service docker stop#ip link set dev docker0 down#brctl delbr docker0 2.创建新网桥bridge0#brc ...

  6. jCanvaScript canvas的操作库

    在jcscript.com上下载最新的jCanvaScript.1.5.18.min.js文件  里面有很多关于canvas的方法都已经是封装好了的,只需直接调用,但是要注意调用之前和调用之后都要写: ...

  7. 小程序出现 “2 not found” 解决方案

    今天新建小程序的时候出现 ,控制台出现“2 not found” 报错. 解决方法: 在控制台输入  openVendor()  , 然后会弹出开发工具的文件夹,删除掉下图这两个程序,重启开发工具就可 ...

  8. 按照list中实体类的某一属性排序

    传进一个装有实体类的list public void sort(List<MedicalPracticesDetail> mpdList){ Collections.sort(mpdLis ...

  9. RT-thread内核之线程内核对象

    在RT-Thread实时操作系统中,任务采用了线程来实现,线程是RT-Thread中最基本的调度单位,它描述了一个任务执行的上下文关系,也描述了这个任务所处的优先等级.重要的任务能拥有相对较高的优先级 ...

  10. BZOJ4300 绝世好题(动态规划)

    设f[i][j]为前i个数中所选择的最后一个数在第j位上为1时的最长序列长度,转移显然. #include<iostream> #include<cstdio> #includ ...