本文根据视频https://www.bilibili.com/video/BV1pa4y1x7Kc?p=7和https://www.bilibili.com/video/BV1pa4y1x7Kc?p=8创作。未经视频作者授权,如果作者感到侵权,请联系本人删除此文
发布订阅模式结构图如下:
发布订阅模式特点:
生产者将消息发送给交换机;
交换机绑定多个队列,每个消费者监听自己的队列;
每个绑定交换机的队列都将收到消息。
生产者代码实例:
public class PublishProducer {
private static final String QUEUE_EMAIL = "queue_email";
private static final String QUEUE_SMS = "queue_sms";
private static final String EXCHANGE_FANOUT = "echange_fanout";
public static void main(String[] args) {
//通过连接工厂创建新的连接和MQ建立连接
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("127.0.0.1");
connectionFactory.setPort(5672);
//设置虚拟机,一个MQ可以设置多个虚拟机,每个虚拟机相当于一个独立的MQ
connectionFactory.setVirtualHost("/");
connectionFactory.setUsername("guest");
connectionFactory.setPassword("guest");
Connection connection = null;
Channel channel = null;
try {
//建立新的连接
connection = connectionFactory.newConnection();
//创建会话通道,生产者和MQ服务所有通信都在channel通道中完成
channel = connection.createChannel();
//声明队列,如果队列在MQ中不存在则创建
channel.queueDeclare(QUEUE_SMS, true, false, false,null);
channel.queueDeclare(QUEUE_EMAIL, true, false, false,null);
//声明交换机
//参数: String exchange, String type
/**
* 参数明细
* 1. exchange 交换机名称
* 2. 交换机类型
* fanout: 对应发布订阅模式
* direct: 对应路由模式
* topic: 对应通配符模式
* headers: 对应header转发模式
*/
channel.exchangeDeclare(EXCHANGE_FANOUT, BuiltinExchangeType.FANOUT);
//绑定交换机和队列
//参数: String queue, String exchange, String routingKey
/**
* 参数明细:
* 1. queue 队列名称
* 2. exchange 交换机名称
* 3. routingKey 路由key,作用是交换机会根据路由key的值转发到指定的队列,在发布订阅模式为空串
*/
channel.queueBind(QUEUE_EMAIL, EXCHANGE_FANOUT, "");
channel.queueBind(QUEUE_SMS, EXCHANGE_FANOUT, "");
//发送消息
String message = "Hello World";
channel.basicPublish(EXCHANGE_FANOUT, "", null, message.getBytes());
System.out.println("send to mq " + message);
} catch (Exception e) {
e.printStackTrace();
} finally {
//关闭连接
//先关闭通道,在关闭连接
try {
channel.close();
} catch (IOException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
}
try {
connection.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
消费者代码实例一:
public class SubscriteConsumerEmail {
private static final String QUEUE_EMAIL = "queue_email";
private static final String EXCHANGE_FANOUT = "echange_fanout";
public static void main(String[] args) throws IOException, TimeoutException {
//通过连接工厂创建新的连接和MQ建立连接
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("127.0.0.1");
connectionFactory.setPort(5672);
//设置虚拟机,一个MQ可以设置多个虚拟机,每个虚拟机相当于一个独立的MQ
connectionFactory.setVirtualHost("/");
connectionFactory.setUsername("guest");
connectionFactory.setPassword("guest");
Connection connection = null;
Channel channel = null;
//建立新的连接
connection = connectionFactory.newConnection();
//创建会话通道,生产者和MQ服务所有通信都在channel通道中完成
channel = connection.createChannel();
//声明队列,如果队列在MQ中不存在则创建
channel.queueDeclare(QUEUE_EMAIL, true, false, false, null);
//声明交换机
channel.exchangeDeclare(EXCHANGE_FANOUT, BuiltinExchangeType.FANOUT);
//绑定交换机和队列
channel.queueBind(QUEUE_EMAIL, EXCHANGE_FANOUT, "");
//实现消费方法
DefaultConsumer defaultConsumer = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
String message = new String(body, "UTF-8");
System.out.println("receive message: " + message);
}
};
//监听队列
channel.basicConsume(QUEUE_EMAIL, true, defaultConsumer);
}
}
消费者代码实例二:
public static void main(String[] args) throws IOException, TimeoutException {
//通过连接工厂创建新的连接和MQ建立连接
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("127.0.0.1");
connectionFactory.setPort(5672);
//设置虚拟机,一个MQ可以设置多个虚拟机,每个虚拟机相当于一个独立的MQ
connectionFactory.setVirtualHost("/");
connectionFactory.setUsername("guest");
connectionFactory.setPassword("guest");
Connection connection = null;
Channel channel = null;
//建立新的连接
connection = connectionFactory.newConnection();
//创建会话通道,生产者和MQ服务所有通信都在channel通道中完成
channel = connection.createChannel();
//声明队列,如果队列在MQ中不存在则创建
channel.queueDeclare(QUEUE_SMS, true, false, false, null);
//声明交换机
channel.exchangeDeclare(EXCHANGE_FANOUT, BuiltinExchangeType.FANOUT);
//绑定交换机和队列
channel.queueBind(QUEUE_SMS, EXCHANGE_FANOUT, "");
//实现消费方法
DefaultConsumer defaultConsumer = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
String message = new String(body, "UTF-8");
System.out.println("receive message: " + message);
}
};
//监听队列
channel.basicConsume(QUEUE_SMS, true, defaultConsumer);
}
}