一、模型图
- P:生产者
- X:交换机
- 红色:临时队列
- C1:消费者1
- C2: 消费者2
在广播模式下,消息发送流程是这样的:
- 可以有多个消费者
- 每个消费者有自己的queue(队列)
- 每个队列都要绑定到exchange(交换机)
- 交换机把消息发送给绑定过的所有队列
- 队列的i西奥菲这都能拿到消息,实现一条消息被多个消费者消费
二、代码演示
1、工具类
package com.java.study.rabbitmq.utils;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
public class RabbitMQUtils {
private static ConnectionFactory connectionFactory;
static{
//1.创建连接mq的连接工厂对象
connectionFactory = new ConnectionFactory();
//2.设置连接rabbitmq主机
connectionFactory.setHost("192.168.8.222");
//3.设置端口号
connectionFactory.setPort(5672);
//4.设置连接那个虚拟主机
connectionFactory.setVirtualHost("/ems");
//5.设置访问虚拟主机的用户名和密码
connectionFactory.setUsername("ems");
connectionFactory.setPassword("123");
}
public static Connection getConnections(){
try{
//6.获取连接
return connectionFactory.newConnection();
}catch (Exception e){
e.printStackTrace();
}
return null;
}
public static void closeConnectionAndChannel(Channel channel,Connection connection){
try {
channel.close();
connection.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
2、生产者
package com.java.study.rabbitmq.fanout;
import com.java.study.rabbitmq.utils.RabbitMQUtils;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import org.junit.Test;
public class Producer {
private final static String EXCHANGE_NAME = "logs";
private final static String EXCHANGE_TYPE = "fanout";
@Test
public void sendMessages() throws Exception {
//6.获取连接
Connection connection = RabbitMQUtils.getConnections();
//7.获取通道
Channel channel = connection.createChannel();
//8.将通道声明指定的交换机
//参数1:交换机的名字
//参数2:交换机的类型
channel.exchangeDeclare(EXCHANGE_NAME,EXCHANGE_TYPE);
String message = "fanout type message";
//9.发布消息
//参数1:exchange 交换机名称
//参数2:routingKey 队列名称(由这里具体指定发送到具体哪个队列中)
//参数3:props 传递消息额外设置(由这里设置消息是否持久化,MessageProperties.PERSISTENT_TEXT_PLAIN:重启不会消失)
//参数4:body 消息的具体内容
channel.basicPublish(EXCHANGE_NAME,"",null,message.getBytes());
//10.关闭连接
RabbitMQUtils.closeConnectionAndChannel(channel,connection);
}
}
3、消费者1
package com.java.study.rabbitmq.fanout;
import com.java.study.rabbitmq.utils.RabbitMQUtils;
import com.rabbitmq.client.*;
import java.io.IOException;
public class Consumer1 {
private final static String EXCHANGE_NAME = "logs";
private final static String EXCHANGE_TYPE = "fanout";
public static void main(String[] args) throws Exception{
//6.获取连接
Connection connection = RabbitMQUtils.getConnections();
//7.获取通道
Channel channel = connection.createChannel();
//8.通道绑定交换机
channel.exchangeDeclare(EXCHANGE_NAME,EXCHANGE_TYPE);
//9.临时队列
String queueName = channel.queueDeclare().getQueue();
//10.绑定交换机和队列
channel.queueBind(queueName,EXCHANGE_NAME,"");
//11.消费消息
//参数1:队列名称
//参数2:消息的自动确认机制 true:消费者自动向rabbitmq确认消息消费(拿到即确认,遇到异常消息丢失) false:手动确认
//参数3:消费消息时的回调接口
channel.basicConsume(queueName,true,new DefaultConsumer(channel){
//参数1:consumerTag 消费者标签,用来标识消费者的,在
//参数2:envelope 信封
//参数3:properties 消息属性
//参数4:body 消息队列中取出的消息
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println("消费者1:"+new String(body));
}
});
}
}
4、消费者2
package com.java.study.rabbitmq.fanout;
import com.java.study.rabbitmq.utils.RabbitMQUtils;
import com.rabbitmq.client.*;
import java.io.IOException;
public class Consumer2 {
private final static String EXCHANGE_NAME = "logs";
private final static String EXCHANGE_TYPE = "fanout";
public static void main(String[] args) throws Exception{
//6.获取连接
Connection connection = RabbitMQUtils.getConnections();
//7.获取通道
Channel channel = connection.createChannel();
//8.通道绑定交换机
channel.exchangeDeclare(EXCHANGE_NAME,EXCHANGE_TYPE);
//9.临时队列
String queueName = channel.queueDeclare().getQueue();
//10.绑定交换机和队列
channel.queueBind(queueName,EXCHANGE_NAME,"");
//11.消费消息
//参数1:队列名称
//参数2:消息的自动确认机制 true:消费者自动向rabbitmq确认消息消费(拿到即确认,遇到异常消息丢失) false:手动确认
//参数3:消费消息时的回调接口
channel.basicConsume(queueName,true,new DefaultConsumer(channel){
//参数1:consumerTag 消费者标签,用来标识消费者的,在
//参数2:envelope 信封
//参数3:properties 消息属性
//参数4:body 消息队列中取出的消息
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println("消费者2:"+new String(body));
}
});
}
}
5、消费者3
package com.java.study.rabbitmq.fanout;
import com.java.study.rabbitmq.utils.RabbitMQUtils;
import com.rabbitmq.client.*;
import java.io.IOException;
public class Consumer3 {
private final static String EXCHANGE_NAME = "logs";
private final static String EXCHANGE_TYPE = "fanout";
public static void main(String[] args) throws Exception{
//6.获取连接
Connection connection = RabbitMQUtils.getConnections();
//7.获取通道
Channel channel = connection.createChannel();
//8.通道绑定交换机
channel.exchangeDeclare(EXCHANGE_NAME,EXCHANGE_TYPE);
//9.临时队列
String queueName = channel.queueDeclare().getQueue();
//10.绑定交换机和队列
channel.queueBind(queueName,EXCHANGE_NAME,"");
//11.消费消息
//参数1:队列名称
//参数2:消息的自动确认机制 true:消费者自动向rabbitmq确认消息消费(拿到即确认,遇到异常消息丢失) false:手动确认
//参数3:消费消息时的回调接口
channel.basicConsume(queueName,true,new DefaultConsumer(channel){
//参数1:consumerTag 消费者标签,用来标识消费者的,在
//参数2:envelope 信封
//参数3:properties 消息属性
//参数4:body 消息队列中取出的消息
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println("消费者3:"+new String(body));
}
});
}
}