2.7日学习打卡----初学RabbitMQ(二)
2.7日学习打卡
JMS
由于MQ产品很多,操作方式各有不同,于是JAVA提供了一套规则
——JMS,用于操作消息中间件。JMS即Java消息服务
(JavaMessage Service)应用程序接口,是一个Java平台中关于面
向消息中间件的API。JMS是JavaEE规范中的一种,类比JDBC。很多
MQ产品都实现了JMS规范,例如ActiveMQ。RabbitMQ官方并没
有实现JMS规范,但是开源社区有JMS的实现包。
创建项目
# 开启管控台插件
rabbitmq-plugins enable
rabbitmq_management
# 启动rabbitmq
rabbitmq-server -detached
创建普通maven项目,添加RabbitMQ依赖:
<dependencies><dependency><groupId>com.rabbitmq</groupId><artifactId>amqpclient</artifactId><version>5.14.0</version></dependency>
</dependencies>
一. RabbitMQ 简单模式
P:生产者,也就是要发送消息的程序
C:消费者:消息的接收者,会一直等待消息到来
queue:消息队列,图中红色部分。类似一个邮箱,可以缓存消息;生产者向其中投递消息,消费者从其中取出消息
特点:
- 一个生产者对应一个消费者,通过队列进行消息传递。
- 该模式使用direct交换机,direct交换机是RabbitMQ默认交换机
生产者代码实现
步骤:
- 创建连接工厂ConnectionFactory
- 设置工厂的参数
- 创建连接 Connection
- 创建管道 Channel
- 简单模式中没有交换机exchange,所以不用创建(RabbitMQ会使用默认的交换机!)
- 创建队列 queue
- 设置发送内容,使用channal.basicPublish()发送
- 释放资源
代码实现
package com.jjy.mq.simple;import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;import java.io.IOException;
import java.util.concurrent.TimeoutException;//生产者
public class Producer {public static void main(String[] args) throws IOException, TimeoutException {//1.创建连接工厂ConnectionFactory connectionFactory = new ConnectionFactory();//使用自己的服务器ip地址connectionFactory.setHost("192.168.66.100");//rabbitmq的默认端口5672connectionFactory.setPort(5672);//用户名connectionFactory.setUsername("jjy");//密码connectionFactory.setPassword("jjy");//虚拟机connectionFactory.setVirtualHost("/");//2.创建连接Connection connection = connectionFactory.newConnection();//3.建立信道Channel channel = connection.createChannel();//4.创建队列,如果队列已存在,则使用该队列/**// * 参数1:队列名// * 参数2:是否持久化,true表示MQ重启后队列还在。// * 参数3:是否私有化,false表示所有消费者都可以访问,true表示只有第一次拥有它的消费者才能访问// * 参数4:是否自动删除,true表示不再使用队列时自动删除队列// * 参数5:其他额外参数// */channel.queueDeclare("simple_queue",false,false,false,null);//5.发送消息String mesg="hello rabbitmq";/*** 参数1:交换机名,""表示默认交换机* 参数2:路由键,简单模式就是队列名* 参数3:其他额外参数* 参数4:要传递的消息字节数组*/channel.basicPublish("","simple_queue",null,mesg.getBytes());//6.关闭资源(信道和连接)channel.close();connection.close();System.out.println("发送成功");}
}
消费者代码实现
步骤:
1.创建连接工厂ConnectionFactory
2.设置工厂参数
3.创建连接
4.创建信道
前四步代码基本是一致的,需要注意的是生产者与消费者的Channel是不同Connection中的!不是同一个对象.
5. 最简单的模型没有交换机exchange,所以此处RabbitMQ会使用默认的交换机
6. 接收消息,有一个回调方法 channel.basicConsume()
代码实现
package com.jjy.mq.simple;import com.rabbitmq.client.*;import java.io.IOException;
import java.util.concurrent.TimeoutException;public class Customer {public static void main(String[] args) throws IOException, TimeoutException {//1.创建连接工厂ConnectionFactory connectionFactory = new ConnectionFactory();connectionFactory.setHost("192.168.66.100");connectionFactory.setPort(5672);connectionFactory.setUsername("jjy");connectionFactory.setPassword("jjy");connectionFactory.setVirtualHost("/");//2.创建连接Connection connection = connectionFactory.newConnection();//3.建立信道Channel channel = connection.createChannel();//4.监听队列/*** 参数1:监听的队列名* 参数2:是否自动签收,如果设置为false,则需要手动确认消息已收到,否则MQ会一直发送消息* 参数3:Consumer的实现类,重写该类方法表示接受到消息后如何消费*/channel.basicConsume("simple_queue",true,new DefaultConsumer(channel){@Overridepublic void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {String message = new String(body,"UTF-8");System.out.println("接受消息,消息为:"+message);}});//}
}
二. RabbitMQ 工作队列模式
与简单模式相比,工作队列模式(Work Queue)多了一些消费者,该
模式也使用direct交换机,应用于处理消息较多的情况。特点如
下:
- 一个队列对应多个消费者。
- 一条消息只会被一个消费者消费。
- 消息队列默认采用轮询的方式将消息平均发送给消费者
应用场景:对于任务过重或任务较多情况使用工作队列可以提高任务处理的速度
生产者代码实现
代码实现
package com.jjy.mq.work;import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.MessageProperties;import java.io.IOException;
import java.util.concurrent.TimeoutException;public class Producer {public static void main(String[] args) throws IOException, TimeoutException {// 1.创建连接工厂ConnectionFactory connectionFactory = new ConnectionFactory();connectionFactory.setHost("192.168.66.100");connectionFactory.setPort(5672);connectionFactory.setUsername("jjy");connectionFactory.setPassword("jjy");connectionFactory.setVirtualHost("/");// 2.创建连接Connection connection = connectionFactory.newConnection();// 3.建立信道Channel channel = connection.createChannel();// 4.创建队列,持久化队列channel.queueDeclare("work_queue",true,false,false,null);// 5.发送大量消息,参数3表示该消息为持久化消息,即除了保存到内存还会保存到磁盘中for(int i=0;i<100;i++){channel.basicPublish("","work_queue", MessageProperties.PERSISTENT_TEXT_PLAIN, ("你好,这是今天的第"+i+"条消息").getBytes());}// 6.关闭资源channel.close();connection.close();}
}
消费者代码实现
消费者1:
package com.jjy.mq.work;import com.rabbitmq.client.*;import java.io.IOException;
import java.util.concurrent.TimeoutException;public class Customer1 {public static void main(String[] args) throws IOException, TimeoutException {//1.创建连接工厂ConnectionFactory connectionFactory = new ConnectionFactory();connectionFactory.setHost("192.168.66.100");connectionFactory.setPort(5672);connectionFactory.setUsername("jjy");connectionFactory.setPassword("jjy");connectionFactory.setVirtualHost("/");//2.创建连接Connection connection = connectionFactory.newConnection();//3.建立信道Channel channel = connection.createChannel();// 4.监听队列,处理消息channel.basicConsume("work_queue",true,new DefaultConsumer(channel){@Overridepublic void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {String message = new String(body, "UTF-8");System.out.println("消费者1消费消息,消息为:" + message);}});}
}
消费者2
package com.jjy.mq.work;import com.rabbitmq.client.*;import java.io.IOException;
import java.util.concurrent.TimeoutException;public class Customer2 {public static void main(String[] args) throws IOException, TimeoutException {//1.创建连接工厂ConnectionFactory connectionFactory = new ConnectionFactory();connectionFactory.setHost("192.168.66.100");connectionFactory.setPort(5672);connectionFactory.setUsername("jjy");connectionFactory.setPassword("jjy");connectionFactory.setVirtualHost("/");//2.创建连接Connection connection = connectionFactory.newConnection();//3.建立信道Channel channel = connection.createChannel();// 4.监听队列,处理消息channel.basicConsume("work_queue",true,new DefaultConsumer(channel){@Overridepublic void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {String message = new String(body, "UTF-8");System.out.println("消费者2消费消息,消息为:" + message);}});}}
消费者3
package com.jjy.mq.work;import com.rabbitmq.client.*;import java.io.IOException;
import java.util.concurrent.TimeoutException;public class Customer3 {public static void main(String[] args) throws IOException, TimeoutException {//1.创建连接工厂ConnectionFactory connectionFactory = new ConnectionFactory();connectionFactory.setHost("192.168.66.100");connectionFactory.setPort(5672);connectionFactory.setUsername("jjy");connectionFactory.setPassword("jjy");connectionFactory.setVirtualHost("/");//2.创建连接Connection connection = connectionFactory.newConnection();//3.建立信道Channel channel = connection.createChannel();// 4.监听队列,处理消息channel.basicConsume("work_queue",true,new DefaultConsumer(channel){@Overridepublic void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {String message = new String(body, "UTF-8");System.out.println("消费者3消费消息,消息为:" + message);}});}}
三. RabbitMQ 发布订阅模式
P:生产者,也就是要发送消息的程序,但是不再发送到队列中,而是发给X(交换机
C:消费者,消息的接收者,会一直等待消息到来
Queue:消息队列,接收消息、缓存消息
在开发过程中,有一些消息需要不同消费者进行不同的处理,如电
商网站的同一条促销信息需要短信发送、邮件发送、站内信发送
等。此时可以使用发布订阅模式(Publish/Subscribe)
特点:
- 生产者将消息发送给交换机,交换机将消息转发到绑定此交换机的每个队列中。
- 工作队列模式的交换机只能将消息发送给一个队列,发布订阅模式的交换机能将消息发送给多个队列。发布订阅模式使用fanout交换机。
Exchange:交换机(X)一方面,接收生产者发送的消息。另一方面,知道如何处理消息,例如递交给某个特别队列、 递交给所有队列、或是将消息丢弃。到底如何操作,取决于Exchange的类型。Exchange有常见以下3种类型:
➢ Fanout:广播,将消息交给所有绑定到交换机的队列
➢ Direct:定向,把消息交给符合指定routing key 的队列
➢ Topic(常用):通配符,把消息交给符合routing pattern(路由模式)的队列
Exchange(交换机)只负责转发消息,不具备存储消息的能力,因此如果没有任何队列与 Exchange 绑定,或者没有符合路由规则的队列,那么消息会丢失!
生产者代码实现
与之前的步骤相比,多了创建交换机和绑定交换机与队列的操作
代码实现
package com.jjy.mq.publish;import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeoutException;public class produce {public static void main(String[] args) throws IOException, TimeoutException {//1.创建连接工厂ConnectionFactory connectionFactory = new ConnectionFactory();connectionFactory.setHost("192.168.66.100");connectionFactory.setPort(5672);connectionFactory.setUsername("jjy");connectionFactory.setPassword("jjy");connectionFactory.setVirtualHost("/");//2.创建连接Connection connection = connectionFactory.newConnection();//3.建立信道Channel channel = connection.createChannel();//4.创建交换机/*exchangeDeclare(String exchange, -- 交换机的名称String type, -- 交换机的类型,4种枚举(direct,fanout,topic,headers)boolean durable, -- 持久化boolean autoDelete, -- 自动删除boolean internal, -- 内部使用,基本是falseMap<String, Object> arguments) -- 参数*/*** 参数1:交换机名* 参数2:交换机类型* 参数3:交换机持久化*/channel.exchangeDeclare("exchange_fanout", BuiltinExchangeType.FANOUT,true);//5.创建队列//短信队列channel.queueDeclare("SEND_MAIL",true,false,false,null);//消息队列channel.queueDeclare("SEND_MESSAGE",true,false,false,null);//站内信息channel.queueDeclare("SEND_STATION",true,false,false,null);//6.交换机绑定队列/*** 参数1:队列名* 参数2:交换机名* 参数3:路由关键字,发布订阅模式写""即可*/channel.queueBind("SEND_MAIL","exchange_fanout","");channel.queueBind("SEND_MESSAGE","exchange_fanout","");channel.queueBind("SEND_STATION","exchange_fanout","");//7.发送消息for (int i = 1; i <= 10 ; i++) {channel.basicPublish("exchange_fanout","",null,("你好,尊敬的用户,秒杀商品开抢了!"+i).getBytes(StandardCharsets.UTF_8));}//8.关闭资源channel.close();connection.close();}
}
消费者代码实现
接下来编写三个消费者,分别监听各自的队列。
//站内信消费者
package com.jjy.mq.publish;import com.rabbitmq.client.*;import java.io.IOException;
import java.util.concurrent.TimeoutException;// 站内信消费者
public class CustomerStation {public static void main(String[] args) throws IOException, TimeoutException {// 1.创建连接工厂ConnectionFactory connectionFactory = new ConnectionFactory();connectionFactory.setHost("192.168.66.100");connectionFactory.setPort(5672);connectionFactory.setUsername("jjy");connectionFactory.setPassword("jjy");connectionFactory.setVirtualHost("/");// 默认虚拟机//2.创建连接Connection conn = connectionFactory.newConnection();//3.建立信道Channel channel = conn.createChannel();// 4.监听队列channel.basicConsume("SEND_STATION", true, new DefaultConsumer(channel) {@Overridepublic void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {String message = new String(body, "utf-8");System.out.println("发送站内信:"+message);}});}
}
邮件消费者
package com.jjy.mq.publish;import com.rabbitmq.client.*;import java.io.IOException;
import java.util.concurrent.TimeoutException;public class CustomerMail {public static void main(String[] args) throws IOException, TimeoutException {// 1.创建连接工厂ConnectionFactory connectionFactory = new ConnectionFactory();connectionFactory.setHost("192.168.66.100");connectionFactory.setPort(5672);connectionFactory.setUsername("jjy");connectionFactory.setPassword("jjy");connectionFactory.setVirtualHost("/");// 默认虚拟机//2.创建连接Connection conn = connectionFactory.newConnection();//3.建立信道Channel channel = conn.createChannel();// 4.监听队列channel.basicConsume("SEND_MAIL", true, new DefaultConsumer(channel) {@Overridepublic void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {String message = new String(body, "utf-8");System.out.println("发送邮件:"+message);}});}
}
短信消费者
package com.jjy.mq.publish;import com.rabbitmq.client.*;import java.io.IOException;
import java.util.concurrent.TimeoutException;public class CustomerMessage {public static void main(String[] args) throws IOException, TimeoutException {// 1.创建连接工厂ConnectionFactory connectionFactory = new ConnectionFactory();connectionFactory.setHost("192.168.66.100");connectionFactory.setPort(5672);connectionFactory.setUsername("jjy");connectionFactory.setPassword("jjy");connectionFactory.setVirtualHost("/");// 默认虚拟机//2.创建连接Connection conn = connectionFactory.newConnection();//3.建立信道Channel channel = conn.createChannel();// 4.监听队列channel.basicConsume("SEND_MESSAGE", true, new DefaultConsumer(channel) {@Overridepublic void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {String message = new String(body, "utf-8");System.out.println("发送短信:"+message);}});}
}
也可以使用工作队列+发布订阅模式同时使用,两个消费者同时监听
一个队列:
// 短信消费者2
public class CustomerMessage2 {public static void main(String[] args) throws IOException, TimeoutException {// 1.创建连接工厂ConnectionFactory connectionFactory = new ConnectionFactory();connectionFactory.setHost("192.168.0.162");connectionFactory.setPort(5672);connectionFactory.setUsername("itbaizhan");connectionFactory.setPassword("itbaizhan");connectionFactory.setVirtualHost("/");// 默认虚拟机//2.创建连接Connection conn = connectionFactory.newConnection();//3.建立信道Channel channel = conn.createChannel();// 4.监听队列channel.basicConsume("SEND_MESSAGE", true, new DefaultConsumer(channel) {@Overridepublic void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {String message = new String(body, "utf-8");System.out.println("发送短信2:"+message);}});}
}
两个不一样的系统,对同一条消息做不一样的处理
发布订阅模式与工作队列模式的区别
(1)工作队列模式不用定义交换机,而发布/订阅模式需要定义交换机
(2)发布/订阅模式的生产方是面向交换机发送消息,工作队列模式的生产方是面向队列发送消息(底层使用 默认交换机)
(3)发布/订阅模式需要设置队列和交换机的绑定,工作队列模式不需要设置,实际上工作队列模式会将队列绑定到默认的交换机
四. RabbitMQ 路由模式
使用发布订阅模式时,所有消息都会发送到绑定的队列中,但很多
时候,不是所有消息都无差别的发布到所有队列中。比如电商网站
的促销活动,双十一大促可能会发布到所有队列;而一些小的促销
活动为了节约成本,只发布到站内信队列。此时需要使用路由模式
(Routing)完成这一需求。
特点:
- 每个队列绑定路由关键字RoutingKey
- 生产者将带有RoutingKey的消息发送给交换机,交换机根据RoutingKey转发到指定队列。路由模
式使用direct交换机。
队列与交换机的绑定,不能是任意绑定了,而是要指定一个 RoutingKey(路由key)
消息的发送方在向 Exchange 发送消息时,也必须指定消息的 RoutingKey
Exchange 不再把消息交给每一个绑定的队列,而是根据消息的 Routing Key 进行判断,只有队列的 Routingkey 与消息的 Routing key 完全一致,才会接收到消息
生产者代码实现
package com.jjy.mq.routing;import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeoutException;public class produce {public static void main(String[] args) throws IOException, TimeoutException {//1.创建连接工厂ConnectionFactory connectionFactory = new ConnectionFactory();connectionFactory.setHost("192.168.66.100");connectionFactory.setPort(5672);connectionFactory.setUsername("jjy");connectionFactory.setPassword("jjy");connectionFactory.setVirtualHost("/");//2.创建连接Connection connection = connectionFactory.newConnection();//3.建立信道Channel channel = connection.createChannel();//4.创建交换机/*** 参数1:交换机名* 参数2:交换机类型* 参数3:交换机持久化*/channel.exchangeDeclare("exchange_routing", BuiltinExchangeType.DIRECT,true);// 5.创建队列channel.queueDeclare("SEND_MAIL2",true,false,false,null);channel.queueDeclare("SEND_MESSAGE2",true,false,false,null);channel.queueDeclare("SEND_STATION2",true,false,false,null);//6.交换机绑定队列/*** 参数1:队列名* 参数2:交换机名* 参数3:路由关键字,发布订阅模式写""即可*/channel.queueBind("SEND_MAIL2","exchange_routing","import");channel.queueBind("SEND_MESSAGE2","exchange_routing","import");channel.queueBind("SEND_STATION2","exchange_routing","import");channel.queueBind("SEND_STATION2","exchange_routing","normal");//7.发送消息channel.basicPublish("exchange_routing","import",null,"双十一大促活动".getBytes());channel.basicPublish("exchange_routing","normal",null,"小型促销活动".getBytes());//8.关闭资源channel.close();connection.close();}
}
消费者代码实现
站内信消费者
package com.jjy.mq.routing;import com.rabbitmq.client.*;import java.io.IOException;
import java.util.concurrent.TimeoutException;// 站内信消费者
public class CustomerStation {public static void main(String[] args) throws IOException, TimeoutException {// 1.创建连接工厂ConnectionFactory connectionFactory = new ConnectionFactory();connectionFactory.setHost("192.168.66.100");connectionFactory.setPort(5672);connectionFactory.setUsername("jjy");connectionFactory.setPassword("jjy");connectionFactory.setVirtualHost("/");// 默认虚拟机//2.创建连接Connection conn = connectionFactory.newConnection();//3.建立信道Channel channel = conn.createChannel();// 4.监听队列channel.basicConsume("SEND_STATION2", true, new DefaultConsumer(channel) {@Overridepublic void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {String message = new String(body, "utf-8");System.out.println("发送站内信:"+message);}});}
}
短信消费者
package com.jjy.mq.routing;import com.rabbitmq.client.*;import java.io.IOException;
import java.util.concurrent.TimeoutException;public class CustomerMessage {public static void main(String[] args) throws IOException, TimeoutException {// 1.创建连接工厂ConnectionFactory connectionFactory = new ConnectionFactory();connectionFactory.setHost("192.168.66.100");connectionFactory.setPort(5672);connectionFactory.setUsername("jjy");connectionFactory.setPassword("jjy");connectionFactory.setVirtualHost("/");// 默认虚拟机//2.创建连接Connection conn = connectionFactory.newConnection();//3.建立信道Channel channel = conn.createChannel();// 4.监听队列channel.basicConsume("SEND_MESSAGE2", true, new DefaultConsumer(channel) {@Overridepublic void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {String message = new String(body, "utf-8");System.out.println("发送短信:"+message);}});}
}
邮件消费者
package com.jjy.mq.routing;import com.rabbitmq.client.*;import java.io.IOException;
import java.util.concurrent.TimeoutException;public class CustomerMail {public static void main(String[] args) throws IOException, TimeoutException {// 1.创建连接工厂ConnectionFactory connectionFactory = new ConnectionFactory();connectionFactory.setHost("192.168.66.100");connectionFactory.setPort(5672);connectionFactory.setUsername("jjy");connectionFactory.setPassword("jjy");connectionFactory.setVirtualHost("/");// 默认虚拟机//2.创建连接Connection conn = connectionFactory.newConnection();//3.建立信道Channel channel = conn.createChannel();// 4.监听队列channel.basicConsume("SEND_MAIL2", true, new DefaultConsumer(channel) {@Overridepublic void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {String message = new String(body, "utf-8");System.out.println("发送邮件:"+message);}});}
}
总的来说就一句话:
Routing 模式要求队列在绑定交换机时要指定 routing key,消息会转发到符合 routing key 的队列。
五. RabbitMQ 通配符模式
通配符模式(Topic)是在路由模式的基础上,给队列绑定带通配符的
路由关键字,只要消息的RoutingKey能实现通配符匹配,就会将消
息转发到该队列。通配符模式比路由模式更灵活,使用topic交换
机.
通配符规则:
- 消息设置RoutingKey时,RoutingKey由多个单词构成,中间以 . 分割。
- 队列设置RoutingKey时, # 可以匹配任意多个单词, * 可以匹配任意一个单词。
生产者代码实现
代码实现
package com.jjy.mq.topic;import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;import java.io.IOException;
import java.util.concurrent.TimeoutException;public class produce {public static void main(String[] args) throws IOException, TimeoutException {//1.创建连接工厂ConnectionFactory connectionFactory = new ConnectionFactory();connectionFactory.setHost("192.168.66.100");connectionFactory.setPort(5672);connectionFactory.setUsername("jjy");connectionFactory.setPassword("jjy");connectionFactory.setVirtualHost("/");//2.创建连接Connection connection = connectionFactory.newConnection();//3.建立信道Channel channel = connection.createChannel();//4.创建交换机/*** 参数1:交换机名* 参数2:交换机类型* 参数3:交换机持久化*/channel.exchangeDeclare("exchange_topic", BuiltinExchangeType.TOPIC,true);// 5.创建队列channel.queueDeclare("SEND_MAIL3",true,false,false,null);channel.queueDeclare("SEND_MESSAGE3",true,false,false,null);channel.queueDeclare("SEND_STATION3",true,false,false,null);//6.交换机绑定队列channel.queueBind("SEND_MAIL3","exchange_topic","#.mail.#");channel.queueBind("SEND_MESSAGE3","exchange_topic","#.message.#");channel.queueBind("SEND_STATION3","exchange_topic","#.station.#");//7.发送消息channel.basicPublish("exchange_topic","mail.message.station",null,"双十一大促活动".getBytes());channel.basicPublish("exchange_topic","station",null,"小型促销活动".getBytes());//8.关闭资源channel.close();connection.close();}
}
消费者代码实现
站内信消费者
package com.jjy.mq.topic;import com.rabbitmq.client.*;import java.io.IOException;
import java.util.concurrent.TimeoutException;// 站内信消费者
public class CustomerStation {public static void main(String[] args) throws IOException, TimeoutException {// 1.创建连接工厂ConnectionFactory connectionFactory = new ConnectionFactory();connectionFactory.setHost("192.168.66.100");connectionFactory.setPort(5672);connectionFactory.setUsername("jjy");connectionFactory.setPassword("jjy");connectionFactory.setVirtualHost("/");// 默认虚拟机//2.创建连接Connection conn = connectionFactory.newConnection();//3.建立信道Channel channel = conn.createChannel();// 4.监听队列channel.basicConsume("SEND_STATION3", true, new DefaultConsumer(channel) {@Overridepublic void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {String message = new String(body, "utf-8");System.out.println("发送站内信:"+message);}});}
}
短信消费者
package com.jjy.mq.topic;import com.rabbitmq.client.*;import java.io.IOException;
import java.util.concurrent.TimeoutException;public class CustomerMessage {public static void main(String[] args) throws IOException, TimeoutException {// 1.创建连接工厂ConnectionFactory connectionFactory = new ConnectionFactory();connectionFactory.setHost("192.168.66.100");connectionFactory.setPort(5672);connectionFactory.setUsername("jjy");connectionFactory.setPassword("jjy");connectionFactory.setVirtualHost("/");// 默认虚拟机//2.创建连接Connection conn = connectionFactory.newConnection();//3.建立信道Channel channel = conn.createChannel();// 4.监听队列channel.basicConsume("SEND_MESSAGE3", true, new DefaultConsumer(channel) {@Overridepublic void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {String message = new String(body, "utf-8");System.out.println("发送短信:"+message);}});}
}
邮件消费者
package com.jjy.mq.topic;import com.rabbitmq.client.*;import java.io.IOException;
import java.util.concurrent.TimeoutException;public class CustomerMail {public static void main(String[] args) throws IOException, TimeoutException {// 1.创建连接工厂ConnectionFactory connectionFactory = new ConnectionFactory();connectionFactory.setHost("192.168.66.100");connectionFactory.setPort(5672);connectionFactory.setUsername("jjy");connectionFactory.setPassword("jjy");connectionFactory.setVirtualHost("/");// 默认虚拟机//2.创建连接Connection conn = connectionFactory.newConnection();//3.建立信道Channel channel = conn.createChannel();// 4.监听队列channel.basicConsume("SEND_MAIL3", true, new DefaultConsumer(channel) {@Overridepublic void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {String message = new String(body, "utf-8");System.out.println("发送邮件:"+message);}});}
}
总述:topics模式比routing模式要更加灵活,笼统的说就是routing模式加上通配符
如果我的内容对你有帮助,请点赞,评论,收藏。创作不易,大家的支持就是我坚持下去的动力!
相关文章:

2.7日学习打卡----初学RabbitMQ(二)
2.7日学习打卡 JMS 由于MQ产品很多,操作方式各有不同,于是JAVA提供了一套规则 ——JMS,用于操作消息中间件。JMS即Java消息服务 (JavaMessage Service)应用程序接口,是一个Java平台中关于面 向消息中间件的…...

【工作学习 day04】 9. uniapp 页面和组件的生命周期
问题描述 uniapp常用的有:页面和组件,并且页面和组件各自有各自的生命周期函数,那么在页面/组件请求数据时,是用created呢,还是用onLoad呢? 先说结论: 组件使用组件的生命周期,页面使用页面的…...

Mysql-数据库优化-客户端连接参数
客户端参数 原文地址 # 连接池配置 # 初始化连接数 spring.datasource.druid.initial-size1 # 最小空闲连接数,一般设置和initial-size一致 spring.datasource.druid.min-idle1 # 最大活动连接数,一个数据库能够支撑最大的连接数是多少呢? …...

【十二】【C++】vector用法的探究
vector类创建对象 /*vector类创建对象*/ #if 1 #define _CRT_SECURE_NO_WARNINGS#include <iostream> using namespace std; #include <vector> #include <algorithm> #include <crtdbg.h>class Date {public:Date(int year 1900, int month 1, int …...
Docker 基本介绍
Docker 基本介绍 镜像 Docker镜像就是一个只读的模板。 例如:一个镜像可以包含一个完整的ubuntu操作系统环境,里面仅安装了Apache或用户需要的其它应用 程序。 镜像可以用来创建Docker容器。Docker提供了一个很简单的机制来创建镜像或者更新现有的镜…...
CentOS 7 安装 install abiword
安装 1.下载noarch安装包 wget http://repo.iotti.biz/CentOS/7/noarch/lux-release-7-1.noarch.rpm 2.安装noarch rpm -Uvh lux-release-7-1.noarch.rpm 3.安装abiword yum -y install abiword...
开源的直播平台
直播平台系统界面介绍 开源一套直播平台 私信可获取源码...

ChatGPT 变懒最新解释!或和系统Prompt太长有关
大家好我是二狗。 ChatGPT变懒这件事又有了最新解释了。 这两天,推特用户Dylan Patel发文表示: 你想知道为什么 ChatGPT 和 6 个月前相比会如此糟糕吗? 那是因为ChatGPT系统Prompt是竟然包含1700 tokens,看看这个prompt里面有多…...

书生·浦语大模型第三课作业
基础作业: 复现课程知识库助手搭建过程 (截图) 进阶作业: 选择一个垂直领域,收集该领域的专业资料构建专业知识库,并搭建专业问答助手,并在 OpenXLab 上成功部署(截图,并提供应用地址&#x…...
【Redis笔记】分布式锁及4种常见实现方法
线程锁 主要用来给方法、代码块加锁。当某个方法或代码使用锁,在同一时刻仅有一个线程执行该方法或该代码段。线程锁只在同一JVM中有效果,因为线程锁的实现在根本上是依靠线程之间共享内存实现的,比如Synchronized、Lock等。 进程锁 控制同…...

SpringMVC第一天
一、SpringMVC简介 1 SpringMVC概述 1.1 SpringMVC概述 SpringMVC是一种基于Java实现MVC模型的轻量级Web框架 优点 使用简单,开发便捷(相比于Servlet) 灵活性强 2 入门案例【重点】 问题导入 在Controller中如何定义访问路径ÿ…...
如何利用腾讯工蜂提升广告推广和用户运营效率
无代码开发:腾讯工蜂的连接优势 在广告推广和用户运营中,腾讯工蜂的无代码开发优势让广告系统和用户运营系统能够轻松地实现无需API开发的集成。这使得没有专业编程技能的工作人员也能通过腾讯工蜂的用户友好界面,实现系统的快速连接和集成&…...
【QT+QGIS跨平台编译】之三十二:【MiniZip+Qt跨平台编译】(一套代码、一套框架,跨平台编译)
文章目录 一、MiniZip介绍二、文件下载三、文件分析四、pro文件五、编译实践一、MiniZip介绍 MiniZip是一个轻量级的开源库,用于创建、读取和操作ZIP文件格式的压缩文件。它提供了一组简单而灵活的API,可以方便地在应用程序中进行ZIP文件的压缩和解压操作。 MiniZip的主要特…...
OLAP技术的发展及趋势简述
这里写自定义目录标题 历史发展基于电子表格的数据分析基于传统数据库的数据分析基于大数据的数据分析 当下的现状OLAP技术的分类MOLAPROLAPHOLAP 主流的OLAP引擎新技术的普及内存向量计算列式数据存储及交换增量查询多源融合计算下推物化视图 发展趋势智能化分析多源融合和自动…...
stupid_brain
前言: 本文用于记录本人AI新手期间犯的各种错误,时常更新。 正文开始: 读取数据的num_worker设置过少,以至于训练速度卡在读取数据上。训练集数据处理:数据增强有利于解决过拟合问题。模型:relu少写、batc…...
C# BackgroundWorker的使用
C# 中的 BackgroundWorker 类是 .NET Framework 提供的一个组件,用于在后台线程上异步执行长时间运行的操作,同时保持与用户界面(UI)的交互,如更新进度信息或处理取消请求。这使得可以轻松地在不冻结UI的情况下执行耗时…...
(简单有案例)前端实现主题切换、动态换肤的两种简单方式
目录 背景 (强烈推荐)实现方法1:CSS中原生变量“--”和var() 步骤1:定义css变量 步骤2:使用CSS变量 步骤3:切换主题 实现完整案例 实现方法2:link 动态引入 背景 我们需要做一个功能&#…...

wyh的迷宫
涉及知识点:求迷宫能否到达终点的,而不是求路径数的,用bfs时可以不用重置状态数组(回溯)。 题目描述 给你一个n*m的迷宫,这个迷宫中有以下几个标识: s代表起点 t代表终点 x代表障碍物 .代…...

AWS云用户创建
问题 需要给工友创建AWS云的用户,这里假设使用分配给自己AWS开发者IAM账号,给别人创建aws IAM账号。 登录系统 打开页面:https://xxx.signin.aws.amazon.com/console,使用分配的开发者账号登录。如下图: 创建用户…...

微信小程序(三十七)选项点击高亮效果
注释很详细,直接上代码 上一篇 新增内容: 1.选择性渲染类 2.以数字为需渲染内容(数量) 源码: index.wxml <view class"Area"><!-- {{activeNumindex?Active:}}是选择性添加类名进行渲染 -->&l…...

铭豹扩展坞 USB转网口 突然无法识别解决方法
当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...
Leetcode 3576. Transform Array to All Equal Elements
Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接:3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)
文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

使用分级同态加密防御梯度泄漏
抽象 联邦学习 (FL) 支持跨分布式客户端进行协作模型训练,而无需共享原始数据,这使其成为在互联和自动驾驶汽车 (CAV) 等领域保护隐私的机器学习的一种很有前途的方法。然而,最近的研究表明&…...
unix/linux,sudo,其发展历程详细时间线、由来、历史背景
sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...
安卓基础(aar)
重新设置java21的环境,临时设置 $env:JAVA_HOME "D:\Android Studio\jbr" 查看当前环境变量 JAVA_HOME 的值 echo $env:JAVA_HOME 构建ARR文件 ./gradlew :private-lib:assembleRelease 目录是这样的: MyApp/ ├── app/ …...
Mysql8 忘记密码重置,以及问题解决
1.使用免密登录 找到配置MySQL文件,我的文件路径是/etc/mysql/my.cnf,有的人的是/etc/mysql/mysql.cnf 在里最后加入 skip-grant-tables重启MySQL服务 service mysql restartShutting down MySQL… SUCCESS! Starting MySQL… SUCCESS! 重启成功 2.登…...
日常一水C
多态 言简意赅:就是一个对象面对同一事件时做出的不同反应 而之前的继承中说过,当子类和父类的函数名相同时,会隐藏父类的同名函数转而调用子类的同名函数,如果要调用父类的同名函数,那么就需要对父类进行引用&#…...

WPF八大法则:告别模态窗口卡顿
⚙️ 核心问题:阻塞式模态窗口的缺陷 原始代码中ShowDialog()会阻塞UI线程,导致后续逻辑无法执行: var result modalWindow.ShowDialog(); // 线程阻塞 ProcessResult(result); // 必须等待窗口关闭根本问题:…...
SQL Server 触发器调用存储过程实现发送 HTTP 请求
文章目录 需求分析解决第 1 步:前置条件,启用 OLE 自动化方式 1:使用 SQL 实现启用 OLE 自动化方式 2:Sql Server 2005启动OLE自动化方式 3:Sql Server 2008启动OLE自动化第 2 步:创建存储过程第 3 步:创建触发器扩展 - 如何调试?第 1 步:登录 SQL Server 2008第 2 步…...