简单队列
即一个生产者和一个消费者
public class OneToOne {
private static final String HOST = "192.168.101.210";
private static final int PORT = 5672;
private static final String USERNAME = "admin";
private static final String PASSWORD = "123456";
private static final String QUEUENAME = "hello";
@Test
public void mq_producer() throws IOException {
//创建连接工厂
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost(HOST);
connectionFactory.setPort(PORT);
connectionFactory.setUsername(USERNAME);
connectionFactory.setPassword(PASSWORD);
//设置虚拟主机连接
connectionFactory.setVirtualHost("/");
//从虚拟主机中获取一个连接
Connection connection = connectionFactory.newConnection();
//声明通道 一个TCP连接有可能多个通道
Channel channel = connection.createChannel();
//声明队列
channel.queueDeclare(QUEUENAME, false, false, false, null);
//定义需要发送的内容
String msg = "hello rabbitmq2";
//发布消息
channel.basicPublish("",QUEUENAME,null,msg.getBytes());
System.out.println("向"+QUEUENAME+"队列发送了:>>"+msg+"<<");
channel.close();
connection.close();
}
@Test
public void mq_consumer() throws IOException, InterruptedException {
//创建工厂
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost(HOST);
connectionFactory.setPort(PORT);
connectionFactory.setUsername(USERNAME);
connectionFactory.setPassword(PASSWORD);
//设置发送的虚拟主机
connectionFactory.setVirtualHost("/");
//从工厂中获取连接
Connection connection = connectionFactory.newConnection();
//声明通道 一个TCP连接有可能多个通道
Channel channel = connection.createChannel();
//声明队列
channel.queueDeclare(QUEUENAME,false,false,false,null);
//定义队列的消费者
QueueingConsumer queueingConsumer = new QueueingConsumer(channel);
//监听队列
/*
true:表示自动确认,只要消息从队列中获取,无论消费者获取到消息后是否成功消费,都会认为消息已经成功消费
false:表示手动确认,消费者获取消息后,服务器会将该消息标记为不可用状态,等待消费者的反馈,
如果消费者一直没有反馈,那么该消息将一直处于不可用状态,并且服务器会认为该消费者已经挂掉,不会再给其
发送消息,直到该消费者反馈。
*/
channel.basicConsume(QUEUENAME,true,queueingConsumer);
//获取消息
while (true){
QueueingConsumer.Delivery delivery = queueingConsumer.nextDelivery();
String msg = new String(delivery.getBody());
System.out.println("从"+QUEUENAME+"队列中取出了消息:"+msg);
}
}
}
Work模式
即一个生产者多个消费者(work,像给老板打工一样)
/**
*
* 如果设置了手动回复,且未回复消息,那么消息在RabbitMq里面是Unacked状态,
* 每当一个消费者接入,消息会重新变成ready状态重新发送给该消费者,直到接收到回复
* 如果消费者抛了异常,就会中断与消息队列的连接,由于中断与消息队列的连接相当于没有回复
* 消息会重新回到队列中,继续发送给下一个消费者处理
*/
public class OneToMany {
private static final String HOST = "192.168.101.210";
private static final int PORT = 5672;
private static final String USERNAME = "admin";
private static final String PASSWORD = "123456";
private static final String QUEUENAME = "hello";
@Test
public void producer() throws IOException {
//创建连接工厂
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost(HOST);
connectionFactory.setPort(PORT);
connectionFactory.setUsername(USERNAME);
connectionFactory.setPassword(PASSWORD);
connectionFactory.setVirtualHost("/");
//获取连接
Connection connection = connectionFactory.newConnection();
//声明通道
Channel channel = connection.createChannel();
//声明队列
channel.queueDeclare(QUEUENAME,false,false,false,null);
//发送消息
for (int i=0;i<10;i++){
String msg = "OneToMany-->>"+i;
channel.basicPublish("",QUEUENAME,null,msg.getBytes());
}
channel.close();
connection.close();
}
@Test
public void consumer1() throws IOException, InterruptedException {
//创建连接工厂
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost(HOST);
connectionFactory.setPort(PORT);
connectionFactory.setUsername(USERNAME);
connectionFactory.setPassword(PASSWORD);
connectionFactory.setVirtualHost("/");
//获取连接
Connection connection = connectionFactory.newConnection();
//声明通道
Channel channel = connection.createChannel();
//能者多劳模式、服务器会选择处理完消息的消费者继续发送、如不加这句话无论处理完与否、都会按照平均分发的模式
/*概念是每次给同一个消费者只发一条消息,在消费者没有反馈处理完该消息时不会再给该消费者发消息*/
channel.basicQos(1);
//声明队列
channel.queueDeclare(QUEUENAME,false,false,false,null);
//定义该队列的消费者
QueueingConsumer queueingConsumer = new QueueingConsumer(channel);
//监听队列,false为 手动返回消息状态
channel.basicConsume(QUEUENAME,false,queueingConsumer);
while(true){
QueueingConsumer.Delivery delivery = queueingConsumer.nextDelivery();
byte[] body = delivery.getBody();
System.out.println("consumer1接收消息:"+new String(body));
Thread.sleep(10);
//手动返回消息给队列
channel.basicAck(delivery.getEnvelope().getDeliveryTag(),false);
}
}
@Test
public void consumer2() throws IOException, InterruptedException {
//创建连接工厂
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost(HOST);
connectionFactory.setPort(PORT);
connectionFactory.setUsername(USERNAME);
connectionFactory.setPassword(PASSWORD);
connectionFactory.setVirtualHost("/");
//获取连接
Connection connection = connectionFactory.newConnection();
//声明通道
Channel channel = connection.createChannel();
//声明队列
channel.queueDeclare(QUEUENAME,false,false,false,null);
//能者多劳模式、服务器会选择处理完消息的消费者继续发送、如不加这句话无论处理完与否、都会按照平均分发的模式
/*概念是每次给同一个消费者只发一条消息,在消费者没有反馈处理完该消息时不会再给该消费者发消息*/
channel.basicQos(1);
//定义该队列的消费者
QueueingConsumer queueingConsumer = new QueueingConsumer(channel);
//监听队列,false为 手动返回消息状态
channel.basicConsume(QUEUENAME,false,queueingConsumer);
while(true){
QueueingConsumer.Delivery delivery = queueingConsumer.nextDelivery();
byte[] body = delivery.getBody();
System.out.println("consumer1接收消息:"+new String(body));
Thread.sleep(20);
//手动返回消息给队列
channel.basicAck(delivery.getEnvelope().getDeliveryTag(),false);
}
}
}
发布订阅
即一个生产者发布,多个消费者共享
/**
* 发布订阅模式,如果某个消费者挂掉,消息还是会直接存储在队列中,实际情况和一对多消费模式一样
* 交换机一定要绑定队列,否则消息发送到交换机就会直接丢失(只有队列才有存储的功能)
*/
public class PublishSubscribe {
private static final String HOST = "192.168.101.210";
private static final int PORT = 5672;
private static final String USERNAME = "admin";
private static final String PASSWORD = "123456";
private static final String QUEUENAME = "hello";
private static final String QUEUENAME2 = "hello2";
private static final String EXCHANGE_NAME = "fanout_exchange";
@Test
public void producer() throws IOException {
//创建连接工厂
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost(HOST);
connectionFactory.setPort(PORT);
connectionFactory.setUsername(USERNAME);
connectionFactory.setPassword(PASSWORD);
connectionFactory.setVirtualHost("/");
//获取连接
Connection connection = connectionFactory.newConnection();
//获取通道
Channel channel = connection.createChannel();
//声明交换机 名字和类型
channel.exchangeDeclare(EXCHANGE_NAME,"fanout");
for(int i=0;i<10;i++){
//创建消息
String msg = "hello exchange"+i;
//发布消息
channel.basicPublish(EXCHANGE_NAME,"",null,msg.getBytes());
}
channel.close();
connection.close();
}
@Test
public void consumer1() throws IOException, InterruptedException {
//创建连接工厂
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost(HOST);
connectionFactory.setPort(PORT);
connectionFactory.setUsername(USERNAME);
connectionFactory.setPassword(PASSWORD);
connectionFactory.setVirtualHost("/");
//获取连接
Connection connection = connectionFactory.newConnection();
//获取通道
Channel channel = connection.createChannel();
//声明队列
channel.queueDeclare(QUEUENAME,false,false,false,null);
//绑定队列到交换机
channel.queueBind(QUEUENAME,EXCHANGE_NAME,"");
//服务器每次只发送一条消息给一个消费者
channel.basicQos(1);
//定义队列的消费者
QueueingConsumer queueingConsumer = new QueueingConsumer(channel);
//监听队列,手动返回状态
channel.basicConsume(QUEUENAME,false,queueingConsumer);
while(true){
QueueingConsumer.Delivery delivery = queueingConsumer.nextDelivery();
System.out.println("consumer1消费消息:>>>"+new String(delivery.getBody()));
//手动返回消息给服务器
channel.basicAck(delivery.getEnvelope().getDeliveryTag(),false);
}
}
@Test
public void consumer2() throws IOException, InterruptedException {
//创建连接工厂
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost(HOST);
connectionFactory.setPort(PORT);
connectionFactory.setUsername(USERNAME);
connectionFactory.setPassword(PASSWORD);
connectionFactory.setVirtualHost("/");
//获取连接
Connection connection = connectionFactory.newConnection();
//获取通道
Channel channel = connection.createChannel();
//声明队列
channel.queueDeclare(QUEUENAME2,false,false,false,null);
//绑定队列到交换机
channel.queueBind(QUEUENAME2,EXCHANGE_NAME,"");
//服务器每次只发送一条消息给一个消费者
channel.basicQos(1);
//定义队列的消费者
QueueingConsumer queueingConsumer = new QueueingConsumer(channel);
//监听队列,手动返回状态
channel.basicConsume(QUEUENAME2,false,queueingConsumer);
while(true){
QueueingConsumer.Delivery delivery = queueingConsumer.nextDelivery();
System.out.println("consumer2消费消息:>>>"+new String(delivery.getBody()));
//手动返回消息给服务器
channel.basicAck(delivery.getEnvelope().getDeliveryTag(),false);
}
}
}
路由模式
即一个生产者,有选择的发送给多个消费者
public class Route {
private static final String HOST = "192.168.101.210";
private static final int PORT = 5672;
private static final String USERNAME = "admin";
private static final String PASSWORD = "123456";
private static final String QUEUENAME = "hello";
private static final String QUEUENAME2 = "hello2";
private static final String EXCHANGE_NAME = "direct_exchange";
@Test
public void producer() throws IOException {
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost(HOST);
connectionFactory.setPort(PORT);
connectionFactory.setUsername(USERNAME);
connectionFactory.setPassword(PASSWORD);
connectionFactory.setVirtualHost("/");
Connection connection = connectionFactory.newConnection();
//声明信道
Channel channel = connection.createChannel();
//声明交换机类型为direct
channel.exchangeDeclare(EXCHANGE_NAME,"direct");
//创建消息
String msg = "Hello Direct !";
Student s = new Student();
s.setId(1);
s.setName("呵呵呵吧");
//发布消息
channel.basicPublish(EXCHANGE_NAME,"select",null,Student.ObjectToByte(s));
System.out.println("生产者发送了:"+msg);
//关闭通道
channel.close();
//关闭连接
connection.close();
}
@Test
public void consumer1() throws IOException, InterruptedException {
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost(HOST);
connectionFactory.setPort(PORT);
connectionFactory.setUsername(USERNAME);
connectionFactory.setPassword(PASSWORD);
connectionFactory.setVirtualHost("/");
Connection connection = connectionFactory.newConnection();
//声明信道
Channel channel = connection.createChannel();
//声明队列
channel.queueDeclare(QUEUENAME,false,false,false,null);
//把队列绑定到交换机上,指定路由Key
channel.queueBind(QUEUENAME,EXCHANGE_NAME,"update");
channel.queueBind(QUEUENAME,EXCHANGE_NAME,"delete");
channel.queueBind(QUEUENAME,EXCHANGE_NAME,"add");
//同一时刻只发送一条消息给消费者
channel.basicQos(1);
//定义队列的消费者
QueueingConsumer queueingConsumer = new QueueingConsumer(channel);
//监听队列,手动返回完成状态
channel.basicConsume(QUEUENAME,false,queueingConsumer);
//获取消息
while(true){
QueueingConsumer.Delivery delivery = queueingConsumer.nextDelivery();
byte[] body = delivery.getBody();
System.out.println("消费者1接收到消息:"+new String(body,"UTF-8"));
//返回消息确认状态
channel.basicAck(delivery.getEnvelope().getDeliveryTag(),false);
}
}
@Test
public void consumer2() throws Exception {
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost(HOST);
connectionFactory.setPort(PORT);
connectionFactory.setUsername(USERNAME);
connectionFactory.setPassword(PASSWORD);
connectionFactory.setVirtualHost("/");
Connection connection = connectionFactory.newConnection();
//声明通道
Channel channel = connection.createChannel();
//声明队列
channel.queueDeclare(QUEUENAME2,false,false,false,null);
//绑定队列到交换机,声明key为select
channel.queueBind(QUEUENAME2,EXCHANGE_NAME,"select");
//同一时刻只发送一条消息给消费者
channel.basicQos(1);
//定义队列的消费者
QueueingConsumer queueingConsumer = new QueueingConsumer(channel);
//监听队列,手动返回消息状态
channel.basicConsume(QUEUENAME2,false,queueingConsumer);
//获取消息
while(true){
QueueingConsumer.Delivery delivery = queueingConsumer.nextDelivery();
byte[] body = delivery.getBody();
System.out.println("消费者2接收到消息:"+Student.ByteToObject(body));
//手动返回确认状态
channel.basicAck(delivery.getEnvelope().getDeliveryTag(),false);
}
}
}
主题模式
和路由模式一样,不过消费者可以模糊匹配key来选择接收的消息
public class Topic {
private static final String HOST = "192.168.101.210";
private static final int PORT = 5672;
private static final String USERNAME = "admin";
private static final String PASSWORD = "123456";
private static final String QUEUENAME = "hello";
private static final String QUEUENAME2 = "hello2";
private static final String EXCHANGE_NAME = "topic_exchange";
@Test
public void producer() throws IOException {
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost(HOST);
connectionFactory.setPort(PORT);
connectionFactory.setUsername(USERNAME);
connectionFactory.setPassword(PASSWORD);
connectionFactory.setVirtualHost("/");
Connection connection = connectionFactory.newConnection();
//声明信道
Channel channel = connection.createChannel();
//声明交换机类型为direct
channel.exchangeDeclare(EXCHANGE_NAME,"topic");
//创建消息
String msg = "Hello Topic !";
Student s = new Student();
s.setId(1);
s.setName("呵呵呵吧");
//发布消息
channel.basicPublish(EXCHANGE_NAME,"select.from",null,Student.ObjectToByte(s));
System.out.println("生产者发送了:"+msg);
//关闭通道
channel.close();
//关闭连接
connection.close();
}
@Test
public void consumer1() throws IOException, InterruptedException {
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost(HOST);
connectionFactory.setPort(PORT);
connectionFactory.setUsername(USERNAME);
connectionFactory.setPassword(PASSWORD);
connectionFactory.setVirtualHost("/");
Connection connection = connectionFactory.newConnection();
//声明信道
Channel channel = connection.createChannel();
//声明队列
channel.queueDeclare(QUEUENAME,false,false,false,null);
//把队列绑定到交换机上,指定路由Key
channel.queueBind(QUEUENAME,EXCHANGE_NAME,"update.#");
//同一时刻只发送一条消息给消费者
channel.basicQos(1);
//定义队列的消费者
QueueingConsumer queueingConsumer = new QueueingConsumer(channel);
//监听队列,手动返回完成状态
channel.basicConsume(QUEUENAME,false,queueingConsumer);
//获取消息
while(true){
QueueingConsumer.Delivery delivery = queueingConsumer.nextDelivery();
byte[] body = delivery.getBody();
System.out.println("消费者1接收到消息:"+new String(body,"UTF-8"));
//返回消息确认状态
channel.basicAck(delivery.getEnvelope().getDeliveryTag(),false);
}
}
@Test
public void consumer2() throws Exception {
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost(HOST);
connectionFactory.setPort(PORT);
connectionFactory.setUsername(USERNAME);
connectionFactory.setPassword(PASSWORD);
connectionFactory.setVirtualHost("/");
Connection connection = connectionFactory.newConnection();
//声明通道
Channel channel = connection.createChannel();
//声明队列
channel.queueDeclare(QUEUENAME2,false,false,false,null);
//绑定队列到交换机,声明key为select
channel.queueBind(QUEUENAME2,EXCHANGE_NAME,"select.#");
//同一时刻只发送一条消息给消费者
channel.basicQos(1);
//定义队列的消费者
QueueingConsumer queueingConsumer = new QueueingConsumer(channel);
//监听队列,手动返回消息状态
channel.basicConsume(QUEUENAME2,false,queueingConsumer);
//获取消息
while(true){
QueueingConsumer.Delivery delivery = queueingConsumer.nextDelivery();
byte[] body = delivery.getBody();
System.out.println("消费者2接收到消息:"+Student.ByteToObject(body));
//手动返回确认状态
channel.basicAck(delivery.getEnvelope().getDeliveryTag(),false);
}
}
}