RabbitMQ通信方式之Publish/Subscribe
Publish/Subscribe通信方式结构图
![](https://img-blog.csdnimg.cn/img_convert/c22efb1158bc38f3a65a672a2d779c37.png)
添加RabbitMQ和Junit工具栏的maven依赖
<!--rabbitmq-->
<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
<version>5.12.0</version>
</dependency>
<!--junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
创建一个构建连接的工具类
public class RabbitMQConnectionUtil {
public static final String RABBITMQ_HOST = "xxx.xx.xxx.xxx"; //设置你自己的RabbitMQ服务ip
public static final int RABBITMQ_PORT = 5672;
public static final String RABBITMQ_USERNAME = "guest";
public static final String RABBITMQ_PASSWORD = "guest";
public static final String RABBITMQ_VIRTUAL_HOST = "/";
/**
* 构建RabbitMQ的连接对象
*/
public static Connection getConnection() throws Exception {
//1. 创建Connection工厂
ConnectionFactory factory = new ConnectionFactory();
//2. 设置RabbitMQ的连接信息
factory.setHost(RABBITMQ_HOST);
factory.setPort(RABBITMQ_PORT);
factory.setUsername(RABBITMQ_USERNAME);
factory.setPassword(RABBITMQ_PASSWORD);
factory.setVirtualHost(RABBITMQ_VIRTUAL_HOST);
//3. 返回连接对象
Connection connection = factory.newConnection();
return connection;
}
创建生产者
public class Producer {
private static final String EXCHANGE_NAME = "my_exchange";
public static final String QUEUE_NAME1 = "pubsub-one";
public static final String QUEUE_NAME2 = "pubsub-two";
@Test
public void pubSub() throws Exception {
//1.获取连接对象
Connection connection = RabbitMQConnectionUtil.getConnection();
//2.构建Channel
Channel channel = connection.createChannel();
//3.构建交换机 exchange类型为fanout(发布-订阅模式)
channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.FANOUT);
//4.构建队列
channel.queueDeclare(QUEUE_NAME1,false,false,false,null);
channel.queueDeclare(QUEUE_NAME2,false,false,false,null);
//5.绑定交换机和队列,使用的是FANOUT类型的交换机,绑定方式是直接绑定
channel.queueBind(QUEUE_NAME1,EXCHANGE_NAME,"");
channel.queueBind(QUEUE_NAME2,EXCHANGE_NAME,"");
//6.发消息到交换机
channel.basicPublish(EXCHANGE_NAME,"",null,"publish/subscribe!".getBytes());
System.out.println("消息成功发送!");
}
}
创建消费者
public class Consumer {
//消费者1号,监听队列pubsub-one
@Test
public void consume1() throws Exception {
//1.获取连接对象
Connection connection = RabbitMQConnectionUtil.getConnection();
//2.构建Channel
Channel channel = connection.createChannel();
//3.构建队列
channel.queueDeclare(Producer.QUEUE_NAME1,false,false,false,null);
//4. 监听消息
DefaultConsumer callback = new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println("消费者获取到消息:" + new String(body,"UTF-8"));
}
};
channel.basicConsume(Producer.QUEUE_NAME1,true,callback);
System.out.println("消费者开始监听队列");
System.in.read();
}
//消费者2号代码同上,监听队列pubsub-two
@Test
...
}
启动生产者和消费者1号后,可以看到消费者1号成功消费
![](https://img-blog.csdnimg.cn/img_convert/b4544959a9b2577a6fd47be179a0cb1e.png)
在客户端也同样可以看到pubsub-one中的消息已被成功消费
![](https://img-blog.csdnimg.cn/img_convert/3449cc96736efd45857db2cd406b7201.png)
也可以通过客户端操作来消费pubsub-two中的消息
点击pubsub-two队列进入详情,可以看到具体的信息
![](https://img-blog.csdnimg.cn/img_convert/afb1504c010c7fa7c336932bf9e0ebe2.png)
pubsub模式则是基于Exchange(交换机)和队列的发布-订阅模式,包含一个或多个发送者和多个接收者,发送者将消息发送到Exchange上,Exchange将消息转发到所有与之绑定的队列中,所有绑定到队列上的接收者都能够接收到相同的消息。