消息队列可以导入导出
生产者代码
package com.zzj.rabbitmq.simple;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
public class Producer {
private static String QUEUE_NAME = "simple_queue";
public static void main(String[] args) throws Exception {
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("192.168.80.128");
connectionFactory.setPort(5672);
connectionFactory.setVirtualHost("/xzk");
connectionFactory.setUsername("zzj");
connectionFactory.setPassword("zzj");
Connection connection = connectionFactory.newConnection();
Channel channel = connection.createChannel();
/***
* 参数1:队列名称
* 参数2:是否定义持久化队列
* 参数3:是否独占本次连接
* 参数4:是否在不使用的时候自动删除队列
* 参数5:队列其它参数
* */
channel.queueDeclare(QUEUE_NAME, true, false, false, null);
String message = "你好:小兔子";
/*** 参数1:交换机名称,如果没有指定则使用默认Default Exchage *
* 参数2:路由key,简单模式可以传递队列名称 *
* 参数3:消息其它属性 *
* 参数4:消息内容 */
for(int i = 0;i < 10;i++) {
channel.basicPublish("", QUEUE_NAME, null, message.getBytes());
}
System.out.println("已发送消息");
channel.close();
connection.close();
}
}
一对一的消费模式
运行测试
消费者代码,不能关闭资源
package com.zzj.rabbitmq.simple;
import com.rabbitmq.client.*;
import java.io.IOException;
public class Consumer {
private static String QUEUE_NAME = "simple_queue";
public static void main(String[] args) throws Exception {
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("192.168.80.128");
connectionFactory.setPort(5672);
connectionFactory.setVirtualHost("/xzk");
connectionFactory.setUsername("zzj");
connectionFactory.setPassword("zzj");
Connection connection = connectionFactory.newConnection();
Channel channel = connection.createChannel();
/*
* 参数1:队列名称
* 参数2:是否定义持久化队列
* 参数3:是否独占本次连接
* 参数4:是否在不使用的时候自动删除队列
* 参数5:队列其它参数
* */
channel.queueDeclare(QUEUE_NAME, true, false, false, null);
//接收消息
DefaultConsumer defaultConsumer = new DefaultConsumer(channel){
/*** consumerTag 消息者标签,在channel.basicConsume时候可以指定 *
* envelope 消息包的内容,可从中获取消息id,消息
* routingkey,交换机,消息和重 传标志(收到消息失败后是否需要重新发送) *
* properties 属性信息 *
* body 消息 */
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
//路由key
System.out.println("路由key为:" + envelope.getRoutingKey());
//交换机
System.out.println("交换机为:" + envelope.getExchange());
//消息id
System.out.println("消息id为:" + envelope.getDeliveryTag());
//收到的消息
System.out.println("接收到的消息为:" + new String(body, "utf-8"));
}
};
/* 参数1:队列名称 *
* 参数2:是否自动确认,设置为true为表示消息接收到自动向mq回复接收到了,mq接收到回复 会删除消息,设置为false则需要手动确认 *
* 参数3:消息接收到后回调 */
channel.basicConsume(QUEUE_NAME, true, defaultConsumer);
// channel.close();
// connection.close();
}
}
直接运行
资源消费后,变成了0
工作队列模式
生产者生产 30个消息
消费者1
消费者 2
消费者之间是一种竞争的关系
发布和订阅模式
多了 一个组件 : Exchange: 不存储,只转发
Exchange: 交换机,图中的X。一方面,接收生产者发送的消息。另一方面,知道如何处理消息,例如递交给某个特别的队列、递交给所有的队列、或是将消息丢弃
到底如何操作,取决于Exchange的类型
生产者发送10个消息给Exchange,X会将这10个消息,分别发给两个队列,两个队列中分别各有10个消息,每一个C都有10个消息
Routing路由模式
路由模式的特点:
队列和交换机的绑定,不能是任意绑定的了。而是要指定一个RoutingKey(路由key)
消息的发送方在向X发送消息的时,也必须指定消息的RoutingKey
X不再把消息交给每一个绑定的队列,而是根据消息的Routing key 进行判断,只有队列的Routingkey和消息的routingkey一致,才会接收到消息
topic 模式
Topic类型和Direct类型相比,都是可以根据RoutingKey把消息路由到不同的队列,只不过Topic类型的Exchange可以让队列在绑定 Routing key 的时候使用通配符!
由于C1绑定的是item.*
由于c2只绑定了 update和delete ,所以只能接受这两个