基于java使用RabbitMQ

框架:SpringBoot1.5.14.RELEASE

maven依赖:

<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
<version>3.6.5</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>

本文只是操作原生RabbitMQ,并没有和SpringBoot进行整合,后面介绍整合,基于注解使用

一、quick start

1.1、Consumer

public static void main(String[] args) throws Exception{
//1 创建一个ConnectionFactory, 并进行配置
ConnectionFactory factory = new ConnectionFactory();
factory.setVirtualHost("/");
factory.setHost("139.196.75.238");
factory.setPort(5672);
//2 通过连接工厂创建连接
Connection connection = factory.newConnection();
//3 通过connection创建一个Channel
Channel channel = connection.createChannel(); //4 声明(创建)一个队列
channel.queueDeclare("test002", true, false, false, null); //5 创建消费者
QueueingConsumer queueingConsumer = new QueueingConsumer(channel); //6 设置Channel
channel.basicConsume("test002", true, queueingConsumer); while(true){
//7 获取消息
QueueingConsumer.Delivery delivery = queueingConsumer.nextDelivery();
String msg = new String(delivery.getBody());
log.info(msg);
}
}
}

Consumer

参数解释:

  durable:是否持久化,Durable:是,即使服务器重启,这个队列也不会消失,Transient:否

  exclusive:这个queue只能由一个exchange监听restricted to this connection,使用场景:顺序消费

  autoDelete:当最后一个Binding到Exchange的Queue删除之后,自动删除该Exchange

  arguments:参数

  autoACK:是否自动签收,对应着手动签收

1.2、Producer

public class Producer {

    public static void main(String[] args) throws Exception{
//1 创建一个ConnectionFactory, 并进行配置
ConnectionFactory factory = new ConnectionFactory();
factory.setVirtualHost("/");
factory.setHost("139.196.75.238");
factory.setPort(5672);
//2 通过连接工厂创建连接
Connection connection = factory.newConnection();
//3 通过connection创建一个Channel
Channel channel = connection.createChannel();
//4 通过Channel发送数据
for(int i=0; i < 5; i++){
String msg = "Hello RabbitMQ!";
//1 exchange 2 routingKey
channel.basicPublish("", "test002", null, msg.getBytes());
}
//5 关闭相关的连接
channel.close();
factory.clone();
}
}

Producer

参数解释:

  exchange name:

  routingKey:路由规则

  BasicProperties:

  body:message中的body

结果:

17:43:49.351 [main] INFO com.it.quickstart.Consumer - Hello RabbitMQ!
17:43:49.351 [main] INFO com.it.quickstart.Consumer - Hello RabbitMQ!
17:43:49.351 [main] INFO com.it.quickstart.Consumer - Hello RabbitMQ!
17:43:49.351 [main] INFO com.it.quickstart.Consumer - Hello RabbitMQ!
17:43:49.351 [main] INFO com.it.quickstart.Consumer - Hello RabbitMQ!

  我们使用RabbitMQ,需要首先在可视化界面确定queue,exchange是否创建,对应关系是否正常,这是一个大前提

1.3、自定义消费者

  之前接收message,通过while(true),感觉太low了,RabbitMQ支持实现自定义消费者,只需要集成DefaultConsumer,重写handlerDelivery,

构造器

public class MyConsumer extends DefaultConsumer {
public MyConsumer(Channel channel) {
super(channel);
} @Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.err.println("-----------consume message----------");
System.err.println("consumerTag: " + consumerTag);
System.err.println("envelope: " + envelope);
System.err.println("properties: " + properties);
System.err.println("body: " + new String(body));
}
}

MyConsumer

而consumer只需要修改

//5 创建消费者
QueueingConsumer queueingConsumer = new QueueingConsumer(channel); //去掉这一步
//6 设置Channel
channel.basicConsume("test002", true, new MyConsumer(channel));

结果:

-----------consume message----------
consumerTag: amq.ctag-YK7CnvWxTpm6hmuyUyqSkQ
envelope: Envelope(deliveryTag=1, redeliver=false, exchange=, routingKey=test002)
properties: #contentHeader<basic>(content-type=null, content-encoding=null, headers=null, delivery-mode=null, priority=null, correlation-id=null, reply-to=null, expiration=null, message-id=null, timestamp=null, type=null, user-id=null, app-id=null, cluster-id=null)
body: Hello RabbitMQ By MyConsumer!

二、Exchange

  Exchange有四种方式Fanout、Direct、Topic、Headers,而我们上面的例子,并没有定义Exchange,RabbitMQ默认使用AMQP default,

要求routing key和queue name相同

  本文只是介绍前三种,Headers几乎用不到

2.1、Fanout

fanout效率是最好的,不需要routing key,你可以随便设置都无所谓,只要consumer和producer的Exchange name相同

producer

public class Producer {

    public static void main(String[] args) throws Exception{
ConnectionFactory factory = new ConnectionFactory();
factory.setVirtualHost("/");
factory.setHost("139.196.75.238");
factory.setPort(5672); Connection connection = factory.newConnection();
Channel channel = connection.createChannel(); String exchangeName = "exchange_fanout";
channel.basicPublish(exchangeName, "", null, "send message by fanout".getBytes());
}
}

Producer Fanout

consumer

public class Consumer {

    public static void main(String[] args) throws Exception{
ConnectionFactory factory = new ConnectionFactory();
factory.setVirtualHost("/");
factory.setHost("139.196.75.238");
factory.setPort(5672); factory.setAutomaticRecoveryEnabled(true);
factory.setNetworkRecoveryInterval(3000); Connection connection = factory.newConnection();
Channel channel = connection.createChannel(); String exchangeName = "exchange_fanout";
String exchangeType = "fanout";
String queueName = "queue_fanout";
String routingKey = ""; //不设置路由键 channel.exchangeDeclare(exchangeName, exchangeType, true, false, false, null);
channel.queueDeclare(queueName, true, false, false, null);
channel.queueBind(queueName, exchangeName, routingKey); channel.basicConsume(queueName, true, new MyConsumer(channel));
}
}

Consumer Fanout

结果:

-----------consume message----------
consumerTag: amq.ctag-rXw7SbaR5aWVMQxZY6SfEA
envelope: Envelope(deliveryTag=1, redeliver=false, exchange=exchange_fanout, routingKey=)
properties: #contentHeader<basic>(content-type=null, content-encoding=null, headers=null, delivery-mode=null, priority=null, correlation-id=null, reply-to=null, expiration=null, message-id=null, timestamp=null, type=null, user-id=null, app-id=null, cluster-id=null)
body: send message by fanout

我们声明queue和exchange之后,要先观察exchange和queue对应关系

点击exchange name,进去查看是否binding成功,如果成功如下图

注意点:

  1、fanout模式下不是直接操作Queue,而是把消息发送给Exchange,由Exchange把消息分发给与之绑定的Queue,也就是广播模式

  2、Queue必须和Exchange进行绑定

  3、每个Consumer的Queue name不能相同,个人测试下,相同的Queue name,只能有一个Consumer收到消息

2.2、Direct

  完全把代码贴出来太浪费篇幅了,而且毫无意思,后面只说一下区别,顺便说一下,对于queue和exchange的declare无论放到producer还是

Consumer都可以的,个人习惯Consumer,而且二者启动顺序没有要求,因为RabbitMQ的消息具有堆积功能

Producer:

 String exchangeName = "exchange_direct";
String routingKey = "key.direct"; channel.basicPublish(exchangeName, routingKey, null, "send message by direct".getBytes());

Consumer:

String exchangeName = "exchange_direct";
String exchangeType = "direct";
String queueName = "queue_direct";
String routingKey = "key.direct"; channel.exchangeDeclare(exchangeName, exchangeType, true, false, false, null);
channel.queueDeclare(queueName, true, false, false, null);
channel.queueBind(queueName, exchangeName, routingKey); channel.basicConsume(queueName, true, new MyConsumer(channel));

结果:

-----------consume message----------
consumerTag: amq.ctag-6UeNiGs1K-gMWbwvVn8F5A
envelope: Envelope(deliveryTag=1, redeliver=false, exchange=exchange_direct, routingKey=key.direct)
properties: #contentHeader<basic>(content-type=null, content-encoding=null, headers=null, delivery-mode=null, priority=null, correlation-id=null, reply-to=null, expiration=null, message-id=null, timestamp=null, type=null, user-id=null, app-id=null, cluster-id=null)
body: send message by direct

说明:

Direct要求routingKey完全一致

2.3、 topic

Producer:

String exchangeName = "exchange_topic";
String routingKey1 = "user.save";
String routingKey2 = "user.update";
String routingKey3 = "user.delete.abc";
//5 发送 String msg = "Send Message By topic";
channel.basicPublish(exchangeName, routingKey1 , null , msg.getBytes());
channel.basicPublish(exchangeName, routingKey2 , null , msg.getBytes());
channel.basicPublish(exchangeName, routingKey3 , null , msg.getBytes());

Consumer:

String exchangeName = "exchange_topic";
String exchangeType = "topic";
String queueName = "queue_topic";
String routingKey = "user.*"; channel.exchangeDeclare(exchangeName, exchangeType, true, false, false, null);
channel.queueDeclare(queueName, true, false, false, null);
channel.queueBind(queueName, exchangeName, routingKey);

说明:

  Topic支持通配符匹配,#匹配一个或多个单词,*匹配一个单词

RabbitMQ系列(三)--Java API的更多相关文章

  1. Kafka系列三 java API操作

    使用java API操作kafka 1.pom.xml <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xs ...

  2. Apache Kafka系列(三) Java API使用

    Apache Kafka系列(一) 起步 Apache Kafka系列(二) 命令行工具(CLI) Apache Kafka系列(三) Java API使用 摘要: Apache Kafka Java ...

  3. rabbitmq系列三 之发布/订阅

    1.发布/订阅 在上篇教程中,我们搭建了一个工作队列,每个任务只分发给一个工作者(worker).在本篇教程中,我们要做的跟之前完全不一样 —— 分发一个消息给多个消费者(consumers).这种模 ...

  4. jvm系列(三):java GC算法 垃圾收集器

    GC算法 垃圾收集器 概述 垃圾收集 Garbage Collection 通常被称为“GC”,它诞生于1960年 MIT 的 Lisp 语言,经过半个多世纪,目前已经十分成熟了. jvm 中,程序计 ...

  5. 消息中间件系列之Java API操作ActiveMQ

    一.依赖 <dependency> <groupId>org.apache.activemq</groupId> <artifactId>activem ...

  6. 消息中间件系列三:使用RabbitMq原生Java客户端进行消息通信(消费者(接收方)自动确认模式、消费者(接收方)自行确认模式、生产者(发送方)确认模式)

    准备工作: 1)安装RabbitMQ,参考文章:消息中间件系列二:RabbitMQ入门(基本概念.RabbitMQ的安装和运行) 2.)分别新建名为OriginalRabbitMQProducer和O ...

  7. Hadoop 系列(三)Java API

    Hadoop 系列(三)Java API <dependency> <groupId>org.apache.hadoop</groupId> <artifac ...

  8. Redis总结(五)缓存雪崩和缓存穿透等问题 Web API系列(三)统一异常处理 C#总结(一)AutoResetEvent的使用介绍(用AutoResetEvent实现同步) C#总结(二)事件Event 介绍总结 C#总结(三)DataGridView增加全选列 Web API系列(二)接口安全和参数校验 RabbitMQ学习系列(六): RabbitMQ 高可用集群

    Redis总结(五)缓存雪崩和缓存穿透等问题   前面讲过一些redis 缓存的使用和数据持久化.感兴趣的朋友可以看看之前的文章,http://www.cnblogs.com/zhangweizhon ...

  9. ElasticSearch实战系列三: ElasticSearch的JAVA API使用教程

    前言 在上一篇中介绍了ElasticSearch实战系列二: ElasticSearch的DSL语句使用教程---图文详解,本篇文章就来讲解下 ElasticSearch 6.x官方Java API的 ...

随机推荐

  1. java.io.IOException: read failed, socket might closed or timeout, read ret: -1

    近期项目中连接蓝牙之后接收蓝牙设备发出的指令功能,在连接设备之后,创建RfcommSocket连接时候报java.io.IOException: read failed, socket might c ...

  2. [DLX反复覆盖] poj 1084 Square Destroyer

    题意: n*n的矩形阵(n<=5),由2*n*(n+1)根火柴构成,那么当中会有非常多诸如边长为1,为2...为n的正方形,如今能够拿走一些火柴,那么就会有一些正方形被破坏掉. 求在已经拿走一些 ...

  3. Codeforces(429D - Tricky Function)近期点对问题

    D. Tricky Function time limit per test 2 seconds memory limit per test 256 megabytes input standard ...

  4. jQuery通过地址获取经纬度demo

    在开始之前,首先需要登录百度地图API控制台申请密钥ak. 1.登录百度地图开放平台http://lbsyun.baidu.com 注册账号,完善信息,点击网站右上角的“API控制台”,点击,创建应用 ...

  5. String,StringBuffer,StringBuilder三者有什么异同?

    相同点: 1.三者都是Java平台提供的三种类型得到字符串,它们可以储存和操作字符串. 不同点: 1.String是final修饰的,也就意味着String引用的字符串内容是不能被改变的.而Strin ...

  6. [Android 编译(一)] Ubuntu 16.04 LTS 成功编译 Android 6.0 源码教程

    本文转载自:[Android 编译(一)] Ubuntu 16.04 LTS 成功编译 Android 6.0 源码教程 1 前言 经过3天奋战,终于在Ubuntu 16.04上把Android 6. ...

  7. Odoo免费开源企业信息化平台助力企业成功

    企业信息化变革之路 信息孤岛的真实由来 打开百度App,看更多图片 左边为当下企业现状,右边为Odoo的整体 企业信息孤岛的严重性,来自于企业的自身高速发展,企业以销售为生命主题围绕着客户会搭建一系列 ...

  8. 整数类型c++

    数据类型 定义标识符 占字节数 数值范围 数值范围 短整型 short [int] 2(16位) -32768-32767 -215-215-1 整型 [long] int 4(32位) -21474 ...

  9. [GDOI2014]拯救莫莉斯

    题目描述 莫莉斯·乔是圣域里一个叱咤风云的人物,他凭借着自身超强的经济头脑,牢牢控制了圣域的石油市场. 圣域的地图可以看成是一个n*m的矩阵.每个整数坐标点(x , y)表示一座城市吗,两座城市间相邻 ...

  10. 贪心 FZU 2013 A short problem

    题目传送门 /* 题意:取长度不小于m的序列使得和最大 贪心:先来一个前缀和,只要长度不小于m,从m开始,更新起点k最小值和ans最大值 */ #include <cstdio> #inc ...