消息队列---RabbitMQ深入研究(含Springboot+RabbitMQ整合)

RabbitMQ的基本结构:

在这里插入图片描述

2.1.组成部分说明如下:

Broker :消息队列服务进程,此进程包括两个部分:Exchange和Queue。

Exchange :消息队列交换机,按一定的规则将消息路由转发到某个队列,对消息进行过虑。

Queue :消息队列,存储消息的队列,消息到达队列并转发给指定的消费方。

Producer :消息生产者,即生产方客户端,生产方客户端将消息发送到MQ。

Consumer :消息消费者,即消费方客户端,接收MQ转发的消息。

2.2.消息发布接收流程:

-----发送消息-----

1、生产者和Broker建立TCP连接。

2、生产者和Broker建立通道。

3、生产者通过通道消息发送给Broker,由Exchange将消息进行转发。

4、Exchange将消息转发到指定的Queue(队列)

----接收消息-----

1、消费者和Broker建立TCP连接

2、消费者和Broker建立通道

3、消费者监听指定的Queue(队列)

4、当有消息到达Queue时Broker默认将消息推送给消费者。

5、消费者接收到消息。

2.3.下载安装

RabbitMQ由Erlang语言开发,Erlang语言用于并发及分布式系统的开发,在电信领域应用广泛,OTP(Open

Telecom Platform)作为Erlang语言的一部分,包含了很多基于Erlang开发的中间件及工具库,安装RabbitMQ需

要安装Erlang/OTP,并保持版本匹配,如下图:

RabbitMQ的下载地址:http://www.rabbitmq.com/download.html

在这里插入图片描述

2.3.1.下载erlang

地址如下:http://erlang.org/download/otp_win64_20.3.exe

或去老师提供的软件包中找到 otp_win64_20.3.exe,以管理员方式运行此文件,安装。

erlang安装完成需要配置erlang环境变量: ERLANG_HOME=D:\Program Files\erl9.3 在path中添

加%ERLANG_HOME%\bin;

2.3.2.安装RabbitMQ

https://github.com/rabbitmq/rabbitmq-server/releases/tag/v3.7.3

2.4.启动

安装成功后会自动创建RabbitMQ服务并且启动。

2.4.1.从开始菜单启动RabbitMQ

完成在开始菜单找到RabbitMQ的菜单:

在这里插入图片描述

RabbitMQ Service-install :安装服务

RabbitMQ Service-remove 删除服务

RabbitMQ Service-start 启动

RabbitMQ Service-stop 启动

2.4.2.如果没有开始菜单则进入安装目录下sbin目录手动启动:

在这里插入图片描述

2.4.3.安装并运行服务

rabbitmq-service.bat install 安装服务 rabbitmq-service.bat stop 停止服务 rabbitmq-service.bat start 启动服务

2.4.4.安装管理插件

安装rabbitMQ的管理插件,方便在浏览器端管理RabbitMQ

管理员身份运行 rabbitmq-plugins.bat enable rabbitmq_management

2.4.5.启动成功 登录RabbitMQ

进入浏览器,输入:http://localhost:15672

在这里插入图片描述

初始账号和密码:guest/guest

在这里插入图片描述

2.4.6.注意事项

1、安装erlang和rabbitMQ以管理员身份运行。

2、当卸载重新安装时会出现RabbitMQ服务注册失败,此时需要进入注册表清理erlang

搜索RabbitMQ、ErlSrv,将对应的项全部删除。

2.5.Hello World

按照官方教程(http://www.rabbitmq.com/getstarted.html) 测试hello world:

在这里插入图片描述

2.5.1.搭建环境

1)java client

生产者和消费者都属于客户端,rabbitMQ的java客户端如下:

在这里插入图片描述

我们先用 rabbitMQ官方提供的java client测试,目的是对RabbitMQ的交互过程有个清晰的认识。

参考 :https://github.com/rabbitmq/rabbitmq-java-client/

2 )创建maven工程

创建生产者工程和消费者工程,分别加入RabbitMQ java client的依赖。

test-rabbitmq-producer:生产者工程

test-rabbitmq-consumer:消费者工程

com.rabbitmq

amqp‐client

4.0.3<!‐‐此版本与spring boot 1.5.9版本匹配‐‐>

org.springframework.boot

spring‐boot‐starter‐logging

2.5.2.生产者

在生产者工程下的test中创建测试类如下:

public class Producer01 {

//队列名称

private static final String QUEUE = “helloworld”;

public static void main(String[] args) throws IOException, TimeoutException {

Connection connection = null;

Channel channel = null;

try

{

ConnectionFactory factory = new ConnectionFactory();

factory.setHost(“localhost”);

factory.setPort(5672);

factory.setUsername(“guest”);

factory.setPassword(“guest”);

factory.setVirtualHost(“/”);//rabbitmq默认虚拟机名称为“/”,虚拟机相当于一个独立的mq服务

//创建与RabbitMQ服务的TCP连接

connection = factory.newConnection();

//创建与Exchange的通道,每个连接可以创建多个通道,每个通道代表一个会话任务

channel = connection.createChannel();

/**

  • 声明队列,如果Rabbit中没有此队列将自动创建

  • param1:队列名称

  • param2:是否持久化

  • param3:队列是否独占此连接

  • param4:队列不再使用时是否自动删除此队列

  • param5:队列参数

*/

channel.queueDeclare(QUEUE, true, false, false, null);

String message = “helloworld小明”+System.currentTimeMillis();

/**

  • 消息发布方法

  • param1:Exchange的名称,如果没有指定,则使用Default Exchange

  • param2:routingKey,消息的路由Key,是用于Exchange(交换机)将消息转发到指定的消息队列

  • param3:消息包含的属性

  • param4:消息体

*/

/**

  • 这里没有指定交换机,消息将发送给默认交换机,每个队列也会绑定那个默认的交换机,但是不能显

示绑定或解除绑定

  • 默认的交换机,routingKey等于队列名称

*/

channel.basicPublish(“”, QUEUE, null, message.getBytes());

System.out.println(“Send Message is:'” + message + “'”);

}

catch(Exception ex)

{

ex.printStackTrace();

}

finally

{

if(channel != null)

{

channel.close();

}

if(connection != null)

{

connection.close();

}

}

}

}

2.5.3.消费者

在消费者工程下的test中创建测试类如下:

public class Consumer01 {

private static final String QUEUE = “helloworld”;

public static void main(String[] args) throws IOException, TimeoutException {

ConnectionFactory factory = new ConnectionFactory();

//设置MabbitMQ所在服务器的ip和端口

factory.setHost(“127.0.0.1”);

factory.setPort(5672);

Connection connection = factory.newConnection();

Channel channel = connection.createChannel();

//声明队列

channel.queueDeclare(QUEUE, true, false, false, null);

//定义消费方法

DefaultConsumer consumer = new DefaultConsumer(channel) {

/**

  • 消费者接收消息调用此方法

  • @param consumerTag 消费者的标签,在channel.basicConsume()去指定

  • @param envelope 消息包的内容,可从中获取消息id,消息routingkey,交换机,消息和重传标志

(收到消息失败后是否需要重新发送)

  • @param properties

  • @param body

  • @throws IOException

*/

@Override

public void handleDelivery(String consumerTag,

Envelope envelope,

AMQP.BasicProperties properties,

byte[] body)

throws IOException {

//交换机

String exchange = envelope.getExchange();

//路由key

String routingKey = envelope.getRoutingKey();

//消息id

long deliveryTag = envelope.getDeliveryTag();

//消息内容

String msg = new String(body,“utf‐8”);

System.out.println(“receive message…” + msg);

}

};

/**

  • 监听队列String queue, boolean autoAck,Consumer callback

  • 参数明细

  • 1、队列名称

  • 2、是否自动回复,设置为true为表示消息接收到自动向mq回复接收到了,mq接收到回复会删除消息,设置

为false则需要手动回复

  • 3、消费消息的方法,消费者接收到消息后调用此方法

*/

channel.basicConsume(QUEUE, true, consumer);

}

}

2.5.4.总结

1、发送端操作流程

1)创建连接

2)创建通道

3)声明队列

4)发送消息

2、接收端

1)创建连接

2)创建通道

3)声明队列

4)监听队列

5)接收消息

6 )ack回复

3.工作模式


RabbitMQ有以下几种工作模式 :

1、Work queues

2、Publish/Subscribe

3、Routing

4、Topics

5、Header

6、RPC

3.1.Work queues在这里插入图片描述

work queues与入门程序相比,多了一个消费端,两个消费端共同消费同一个队列中的消息。

应用场景:对于 任务过重或任务较多情况使用工作队列可以提高任务处理的速度。

测试:

1、使用入门程序,启动多个消费者。

2、生产者发送多个消息。

结果:

1、一条消息只会被一个消费者接收;

2、rabbit采用轮询的方式将消息是平均发送给消费者的;

3、消费者在处理完某条消息后,才会收到下一条消息。

3.2.Publish/subscribe

3.2.1.工作模式

在这里插入图片描述

发布订阅模式:

1、每个消费者监听自己的队列。

2、生产者将消息发给broker,由交换机将消息转发到绑定此交换机的每个队列,每个绑定交换机的队列都将接收

到消息

3.2.2.代码

案例:

用户通知,当用户充值成功或转账完成系统通知用户,通知方式有短信、邮件多种方法 。

1、生产者

声明Exchange_fanout_inform交换机。

声明两个队列并且绑定到此交换机,绑定时不需要指定routingkey

发送消息时不需要指定routingkey

import com.rabbitmq.client.*;

import java.io.IOException;

import java.util.concurrent.TimeoutException;

public class Producer02_publish {

//队列名称

private static final String QUEUE_INFORM_EMAIL = “queue_inform_email”;

private static final String QUEUE_INFORM_SMS = “queue_inform_sms”;

private static final String EXCHANGE_FANOUT_INFORM=“exchange_fanout_inform”;

public static void main(String[] args) {

Connection connection = null;

Channel channel = null;

try {

//创建一个与MQ的连接

ConnectionFactory factory = new ConnectionFactory();

factory.setHost(“127.0.0.1”);

factory.setPort(5672);

factory.setUsername(“guest”);

factory.setPassword(“guest”);

factory.setVirtualHost(“/”);//rabbitmq默认虚拟机名称为“/”,虚拟机相当于一个独立的mq服务

//创建一个连接

connection = factory.newConnection();

//创建与交换机的通道,每个通道代表一个会话

channel = connection.createChannel();

//声明交换机 String exchange, BuiltinExchangeType type

/**

  • 参数明细

  • 1、交换机名称

  • 2、交换机类型,fanout、topic、direct、headers

*/

channel.exchangeDeclare(EXCHANGE_FANOUT_INFORM, BuiltinExchangeType.FANOUT);

//声明队列

// (String queue, boolean durable, boolean exclusive, boolean autoDelete, Map<String,Object> arguments)

/**

  • 参数明细:

  • 1、队列名称

  • 2、是否持久化

  • 3、是否独占此队列

  • 4、队列不用是否自动删除

  • 5、参数

*/

channel.queueDeclare(QUEUE_INFORM_EMAIL, true, false, false, null);

channel.queueDeclare(QUEUE_INFORM_SMS, true, false, false, null);

//交换机和队列绑定String queue, String exchange, String routingKey

/**

  • 参数明细

  • 1、队列名称

  • 2、交换机名称

  • 3、路由key

*/

channel.queueBind(QUEUE_INFORM_EMAIL,EXCHANGE_FANOUT_INFORM,“”);

channel.queueBind(QUEUE_INFORM_SMS,EXCHANGE_FANOUT_INFORM,“”);

//发送消息

for (int i=0;i<10;i++){

String message = “inform to user”+i;

//向交换机发送消息 String exchange, String routingKey, BasicProperties props,byte[] body

/**

  • 参数明细

  • 1、交换机名称,不指令使用默认交换机名称 Default Exchange

  • 2、routingKey(路由key),根据key名称将消息转发到具体的队列,这里填写队列名称表示消

息将发到此队列

  • 3、消息属性

  • 4、消息内容

*/

channel.basicPublish(EXCHANGE_FANOUT_INFORM, “”, null, message.getBytes());

System.out.println(“Send Message is:'” + message + “'”);

}

} catch (IOException e) {

e.printStackTrace();

} catch (TimeoutException e) {

e.printStackTrace();

}finally{

if(channel!=null){

try {

channel.close();

} catch (IOException e) {

e.printStackTrace();

} catch (TimeoutException e) {

e.printStackTrace();

}

}

if(connection!=null){

try {

connection.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

}

}

2、邮件发送消费者

/**

  • @author Administrator

  • @version 1.0

  • @create 2018‐06‐14 10:32

**/

public class Consumer02_subscribe_email {

//队列名称

private static final String QUEUE_INFORM_EMAIL = “inform_queue_email”;

private static final String EXCHANGE_FANOUT_INFORM=“inform_exchange_fanout”;

public static void main(String[] args) throws IOException, TimeoutException {

//创建一个与MQ的连接

ConnectionFactory factory = new ConnectionFactory();

factory.setHost(“127.0.0.1”);

factory.setPort(5672);

factory.setUsername(“guest”);

factory.setPassword(“guest”);

factory.setVirtualHost(“/”);//rabbitmq默认虚拟机名称为“/”,虚拟机相当于一个独立的mq服务器

//创建一个连接

Connection connection = factory.newConnection();

//创建与交换机的通道,每个通道代表一个会话

Channel channel = connection.createChannel();

//声明交换机 String exchange, BuiltinExchangeType type

/**

  • 参数明细

  • 1、交换机名称

  • 2、交换机类型,fanout、topic、direct、headers

*/

channel.exchangeDeclare(EXCHANGE_FANOUT_INFORM, BuiltinExchangeType.FANOUT);

//声明队列

// channel.queueDeclare(String queue, boolean durable, boolean exclusive, boolean autoDelete, Map<String, Object> arguments)

/**

  • 参数明细:

  • 1、队列名称

  • 2、是否持久化

  • 3、是否独占此队列

  • 4、队列不用是否自动删除

  • 5、参数

*/

channel.queueDeclare(QUEUE_INFORM_EMAIL, true, false, false, null);

//交换机和队列绑定String queue, String exchange, String routingKey

/**

  • 参数明细

  • 1、队列名称

  • 2、交换机名称

  • 3、路由key

*/

channel.queueBind(QUEUE_INFORM_EMAIL,EXCHANGE_FANOUT_INFORM,“”);

//定义消费方法

DefaultConsumer defaultConsumer = new DefaultConsumer(channel) {

@Override

public void handleDelivery(String consumerTag, Envelope envelope,

AMQP.BasicProperties properties, byte[] body) throws IOException {

long deliveryTag = envelope.getDeliveryTag();

String exchange = envelope.getExchange();

//消息内容

String message = new String(body, “utf‐8”);

System.out.println(message);

}

};

/**

  • 监听队列String queue, boolean autoAck,Consumer callback

  • 参数明细

  • 1、队列名称

  • 2、是否自动回复,设置为true为表示消息接收到自动向mq回复接收到了,mq接收到回复会删除消息,设置

为false则需要手动回复

  • 3、消费消息的方法,消费者接收到消息后调用此方法

*/

channel.basicConsume(QUEUE_INFORM_EMAIL, true, defaultConsumer);

}

}

按照上边的代码,编写邮件通知的消费代码。

3、短信发送消费者

可参考上边的邮件发送消费者代码编写。

3.2.3.测试

打开RabbitMQ的管理界面,观察交换机绑定情况:

在这里插入图片描述

使用生产者发送若干条消息,每条消息都转发到各各队列,每消费者都接收到了消息。

3.2.3.思考

1、publish/subscribe与work queues有什么区别。

区别:

1)work queues不用定义交换机,而publish/subscribe需要定义交换机。

2)publish/subscribe的生产方是面向交换机发送消息,work queues的生产方是面向队列发送消息(底层使用默认

交换机)。

3)publish/subscribe需要设置队列和交换机的绑定,work queues不需要设置,实质上work queues会将队列绑

定到默认的交换机 。

相同点:

所以两者实现的发布/订阅的效果是一样的,多个消费端监听同一个队列不会重复消费消息。

2、实质工作用什么 publish/subscribe还是work queues。

建议使用 publish/subscribe,发布订阅模式比工作队列模式更强大,并且发布订阅模式可以指定自己专用的交换

机。

3.3.Routing

3.3.1.工作模式

在这里插入图片描述

路由模式:

1、每个消费者监听自己的队列,并且设置routingkey。

2、生产者将消息发给交换机,由交换机根据routingkey来转发消息到指定的队列。

3.3.2.代码

1、生产者

声明exchange_routing_inform交换机。

声明两个队列并且绑定到此交换机,绑定时需要指定routingkey

发送消息时需要指定routingkey

import com.rabbitmq.client.BuiltinExchangeType;

import com.rabbitmq.client.Channel;

import com.rabbitmq.client.Connection;

import com.rabbitmq.client.ConnectionFactory;

import java.io.IOException;

import java.util.concurrent.TimeoutException;

public class Producer03_routing {

//队列名称

private static final String QUEUE_INFORM_EMAIL = “queue_inform_email”;

private static final String QUEUE_INFORM_SMS = “queue_inform_sms”;

private static final String EXCHANGE_ROUTING_INFORM=“exchange_routing_inform”;

public static void main(String[] args) {

Connection connection = null;

Channel channel = null;

try {

//创建一个与MQ的连接

ConnectionFactory factory = new ConnectionFactory();

factory.setHost(“127.0.0.1”);

factory.setPort(5672);

factory.setUsername(“guest”);

factory.setPassword(“guest”);

factory.setVirtualHost(“/”);//rabbitmq默认虚拟机名称为“/”,虚拟机相当于一个独立的mq服务

//创建一个连接

connection = factory.newConnection();

//创建与交换机的通道,每个通道代表一个会话

channel = connection.createChannel();

//声明交换机 String exchange, BuiltinExchangeType type

/**

  • 参数明细

  • 1、交换机名称

  • 2、交换机类型,fanout、topic、direct、headers

*/

channel.exchangeDeclare(EXCHANGE_ROUTING_INFORM, BuiltinExchangeType.DIRECT);

//声明队列

// channel.queueDeclare(String queue, boolean durable, boolean exclusive, boolean autoDelete, Map<String, Object> arguments)

/**

  • 参数明细:

  • 1、队列名称

  • 2、是否持久化

  • 3、是否独占此队列

  • 4、队列不用是否自动删除

  • 5、参数

*/

channel.queueDeclare(QUEUE_INFORM_EMAIL, true, false, false, null);

channel.queueDeclare(QUEUE_INFORM_SMS, true, false, false, null);

//交换机和队列绑定String queue, String exchange, String routingKey

/**

  • 参数明细

  • 1、队列名称

  • 2、交换机名称

  • 3、路由key

*/

channel.queueBind(QUEUE_INFORM_EMAIL,EXCHANGE_ROUTING_INFORM,QUEUE_INFORM_EMAIL);

channel.queueBind(QUEUE_INFORM_SMS,EXCHANGE_ROUTING_INFORM,QUEUE_INFORM_SMS);

//发送邮件消息

for (int i=0;i<10;i++){

String message = “email inform to user”+i;

//向交换机发送消息 String exchange, String routingKey, BasicProperties props,byte[] body

/**

  • 参数明细

  • 1、交换机名称,不指令使用默认交换机名称 Default Exchange

  • 2、routingKey(路由key),根据key名称将消息转发到具体的队列,这里填写队列名称表示消

息将发到此队列

  • 3、消息属性

  • 4、消息内容

*/

channel.basicPublish(EXCHANGE_ROUTING_INFORM, QUEUE_INFORM_EMAIL,null,message.getBytes());

System.out.println(“Send Message is:'” + message + “'”);

}

//发送短信消息

for (int i=0;i<10;i++){

String message = “sms inform to user”+i;

//向交换机发送消息 String exchange, String routingKey, BasicProperties props,byte[] body

channel.basicPublish(EXCHANGE_ROUTING_INFORM, QUEUE_INFORM_SMS, null,message.getBytes());

System.out.println(“Send Message is:'” + message + “'”);

}

} catch (IOException e) {

e.printStackTrace();

} catch (TimeoutException e) {

e.printStackTrace();

}finally{

if(channel!=null){

try {

channel.close();

} catch (IOException e) {

e.printStackTrace();

} catch (TimeoutException e) {

e.printStackTrace();

}

}

if(connection!=null){

try {

connection.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

}

}

2、邮件发送消费者

import com.rabbitmq.client.*;

import java.io.IOException;

import java.util.concurrent.TimeoutException;

public class Consumer03_routing_email {

//队列名称

private static final String QUEUE_INFORM_EMAIL = “inform_queue_email”;

private static final String EXCHANGE_ROUTING_INFORM=“inform_exchange_routing”;

public static void main(String[] args) throws IOException, TimeoutException {

//创建一个与MQ的连接

ConnectionFactory factory = new ConnectionFactory();

factory.setHost(“127.0.0.1”);

factory.setPort(5672);

factory.setUsername(“guest”);

factory.setPassword(“guest”);

factory.setVirtualHost(“/”);//rabbitmq默认虚拟机名称为“/”,虚拟机相当于一个独立的mq服务器

//创建一个连接

Connection connection = factory.newConnection();

//创建与交换机的通道,每个通道代表一个会话

Channel channel = connection.createChannel();

//声明交换机 String exchange, BuiltinExchangeType type

/**

  • 参数明细

  • 1、交换机名称

  • 2、交换机类型,fanout、topic、direct、headers

*/

channel.exchangeDeclare(EXCHANGE_ROUTING_INFORM, BuiltinExchangeType.DIRECT);

//声明队列

// channel.queueDeclare(String queue, boolean durable, boolean exclusive, boolean autoDelete, Map<String, Object> arguments)

/**

  • 参数明细:

  • 1、队列名称

  • 2、是否持久化

  • 3、是否独占此队列

  • 4、队列不用是否自动删除

  • 5、参数

*/

channel.queueDeclare(QUEUE_INFORM_EMAIL, true, false, false, null);

//交换机和队列绑定String queue, String exchange, String routingKey

/**

  • 参数明细

  • 1、队列名称

  • 2、交换机名称

  • 3、路由key

*/

channel.queueBind(QUEUE_INFORM_EMAIL,EXCHANGE_ROUTING_INFORM,QUEUE_INFORM_EMAIL);

//定义消费方法

DefaultConsumer defaultConsumer = new DefaultConsumer(channel) {

@Override

public void handleDelivery(String consumerTag, Envelope envelope,AMQP.BasicProperties properties, byte[] body) throws IOException {

long deliveryTag = envelope.getDeliveryTag();

String exchange = envelope.getExchange();

//消息内容

String message = new String(body, “utf‐8”);

System.out.println(message);

}

};

/**

  • 监听队列String queue, boolean autoAck,Consumer callback

  • 参数明细

  • 1、队列名称

  • 2、是否自动回复,设置为true为表示消息接收到自动向mq回复接收到了,mq接收到回复会删除消息,设置

为false则需要手动回复

  • 3、消费消息的方法,消费者接收到消息后调用此方法

*/

channel.basicConsume(QUEUE_INFORM_EMAIL, true, defaultConsumer);

}

}

3 、短信发送消费者

可以参考邮件发送消费者的代码流程,编写短信通知的代码。

3.3.3.测试

打开RabbitMQ的管理界面,观察交换机绑定情况:

在这里插入图片描述

使用生产者发送若干条消息,交换机根据routingkey转发消息到指定的队列。

3.3.4.思考

Routing模式和Publish/subscibe有啥区别?

Routing模式要求队列在绑定交换机时要指定routingkey,消息会转发到符合routingkey的队列。

3.4.Topics

3.4.1.工作模式

在这里插入图片描述

路由模式:

1、每个消费者监听自己的队列,并且设置带统配符的routingkey。

2、生产者将消息发给broker,由交换机根据routingkey来转发消息到指定的队列。

3.4.2.代码

案例:

根据用户的通知设置去通知用户,设置接收Email的用户只接收Email,设置接收sms的用户只接收sms,设置两种

通知类型都接收的则两种通知都有效。

1、生产者

声明交换机,指定topic类型:

/**

  • 声明交换机

  • param1:交换机名称

  • param2:交换机类型 四种交换机类型:direct、fanout、topic、headers

*/

channel.exchangeDeclare(EXCHANGE_TOPICS_INFORM, BuiltinExchangeType.TOPIC);

//Email通知

channel.basicPublish(EXCHANGE_TOPICS_INFORM, “inform.email”, null, message.getBytes());

//sms通知

channel.basicPublish(EXCHANGE_TOPICS_INFORM, “inform.sms”, null, message.getBytes());

//两种都通知

channel.basicPublish(EXCHANGE_TOPICS_INFORM, “inform.sms.email”, null, message.getBytes());

完整代码:完整代码:

import com.rabbitmq.client.BuiltinExchangeType;

import com.rabbitmq.client.Channel;

import com.rabbitmq.client.Connection;

import com.rabbitmq.client.ConnectionFactory;

import java.io.IOException;

import java.util.concurrent.TimeoutException;

public class Producer04_topics {

//队列名称

private static final String QUEUE_INFORM_EMAIL = “queue_inform_email”;

private static final String QUEUE_INFORM_SMS = “queue_inform_sms”;

private static final String EXCHANGE_TOPICS_INFORM=“exchange_topics_inform”;

public static void main(String[] args) {

Connection connection = null;

Channel channel = null;

try {

//创建一个与MQ的连接

ConnectionFactory factory = new ConnectionFactory();

factory.setHost(“127.0.0.1”);

factory.setPort(5672);

factory.setUsername(“guest”);

factory.setPassword(“guest”);

factory.setVirtualHost(“/”);//rabbitmq默认虚拟机名称为“/”,虚拟机相当于一个独立的mq服务器

//创建一个连接

connection = factory.newConnection();

//创建与交换机的通道,每个通道代表一个会话

channel = connection.createChannel();

//声明交换机 String exchange, BuiltinExchangeType type

/**

  • 参数明细* 1、交换机名称

  • 2、交换机类型,fanout、topic、direct、headers

*/

channel.exchangeDeclare(EXCHANGE_TOPICS_INFORM, BuiltinExchangeType.TOPIC);

//声明队列

/**

  • 参数明细:

  • 1、队列名称

  • 2、是否持久化

  • 3、是否独占此队列

  • 4、队列不用是否自动删除

  • 5、参数

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

最后

金三银四到了,送上一个小福利!

image.png

image.png

专题+大厂.jpg
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
();

factory.setHost(“127.0.0.1”);

factory.setPort(5672);

factory.setUsername(“guest”);

factory.setPassword(“guest”);

factory.setVirtualHost(“/”);//rabbitmq默认虚拟机名称为“/”,虚拟机相当于一个独立的mq服务器

//创建一个连接

connection = factory.newConnection();

//创建与交换机的通道,每个通道代表一个会话

channel = connection.createChannel();

//声明交换机 String exchange, BuiltinExchangeType type

/**

  • 参数明细* 1、交换机名称

  • 2、交换机类型,fanout、topic、direct、headers

*/

channel.exchangeDeclare(EXCHANGE_TOPICS_INFORM, BuiltinExchangeType.TOPIC);

//声明队列

/**

  • 参数明细:

  • 1、队列名称

  • 2、是否持久化

  • 3、是否独占此队列

  • 4、队列不用是否自动删除

  • 5、参数

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。[外链图片转存中…(img-vol1Dx2F-1713744909669)]

[外链图片转存中…(img-G0YeFijv-1713744909670)]

[外链图片转存中…(img-JhQuJnPS-1713744909670)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

最后

金三银四到了,送上一个小福利!

[外链图片转存中…(img-AJ0i8l16-1713744909670)]

[外链图片转存中…(img-HPgyFo5M-1713744909671)]

[外链图片转存中…(img-mzckWLKk-1713744909671)]
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

  • 21
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值