RabbitMQ is a message broker: it accepts and forwards messages. You can think about it as a post office: when you put the mail that you want posting in a post box, you can be sure that Mr. or Ms. Mailperson will eventually deliver the mail to your recipient.
In this analogy, RabbitMQ is a post box, a post office and a postman.
The major difference between RabbitMQ and the post office is that it doesn't deal with paper, instead it accepts, stores and forwards binary blobs of data ‒ messages.
RabbitMQ是一个消息代理:它接受和转发消息。 你可以把它想象成一个邮局:当你把邮件放在邮箱里时,你可以确定邮差先生最终会把邮件发送给你的收件人。 在这个比喻中,RabbitMQ是邮政信箱,邮局和邮递员。
RabbitMQ与邮局的主要区别是它不处理纸张,而是接受,存储和转发数据消息的二进制数据块。
在上图模型中,有以下概念:
P:生产者,也就是要发送消息的程序
C:消费者,消息的接收者,会一直等待消息的到来
Queue:消息队列,图中红色部分。类似一个邮箱,可以缓存消息;生产者向其中投递消息,消费者从其中取出消息。
1. 创建项目,引入依赖
<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
<version>5.7.2</version>
</dependency>
2. web管理端添加vhost
3. 添加用户,并访问虚拟主机
点击user-helloword,授权访问虚拟主机
4. 开发生产者
package helloword;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import org.junit.Test;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class Provider {
@Test
public void sendMessage() throws IOException, TimeoutException {
// 创建mq连接工厂
ConnectionFactory connectionFactory = new ConnectionFactory();
// 连接主机
connectionFactory.setHost("192.168.0.116");
connectionFactory.setPort(5672);
// 连接虚拟主机
connectionFactory.setVirtualHost("my_helloword");
connectionFactory.setUsername("helloword");
connectionFactory.setPassword("helloword");
// 获取连接
Connection connection = connectionFactory.newConnection();
// 获取通道
Channel channel = connection.createChannel();
// 通道绑定对应消息队列
// 参数1 name:队列名称,如果不存在则自动创建
// 参数2 durable:是否持久化
// 参数3 exclusive:是否独占队列(其他连接无法访问)
// 参数4 autoDelete:是否再消费完成后自动删除
// 参数5 额外参数
channel.queueDeclare("helloword", false, false, false, null);
// 发布消息
// 参数1 exchange:交换机名称,点对点模式,没有交换机,所以 “”
// 参数2 routingKey: 队列名称
// 参数3 props:消息额外参数
// 参数4 消息内容
channel.basicPublish("", "helloword", null, "hello world rabbitmq!!!".getBytes());
// 发布完成之后关闭通道和连接
channel.close();
connection.close();
}
}
/*修订:chennel.basicPublish() 第一个参数exchange,点对点模式不是没有交换机,而是采用的默认交换机。*/
运行程序后,web端管理界面查看是否发送成功
5. 开发消费者
package helloword;
import com.rabbitmq.client.*;
import com.rabbitmq.client.AMQP.BasicProperties;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class Consumer {
public static void main(String[] args) throws IOException, TimeoutException {
// 创建mq连接工厂
ConnectionFactory connectionFactory = new ConnectionFactory();
// 连接主机
connectionFactory.setHost("192.168.0.116");
connectionFactory.setPort(5672);
// 连接虚拟主机
connectionFactory.setVirtualHost("my_helloword");
connectionFactory.setUsername("helloword");
connectionFactory.setPassword("helloword");
// 获取连接
Connection connection = connectionFactory.newConnection();
// 获取通道
Channel channel = connection.createChannel();
// 通道绑定对应消息队列
// 参数1 name:队列名称,如果不存在则自动创建
// 参数2 durable:是否持久化
// 参数3 exclusive:是否独占队列(其他连接无法访问)
// 参数4 autoDelete:是否再消费完成后自动删除
// 参数5 额外参数
channel.queueDeclare("helloword", false, false, false, null);
// 通道连接队列,消费消息
// 参数1 queue:队列名称
// 参数2 autoAck:开启消息自动确认机制
// 参数3 consume:消息回调
channel.basicConsume("helloword", true, new DefaultConsumer(channel) {
// 获取消息,并且处理,这个方法类似事件监听,如果有消息的时候,会被自动调用
@Override
public void handleDelivery(String consumerTag, Envelope envelope, BasicProperties properties,
byte[] body) throws IOException {
// body 即消息体
String msg = new String(body);
System.out.println(" consumer received : " + msg + "!");
}
});
// 消费对象需要一直监听队列,所以不关闭
// channel.close();
// connection.close();
}
}
运行程序后,日志输出:
查看web管理端
Messages处已经为0,说明已经被消费了。
6. 代码冗余,简化代码,封装
package utils;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import java.io.IOException;
public class RabbitMQUtil {
private static ConnectionFactory connectionFactory;
static {
connectionFactory = new ConnectionFactory();
// 连接主机
connectionFactory.setHost("192.168.0.116");
connectionFactory.setPort(5672);
// 连接虚拟主机
connectionFactory.setVirtualHost("my_helloword");
connectionFactory.setUsername("helloword");
connectionFactory.setPassword("helloword");
}
/**
* 获取连接
* @return
*/
public static Connection getConnection() {
try {
// 获取连接
return connectionFactory.newConnection();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 连接通道
* @param connection
* @return
*/
public static Channel getChannel(Connection connection) {
if (null == connection) {
return null;
}
try {
return connection.createChannel();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
/**
* 关闭通道和连接
* @param channel
* @param connection
*/
public static void close(Channel channel, Connection connection) {
try {
if (null != channel) channel.close();
if (null != connection) connection.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}