转载请注明出处

0.目录

RabbitMQ-从基础到实战(1)— Hello RabbitMQ

RabbitMQ-从基础到实战(2)— 防止消息丢失

RabbitMQ-从基础到实战(3)— 消息的交换(上)

RabbitMQ-从基础到实战(4)— 消息的交换(中)

RabbitMQ-从基础到实战(5)— 消息的交换(下)

1.简介

原计划这章应该讲RabbitMQ的RPC调用的,后来想想,这个场景应该用的不多,现在比较火的微服务,要么用dubbo,要么用spring cloud,用RabbitMQ做RPC比较少见,所以就先跳过了,有需要再补充。

其实网上RabbitMQ和Spring集成的教程有不少,我也大致看了看,大部分都是言简意赅,代码配置一贴,然后就可以用了,而我希望我的教程能多和大家一起探讨一些“为什么”。

2.Spring AMQP

Spring AMQP中有两个单词,Spring都知道,那AMQP是什么?

中文意思是,高级消息队列协议,然后用蹩脚的英语猜一下,advance message queue protocol,差不多了,advance变成形容词高级的-advanced,queue变成queuing(排队论,学术一点),所以,AMQP就是Advanced Message Queuing Protocal。

AMQP 0-9-1 是RabbitMQ支持的协议之一,0-9-1是个版本号,正常情况下推荐使用,它所表现出的形式,就是前面几张介绍的内容

RabbitMQ还支持其他版本的协议,具体可以参考这里

Spring AMQP的定义如下

The Spring AMQP project applies core Spring concepts to the development of AMQP-based messaging solutions. It provides a "template" as a high-level abstraction for sending and receiving messages. It also provides support for Message-driven POJOs with a "listener container". These libraries facilitate management of AMQP resources while promoting the use of dependency injection and declarative configuration

意外的发现谷歌翻译的很通顺

Spring AMQP项目将核心Spring概念应用于基于AMQP的消息传递解决方案的开发。 它提供了一个“模板”作为发送和接收消息的高级抽象。 它还通过“侦听器容器”为消息驱动的POJO提供支持。 这些库促进AMQP资源的管理,同时促进使用依赖注入和声明性配置

这里有很多资料

3.main方法集成

先不用Spring,只在Main方法中集成Spring AMQP,方便分析。

在pom文件中加入如下配置,不需要再引入RabbitMQ的包,Spring AMQP已经包含了4.0.x的客户端

Spring AMQP now uses the new 4.0.x version of the amqp-client library provided by the RabbitMQ team. This client has auto recovery configured by default

<dependency>
<groupId>org.springframework.amqp</groupId>
<artifactId>spring-rabbit</artifactId>
<version>1.7.1.RELEASE</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.1</version>
</dependency>

新建一个类,

 package com.liyang.ticktock.rabbitmq;

 import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter; public class App
{
public static void main( String[] args ) throws InterruptedException
{
//获取一个连接工厂,用户默认是guest/guest(只能使用部署在本机的RabbitMQ)
//是Spring实现的对com.rabbitmq.client.Connection的包装
ConnectionFactory cf = new CachingConnectionFactory("localhost"); //对AMQP 0-9-1的实现
RabbitAdmin admin = new RabbitAdmin(cf);
//声明一个队列
Queue queue = new Queue("myQueue");
admin.declareQueue(queue);
//声明一个exchange
TopicExchange exchange = new TopicExchange("myExchange");
admin.declareExchange(exchange);
//绑定队列到exchange,加上routingKey foo.*
admin.declareBinding(BindingBuilder.bind(queue).to(exchange).with("foo.*")); //监听容器
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(cf);
//监听者对象
Object listener = new Object() {
@SuppressWarnings("unused")
public void handleMessage(String foo) {
System.out.println(foo);
}
};
//通过这个适配器代理listener
MessageListenerAdapter adapter = new MessageListenerAdapter(listener);
//把适配器(listener)设置给Container
container.setMessageListener(adapter);
//设置该容器监听的队列名,可以传多个,public void setQueueNames(String... queueName) {
container.setQueueNames("myQueue");
//开始监听
container.start(); //发送模版,设置上连接工厂
RabbitTemplate template = new RabbitTemplate(cf);
//发送消息
template.convertAndSend("myExchange", "foo.bar", "Hello, world!"); Thread.sleep(1000);
container.stop();
}
}

运行结果如下:

以上代码中

ConnectionFactory包装了所有物理连接信息,然后传递给RabbitAdmin创建了RabbitMQ支持协议的连接(AMQP 0-9-1);

声明队列和交换中心后,通过BindingBuilder把队列的绑定关系声明到admin上;

创建一个消息处理类,用一个适配器(MessageListenerAdapter)包装它,并注册到监听容器中,启动监听;

最后通过连接信息创建一个Rabbit模板,调用发送方法。

  这里引申出一个问题,为什么要用监听容器(SimpleMessageListenerContainer),我们点开它的outline,如下,可以看到,它是对监听这个动作的抽象,一个容器可以有多个Consumer,并且可以控制如超时时间等配置。

  

可以看出,比起直接使用RabbitMQ客户端,以上代码已经简化了一部分,最明显的部分就是,不需要手动去关Channel、Connection了,对以上概念的介绍都穿插在前几章,这里不再赘述。

这些代码用Spring的方式注入将会更加简洁

4.传统Spring方式集成

首先,POM文件中要把Spring引进来

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.7.RELEASE</version>
</dependency>

然后增加applicatioContext.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 http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/rabbit http://www.springframework.org/schema/rabbit/spring-rabbit-1.6.xsd "> <context:annotation-config/>
<context:component-scan base-package="com.liyang.ticktock.rabbitmq.listener"/> <!-- 配置ConnectionFactory -->
<rabbit:connection-factory id="connectionFactory"
host="127.0.0.1" username="guest" password="guest" port="5672" /> <!-- 等同new一个RabbitAdmin -->
<rabbit:admin connection-factory="connectionFactory" /> <!-- 声明一个队列 -->
<rabbit:queue name="myQueue" /> <!-- 声明一个topic类型的exchange,并把上面声明的队列绑定在上面,routingKey="foo.*" -->
<rabbit:topic-exchange name="myExchange">
<rabbit:bindings>
<rabbit:binding queue="myQueue" pattern="foo.*" />
<!-- 这里还可以继续绑定其他队列 -->
</rabbit:bindings>
</rabbit:topic-exchange> <!-- 声明一个rabbitTemplate,指定连接信息,发送消息到myExchange上,routingKey在程序中设置,此处的配置在程序中可以用set修改 -->
<rabbit:template id="amqpTemplate" connection-factory="connectionFactory"
exchange="myExchange"/> <!-- 配置监听容器,指定消息处理类,处理方法,还可以配置自动确认等-->
<rabbit:listener-container connection-factory="connectionFactory">
<rabbit:listener ref="myListener" method="listen" queue-names="myQueue" />
<!-- 可以继续注册监听 -->
</rabbit:listener-container> </beans>

这个配置文件中,我们使用了context的自动扫描装配,不用配bean了,还使用了rabbit的命名空间 xmlns:rabbit

这个东西可能有些童鞋不知道怎么配的,其实没什么神秘的,我们打开根路径看看里面有什么“http://www.springframework.org/schema/”

和本地目录一样,就是个存东西的地方,rabbit命名空间,在这个路径后面加上rabbit对应的目录就行了

再进入rabbit目录,发现里面是一些不同版本的xsd文件,所以,在schemaLocation中,配上使用的具体版本的xsd就可以了

言归正传,上面的配置文件,把大量原来在代码中实现的东西挪到了xml中,一目了然,方便修改。注意注释加粗的三处,现在我们可以用Spring实现我们原来用原生RabbitMQ客户端实现的所有功能了

在发送消息之前,还需要写一个类用来处理消息,并且这个类要有linsten方法,和配置文件中声明的 method="listen" 对应

 package com.liyang.ticktock.rabbitmq.listener;

 import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component; @Component
public class MyListener {
Logger logger = LoggerFactory.getLogger(MyListener.class); public void listen(String message){
logger.debug("received:"+message);
} }

剩下在java中的代码就非常简洁了,监听在Spring环境启动后就自动开始了,我们只需要发消息就行,代码如下

直接一个main方法,省的还要捉一只汤姆猫

 public static void main(String[] args) throws InterruptedException {
//启动Spring环境
AbstractApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
//假装是Autowired的
RabbitTemplate template = ctx.getBean(RabbitTemplate.class);
//设置routingKey
template.setRoutingKey("foo.bar");
//发送,exchange,routingKey什么的都配好了
template.convertAndSend("Hello, world!"); //关掉环境
Thread.sleep(1000);
ctx.destroy();
}

运行结果如下:

5.采用Spring Boot集成

不是很重要,先欠着,有空补上

6.结束语

最近实在太忙,这篇博客利用工作的碎片时间,写了有一个多星期,囧。

在写这篇系列教程的同时,我也获益良多,后面会继续为大家介绍一些RabbitMQ实用的高级特性,请多多支持

RabbitMQ-从基础到实战(6)— 与Spring集成的更多相关文章

  1. RabbitMQ-从基础到实战(3)— 消息的交换

    1.简介 在前面的例子中,每个消息都只对应一个消费者,即使有多个消费者在线,也只会有一个消费者接收并处理一条消息,这是消息中间件的一种常用方式.还有另外一种方式,生产者生产一条消息,广播给所有的消费者 ...

  2. RabbitMQ-从基础到实战(2)— 防止消息丢失

    转载请注明出处 1.简介 RabbitMQ中,消息丢失可以简单的分为两种:客户端丢失和服务端丢失.针对这两种消息丢失,RabbitMQ都给出了相应的解决方案. 2.防止客户端丢失消息 如图,生产者P向 ...

  3. RabbitMQ-从基础到实战(4)— 消息的交换(下)

    0.目录 RabbitMQ-从基础到实战(1)- Hello RabbitMQ RabbitMQ-从基础到实战(2)- 防止消息丢失 RabbitMQ-从基础到实战(3)- 消息的交换(上) 1.简介 ...

  4. RabbitMQ-从基础到实战(5)— 消息的交换(下)

    转载请注明出处 0.目录 RabbitMQ-从基础到实战(1)- Hello RabbitMQ RabbitMQ-从基础到实战(2)- 防止消息丢失 RabbitMQ-从基础到实战(3)- 消息的交换 ...

  5. RabbitMQ-从基础到实战(3)— 消息的交换(上)

    转载请注明出处 0.目录 RabbitMQ-从基础到实战(1)— Hello RabbitMQ RabbitMQ-从基础到实战(2)— 防止消息丢失 RabbitMQ-从基础到实战(4)— 消息的交换 ...

  6. rabbitMQ第五篇:Spring集成RabbitMQ

    前面几篇讲解了如何使用rabbitMq,这一篇主要讲解spring集成rabbitmq. 首先引入配置文件org.springframework.amqp,如下 <dependency> ...

  7. RabbitMQ第四篇:Spring集成RabbitMQ

    前面几篇讲解了如何使用rabbitMq,这一篇主要讲解spring集成rabbitmq. 首先引入配置文件org.springframework.amqp,如下 <dependency> ...

  8. RabbitMQ-从基础到实战(1)— Hello RabbitMQ

    转载请注明出处 1.简介 本篇博文介绍了在windows平台下安装RabbitMQ Server端,并用JAVA代码实现收发消息 2.安装RabbitMQ RabbitMQ是用Erlang开发的,所以 ...

  9. C# RabbitMQ延迟队列功能实战项目演练

    一.需求背景 当用户在商城上进行下单支付,我们假设如果8小时没有进行支付,那么就后台自动对该笔交易的状态修改为订单关闭取消,同时给用户发送一份邮件提醒.那么我们应用程序如何实现这样的需求场景呢?在之前 ...

随机推荐

  1. Html5与CSS3权威指南 百度云下载

    Html5与CSS3权威指南 百度云下载 链接:http://pan.baidu.com/s/1hq6Dlvm 密码:php3

  2. windows 2003装.net 4.0时提示 WIC windows Imaging Component

    运行此安装程序之前,必须安装32位windows映像处理组件(WIC) WIC windows Imaging Component下载地址: http://download.microsoft.com ...

  3. 存储可靠性技术之 --RAID

    云计算项目交付时,不可避免的需要考虑存储磁盘采用何种RAID.例如:我们的项目工程师可能会建议大家连接克隆虚拟机系统盘组RAID 10,完整复制虚拟机数据盘 使用RAID5或者RAID6等,那么RAI ...

  4. 第八讲:I/O虚拟化

    一.I/O虚拟化的产生 服务器单个千兆以太网端口肯定能够支持单个应用,但是当被分割为10个.15个或者更多的服务器负载时(这其中包括网络.存储以及服务器之间的流量)可能就不够用了. 当遇到I/O瓶颈时 ...

  5. 每天一个linux命令(43)--netstat命令

    netstat 命令用于显示与 IP TCP  UDP 和 ICMP协议相关的统计数据,一般用于检验本机各端口的网络连接情况.netstat 是在内核中访问网络及相关信息的程序,它能提供TCP连接,T ...

  6. c#基础——for循环嵌套经典练习题(打★)

    using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace 作业题1 ...

  7. 关于Dapper.NET的相关论述

    年少时,为何不为自己的梦想去拼搏一次呢?纵使头破血流,也不悔有那年少轻狂.感慨很多,最近事情也很多,博客也很少更新了,毕竟每个人都需要为自己的生活去努力. 最近在一个群里遇到一个人说的话,在这里不再赘 ...

  8. 1113: [Poi2008]海报PLA

    1113: [Poi2008]海报PLA Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 765  Solved: 466[Submit][Status ...

  9. 1707: [Usaco2007 Nov]tanning分配防晒霜

    1707: [Usaco2007 Nov]tanning分配防晒霜 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 548  Solved: 262[Sub ...

  10. JSP +++SERVIET总复习

    一. JSP基础概念 软件架构 B/S架构:Browser/Server,浏览器-服务器 最大的优点就是:一次部署,处处访问. C/S架构:Client/Server,客户端-服务器 功能.事件丰富, ...