1. 简单模式
说明:
P:生产者 C:消费者
工作的流程:
- 当生产者生产消息后,将消息发往队列.
- 当队列中有消息时,消费者会实时的监听队列中的消息.如果有消息则会执行消息
public class TestRabbitMQ_1_simple {
private Connection connection = null;
//定义公共连接
/**
* 1.定义rabbmq地址 ip:端口
* 2.定义虚拟主机
* 3.定义用户名和密码
* @throws IOException
*/
@Before
public void init() throws IOException{
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("192.168.126.146");
connectionFactory.setPort(5672);
connectionFactory.setVirtualHost("/jt");
connectionFactory.setUsername("jtadmin");
connectionFactory.setPassword("jtadmin");
//获取链接
connection = connectionFactory.newConnection();
}
//定义生产者
@Test
public void proverder() throws IOException{
//定义通道Chneel接口
Channel channel = connection.createChannel();
//定义队列
/**
* queue:队列名称
* durable:是否持久化 true 和false
* exclusive: 如果为true 表示为生产者独有
* autoDelete:当消息消费完成后是否自动删除
* arguments:是否传递参数 一般为空
*/
channel.queueDeclare("queue_1", false, false, false, null);
//定义发送的消息
String msg = "我是单工模式";
//发送消息
/**
* exchange:交换机名称 如果没有交换机 添加""串
* routingKey:路由KEy 信息标识符,没有添加队列名称
* props 携带的参数
* body.传递信息的字节码文件
*/
channel.basicPublish("", "queue_1",null, msg.getBytes());
channel.close();
connection.close();
}
//定义消费者
@Test
public void consumer() throws IOException, ShutdownSignalException, ConsumerCancelledException, InterruptedException{
//获取通道
Channel channel = connection.createChannel();
//定义队列
channel.queueDeclare("queue_1", false, false, false, null);
//定义消费者对象
QueueingConsumer consumer = new QueueingConsumer(channel);
//将消费者与队列绑定
channel.basicConsume("queue_1", true, consumer);
//循环获取信息
while(true){
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String msg = new String(delivery.getBody());
System.out.println("获取信息:"+msg);
}
}
2.工作模式
说明:
当生产者生产消息时,将消息写入队列中,多个消费者争抢执行,并且实现轮询执行方式.
业务场景:
抢红包的机制/秒杀业务
public class TestRabbitMQ_2_work {
//工作模式:多个人一起消费一个队列消息.内部轮询机制
/**
* 1.定义rabbmq地址 ip:端口
* 2.定义虚拟主机
* 3.定义用户名和密码
* @throws IOException
*/
private Connection connection = null;
@Before
public void init() throws IOException{
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("192.168.126.146");
connectionFactory.setPort(5672);
connectionFactory.setVirtualHost("/jt");
connectionFactory.setUsername("jtadmin");
connectionFactory.setPassword("jtadmin");
//获取链接
connection = connectionFactory.newConnection();
}
@Test
public void provider() throws IOException{
//定义通道对象
Channel channel = connection.createChannel();
//定义队列
channel.queueDeclare("queue_work", false, false, false, null);
//定义广播的消息
String msg = "我是工作模式";
//发送消息
channel.basicPublish("", "queue_work", null, msg.getBytes());
//关闭流文件
channel.close();
connection.close();
}
//定义消费者
@Test
public void consumer1() throws IOException, ShutdownSignalException, ConsumerCancelledException, InterruptedException{
//定义通道
Channel channel = connection.createChannel();
//定义队列
channel.queueDeclare("queue_work", false, false, false, null);
//定义消费数 每次只能消费一条记录.当消息执行后需要返回ack确认消息 才能执行下一条
channel.basicQos(1);
//定义消费者
QueueingConsumer consumer = new QueueingConsumer(channel);
//将队列和消费者绑定 false表示手动返回ack
channel.basicConsume("queue_work", false, consumer);
while(true){
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String msg = new String(delivery.getBody());
System.out.println("队列A获取消息:"+msg);
//deliveryTag 队列下标位置
//multiple是否批量返回
channel.basicAck(delivery.getEnvelope().getDeliveryTag(), true);
}
}
//定义消费者
@Test
public void consumer2() throws IOException, ShutdownSignalException, ConsumerCancelledException, InterruptedException{
//定义通道
Channel channel = connection.createChannel();
//定义队列
channel.queueDeclare("queue_work", false, false, false, null);
//定义消费数 每次只能消费一条记录.当消息执行后需要返回ack确认消息 才能执行下一条
channel.basicQos(1);
//定义消费者
QueueingConsumer consumer = new QueueingConsumer(channel);
//将队列和消费者绑定 false表示手动返回ack
channel.basicConsume("queue_work", false, consumer);
while(true){
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String msg = new String(delivery.getBody());
System.out.println("队列B获取消息:"+msg);
//deliveryTag 队列下标位置
//multiple是否批量返回
channel.basicAck(delivery.getEnvelope().getDeliveryTag(), true);
}
}
//定义消费者
@Test
public void consumer3() throws IOException, ShutdownSignalException, ConsumerCancelledException, InterruptedException{
//定义通道
Channel channel = connection.createChannel();
//定义队列
channel.queueDeclare("queue_work", false, false, false, null);
//定义消费数 每次只能消费一条记录.当消息执行后需要返回ack确认消息 才能执行下一条
channel.basicQos(1);
//定义消费者
QueueingConsumer consumer = new QueueingConsumer(channel);
//将队列和消费者绑定 false表示手动返回ack
channel.basicConsume("queue_work", false, consumer);
while(true){
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String msg = new String(delivery.getBody());
System.out.println("队列C获取消息:"+msg);
//deliveryTag 队列下标位置
//multiple是否批量返回
channel.basicAck(delivery.getEnvelope().getDeliveryTag(), true);
}
}
}
3.发布订阅模式
说明:
P:生产者
C:消费者
X:交换机
模式:
当采用了发布订阅模式时,当生产者发布了消息,经过交换机发往不同的队列.
这时不同的队列中有相同的消息.一个消息被执行多次
使用场景: 群发 微信公众号订阅
public class TestRabbitMQ_3_publish {
//发布订阅模式
private Connection connection = null;
//定义rabbit连接池
@Before
public void initConnection() throws IOException{
//定义工厂对象
ConnectionFactory connectionFactory = new ConnectionFactory();
//设定参数
connectionFactory.setHost("192.168.126.146");
connectionFactory.setPort(5672);
connectionFactory.setVirtualHost("/jt");
connectionFactory.setUsername("jtadmin");
connectionFactory.setPassword("jtadmin");
//创建连接
connection = connectionFactory.newConnection();
}
//定义生产者
@Test
public void proverder() throws IOException{
//定义通道
Channel channel = connection.createChannel();
//定义交换机名称
String exchange_name = "E1";
//定义发布订阅模式 fanout redirect 路由模式 topic 主题模式
channel.exchangeDeclare(exchange_name, "fanout");
for(int i=0;i<10; i++){
String msg = "发布订阅模式"+i;
channel.basicPublish(exchange_name, "", null, msg.getBytes());
}
channel.close();
connection.close();
}
/**
* 消费者需要定义队列名称 并且与交换机绑定
* @throws IOException
* @throws InterruptedException
* @throws ConsumerCancelledException
* @throws ShutdownSignalException
*/
@Test
public void consumer1() throws IOException, ShutdownSignalException, ConsumerCancelledException, InterruptedException{
Channel channel = connection.createChannel();
String exchange_name = "E1";
String queue_name = "c_1";
//定义交换机模式
channel.exchangeDeclare(exchange_name, "fanout");
//定义队列
channel.queueDeclare(queue_name, false, false, false, null);
//将队列和交换机绑定
channel.queueBind(queue_name, exchange_name, "");
//定义消费数量
channel.basicQos(1);
//定义消费者
QueueingConsumer consumer = new QueueingConsumer(channel);
//将消费者和队列绑定,并且需要手动返回
channel.basicConsume(queue_name, false, consumer);
while(true){
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String msg = "发布订阅模式-消费者1"+new String(delivery.getBody());
System.out.println(msg);
//false表示一个一个返回
channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
}
}
/**
* 消费者需要定义队列名称 并且与交换机绑定
* @throws IOException
* @throws InterruptedException
* @throws ConsumerCancelledException
* @throws ShutdownSignalException
*/
@Test
public void consumer2() throws IOException, ShutdownSignalException, ConsumerCancelledException, InterruptedException{
Channel channel = connection.createChannel();
String exchange_name = "E1";
String queue_name = "c_2";
//定义交换机模式
channel.exchangeDeclare(exchange_name, "fanout");
//定义队列
channel.queueDeclare(queue_name, false, false, false, null);
//将队列和交换机绑定
channel.queueBind(queue_name, exchange_name, "");
channel.basicQos(1);
//定义消费者
QueueingConsumer consumer = new QueueingConsumer(channel);
//定义回复方式
channel.basicConsume(queue_name, false, consumer);
while(true){
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String msg = "发布订阅模式-消费者2"+new String(delivery.getBody());
System.out.println(msg);
channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
}
}
}
路由模式
说明:路由模式是发布订阅模式的升级版.根据不同的路由key实现消息的发送.
作用:
可以根据功能模块的业务不同,发往不同的队列中.
代码:
public class TestRabbitMQ_4_redirect {
//发布订阅模式
private Connection connection = null;
//定义rabbit连接池
@Before
public void initConnection() throws IOException{
//定义工厂对象
ConnectionFactory connectionFactory = new ConnectionFactory();
//设定参数
connectionFactory.setHost("192.168.126.146");
connectionFactory.setPort(5672);
connectionFactory.setVirtualHost("/jt");
connectionFactory.setUsername("jtadmin");
connectionFactory.setPassword("jtadmin");
//创建连接
connection = connectionFactory.newConnection();
}
//定义生产者
@Test
public void proverder() throws IOException{
Channel channel = connection.createChannel();
//定义交换机名称
String exchange_name = "redirect";
//定义发布订阅模式 fanout direct 路由模式 topic 主题模式
channel.exchangeDeclare(exchange_name, "direct");
for(int i=0;i<10; i++){
String msg = "生产者发送消息"+i;
String rontKey = "1707B";
/**
* exchange:交换机名称
* routingKey:路由key
* props:参数
* body:发送消息
*/
channel.basicPublish(exchange_name, rontKey, null, msg.getBytes());
}
channel.close();
connection.close();
}
/**
* 消费者需要定义队列名称 并且与交换机绑定
* @throws IOException
* @throws InterruptedException
* @throws ConsumerCancelledException
* @throws ShutdownSignalException
*/
@Test
public void consumer1() throws IOException, ShutdownSignalException, ConsumerCancelledException, InterruptedException{
//定义通道
Channel channel = connection.createChannel();
//定义交换机名称
String exchange_name = "redirect";
//定义队列名称
String queue_name = "c_r_1";
//定义交换机模式
channel.exchangeDeclare(exchange_name, "direct");
//定义队列
channel.queueDeclare(queue_name, false, false, false, null);
//将队列和交换机绑定
/**
* 参数介绍:
* queue:队列名称
* exchange:交换机名称
* routingKey:路由key
*/
//channel.queueBind(queue, exchange, routingKey)
channel.queueBind(queue_name, exchange_name, "1707A");
//定义消费个数
channel.basicQos(1);
//定义消费者
QueueingConsumer consumer = new QueueingConsumer(channel);
//绑定消息与消费者
channel.basicConsume(queue_name, false, consumer);
while(true){
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String msg = "路由模式-消费者1"+new String(delivery.getBody());
System.out.println(msg);
//手动回复 一个一个回复
channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
}
}
/**
* 消费者需要定义队列名称 并且与交换机绑定
* @throws IOException
* @throws InterruptedException
* @throws ConsumerCancelledException
* @throws ShutdownSignalException
*/
@Test
public void consumer2() throws IOException, ShutdownSignalException, ConsumerCancelledException, InterruptedException{
Channel channel = connection.createChannel();
String exchange_name = "redirect";
String queue_name = "c_r_2";
//定义交换机模式
channel.exchangeDeclare(exchange_name, "direct");
//定义队列
channel.queueDeclare(queue_name, false, false, false, null);
//将队列和交换机绑定
channel.queueBind(queue_name, exchange_name, "1707B");
channel.basicQos(1);
//定义消费者
QueueingConsumer consumer = new QueueingConsumer(channel);
//定义回复方式
channel.basicConsume(queue_name, false, consumer);
while(true){
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String msg = "路由模式-消费者2"+new String(delivery.getBody());
System.out.println(msg);
channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
}
}
}
主题模式
说明:
主题模式是路由模式的升级版,只要满足条件的路由key,都可以接收消息.
通配符的格式:
号:匹配一个或一组字符(以.分割)
#号.能够匹配任意的字符.
例子:
Item.update.aabb item.# 可以匹配
Item.update item.# item. 都可以匹配
代码:
//主题模式
public class TestRabbitMQ_5_topic {
private Connection connection = null;
@Before
public void initConnection() throws IOException{
//1.定义ConnectionFactory对象
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("192.168.126.146");
connectionFactory.setPort(5672);
connectionFactory.setVirtualHost("/jt");
connectionFactory.setUsername("jtadmin");
connectionFactory.setPassword("jtadmin");
//获取连接
connection = connectionFactory.newConnection();
}
//定义生产者
@Test
public void proverder() throws Exception{
//获取通道
Channel channel = connection.createChannel();
//定义交换机的名称
String exchange_name = "TOP";
//创建交换机队列
//exchange 交换机名称
//type 定义类型 fanout 发布订阅模式 direct-路由模式 topic-主题模式
channel.exchangeDeclare(exchange_name, "topic"); //主题模式
for (int i = 0; i < 100; i++) {
String msg = "主题模式"+i;
/**
* 参数说明:
* exchange:交换机名称
* routingKey:路由key
* props:参数
* body:数据字节码
*/
//channel.basicPublish(exchange, routingKey, props, body);
channel.basicPublish(exchange_name,"item.update", null, msg.getBytes());
}
channel.close();
connection.close();
}
@Test
public void consumer1() throws Exception{
//定义通道
Channel channel = connection.createChannel();
//定义交换机名称
String exchange_name = "TOP";
//定义队列名称
String queue_name = "TOP1";
//声明交换机名称以及主题模式
channel.exchangeDeclare(exchange_name, "topic");
//定义队列
channel.queueDeclare(queue_name, false, false, false, null);
//将交换机和队列进行绑定
//参数1.队列名称 参数2交换机名称 参数3 路由key #号匹配多个字符
channel.queueBind(queue_name, exchange_name, "item.#");
channel.basicQos(1); //定义消费数量 1
//定义消费者
QueueingConsumer consumer = new QueueingConsumer(channel);
//将队列和消费者绑定
channel.basicConsume(queue_name, false, consumer); //定义手动回复
while(true){
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
//获取消息队列中的数据
String msg = new String(delivery.getBody());
System.out.println("item.#消费者1:"+msg);
//手动回复
channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
}
}
@Test
public void consumer2() throws Exception{
Channel channel = connection.createChannel();
String exchange_name = "TOP";
String queue_name = "TOP2";
//生命交换机模式
channel.exchangeDeclare(exchange_name, "topic");
//定义队列
channel.queueDeclare(queue_name, false, false, false, null);
//将交换机和队列进行绑定
//参数1.队列名称 参数2交换机名称 参数3定义路由key
channel.queueBind(queue_name, exchange_name, "item.*");
channel.basicQos(1); //定义消费数量 1
//定义消费者
QueueingConsumer consumer = new QueueingConsumer(channel);
channel.basicConsume(queue_name, false, consumer); //定义手动回复
while(true){
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
//获取消息队列中的数据
String msg = new String(delivery.getBody());
System.out.println("item.*消费者2:"+msg);
//定义回执
channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
}
}
}