下载安装:
windows:
rabbit-mq官方文档:rabbit下载
rabbitmq依赖erlang:erlang下载
相关文档: https://jingyan.baidu.com/album/a17d5285173ce68098c8f2e5.html?picindex=1
发送/接收消息:
1.引入的jar包:
com.rabbitmq
amqp-client
5.1.2
2.创建RabbitConfig.java常量配置类
public class RabbitConfig {
/**
* 声明名为queue的队列名称
*/
public static final String queue = "queue";
}
3.创建执行发送消息类Send.java
将消息发送到队列名:队列
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
public class Send {
public static void main(String[] args) throws Exception {
ConnectionFactory connectionFactory = new ConnectionFactory();
Connection connection = connectionFactory.newConnection();
Channel channel = connection.createChannel();
channel.queueDeclare(RabbitConfig.queue,true, false, false, null);
String message = "hello world!";
System.out.println("server发送消息:" + message);
channel.basicPublish("", RabbitConfig.queue, true, null, message.getBytes());
channel.close();
connection.close();
}
}
4.创建执行消息类Receive.java
接收处理队列名:队列中的消息
import com.rabbitmq.client.*;
public class Receive {
public static void main(String[] args) throws Exception {
ConnectionFactory connectionFactory = new ConnectionFactory();
Connection connection = connectionFactory.newConnection();
Channel channel = connection.createChannel();
channel.queueDeclare(RabbitConfig.queue,true, false, false, null);
DeliverCallback deliverCallback = (consumerTag, delivery)->{
long deliveryTag = delivery.getEnvelope().getDeliveryTag();
String message = new String(delivery.getBody());
System.out.println("client接收消息:" + message + ",deliveryTag:" + deliveryTag);
};
channel.basicConsume(RabbitConfig.queue, true, deliverCallback, (CancelCallback) null);
}
}
执行两个类的主要方法将会看到接收类接收到发送类中的消息:
到这里已经实现rabbitmq发送接收消息。下面简单解析方法参数的含义:
queue:队列名称
durable:是否持久化, 队列的声明默认是存放到内存中的,如果rabbitmq重启会丢失,如果想重启之后还存在就要使队列
持久化,保存到Erlang自带的Mnesia数据库中,当rabbitmq重启之后会读取该数据库
exclusive:是否排外的。 两个作用:
(当设置true:只能存在一个消费者,声明队列连接关闭队列自动删除;false:多个消费者,连接关闭队列不会删除)
1.当关闭声明队列连接时connection.close()该队列是否会自动删除
2.该队列是否是私有的private,如果设置true,只能有一个消费者
autoDelete:是否自动删除。当最后一个消费者断开连接之后,自动删除队列。
arguments:map类型参数。下面表示map中key代表的含义
x-message-ttl:设置队列中的所有消息的生存周期
x-expires:当队列在指定的时间没有被访问,队列就会删除
x-max-length:限定队列的消息的最大值长度,超过指定长度将会把最早的几条删除掉
x-max-length-bytes:限定队列最大占用的空间大小
x-overflow:
x-dead-letter-exchange:当队列消息长度大于最大长度、或者过期的等,将从队列中删除的消息推送到指定的交换机中去而不是丢弃掉
x-dead-letter-routing-key:将删除的消息推送到指定交换机的指定路由键的队列中去
x-max-priority:优先级队列,声明队列时先定义最大优先级值(定义最大值一般不要太大),在发布消息的时候指定该消息的优先级, 优先级更高(数值更大的)的消息先被消费
x-queue-mode:Lazy Queues: 先将消息保存到磁盘上,不放在内存中,当消费者开始消费的时候才加载到内存中
x-queue-master-locator:
exchange:指定交换机(rabbit中队列是在交换机exchange上绑定的,由交换机根据routingkey规则发送到指定队列)
routingKey:路由键(将消息具体发送到交换机哪一个队列的策略/规则)
mandatory:如果exchange根据自身类型和消息routeKey无法找到一个符合条件的queue,那么会调用basic.return方法将消息返还给生产者。false:出现上述情形broker会直接将消息扔掉
props: 请参考:https://blog.csdn.net/vbirdbest/article/details/78698364
body:消息内容
queue:队列名字
autoAck:是否自动确认消息,true自动确认,false 不自动要手动调用
callback:实现Consumer接口:
package com.rabbitmq.client;
import com.rabbitmq.client.AMQP.BasicProperties;
import java.io.IOException;
public interface Consumer {
void handleConsumeOk(String var1);
void handleCancelOk(String var1);
void handleCancel(String var1) throws IOException;
void handleShutdownSignal(String var1, ShutdownSignalException var2);
void handleRecoverOk(String var1);
// 处理消息
void handleDelivery(String var1, Envelope var2, BasicProperties var3, byte[] var4) throws IOException;
}
以上方法解析参考csdn 博主vbirdbest 链接:https://blog.csdn.net/vbirdbest/article/details/78670550
exchange交换机,routingkey路由,queue队列
简述:
rabbitmq中消息并不是直接将消息添加到队列中的,而是通过exchange(交换机)类型,以及 routingKey(路由)到exchange所绑定的queue队列中。
exchange类型特性_推荐参考此博客:https://blog.csdn.net/hry2015/article/details/79118804
routingKey和exchange搭配_推荐参考此博客:https://blog.csdn.net/hry2015/article/details/79183941
使用其中一种交换机类型direct(直连交换机),在上面发送消息代码中修改:
1.添加静态变量
public class RabbitConfig {
/**
* 声明名为queue的队列名称
*/
public static final String queue = "queue2";
/**
* 交换机
*/
public static final String directExchange = "directExchange";
/**
* 路由键
*/
public static final String routingKey = "routingKey";
}
2.修改send类,添加交换机,绑定队列(共修改3处)
import static com.luck.rabbit.test.RabbitConfig.directExchange;
import static com.luck.rabbit.test.RabbitConfig.queue;
import static com.luck.rabbit.test.RabbitConfig.routingKey;
public class Send {
public static void main(String[] args) throws Exception {
ConnectionFactory connectionFactory = new ConnectionFactory();
Connection connection = connectionFactory.newConnection();
Channel channel = connection.createChannel();
channel.queueDeclare(queue,true, false, true, null);
// 1.创建direct交换机
channel.exchangeDeclare(directExchange, BuiltinExchangeType.DIRECT);
// 2.将队列queue绑定到交换机directExchange上,指定路由键为routingKey
channel.queueBind(queue, directExchange, routingKey);
String message = "hello world!";
System.out.println("server发送消息:" + message);
// 3.发送消息到directExchange交换机,路由键为routingKey
channel.basicPublish(directExchange, routingKey, true, null, message.getBytes());
channel.close();
connection.close();
}
}
3.Receive类可以不修改,但是因为队列名字改变了,需要重新运行此类
以上实现了,向direct交换机发送消息到绑定路由键为routingKey的队列queue。
Channel接口中的两个方法获取消息:basicGet(pull) / basicConsume(push)
public class Receive {
public static void main(String[] args) throws Exception {
ConnectionFactory connectionFactory = new ConnectionFactory();
Connection connection = connectionFactory.newConnection();
Channel channel = connection.createChannel();
channel.queueDeclare(queue,true, false, true, null);
System.out.println("waiting for messages");
// 更换获取消息方式
pull(channel);
}
/**
* 拉取:主动获取消息
* @param channel
*/
public static void pull(Channel channel) throws Exception {
String message;
GetResponse resp ;
resp = channel.basicGet(queue,true);
if(resp==null){
System.out.println(queue+" 队列无消息");
return;
}
message = new String(resp.getBody(), "UTF-8");
System.out.println("获取消息:"+ message);
channel.close();
}
/**
* 推送:轮训获取消息
* @param channel
*/
public static void push(Channel channel){
DeliverCallback deliverCallback = (consumerTag, delivery)->{
long deliveryTag = delivery.getEnvelope().getDeliveryTag();
String messages = new String(delivery.getBody());
System.out.println("client接收消息:" + messages + ",deliveryTag:" + deliveryTag);
};
try {
channel.basicConsume(queue, true, deliverCallback, (CancelCallback) null);
} catch (IOException e) {
e.printStackTrace();
}
}
}