直接(direct)交换机:交换机可以通过路由(routingKey)与队列进行绑定,在接收到生产者发来消息后,通过路由发送给指定队列,从而达到指定消费者消费。
案例:一个生产者,两个消费者,生产者发送消息给direct交换机,交换机通过指定路由发送给指定队列,如下图:
1、创建工具类获取信道,关闭linux上的防火墙以及启动rabbitmq服务
//连接工厂,创建信道工具类
public class RabbitUtils {
// 得到一个连接的 channel
public static Channel getChannel() throws Exception {
// 创建一个连接工厂
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("192.168.23.129");
factory.setUsername("user");
factory.setPassword("123");
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
return channel;
}
}
2、创建生产者发送消息
(1)获取信道,声明交换机为direct类型;
(2)输入消息以及路由信息;
(3)调用basicPulish(交换机,路由,其他参数,消息体)方法发送消息。
public class Producer {
//交换机名称
public static final String DIRECT_EXCHANGE="direct_exchange";
public static void main(String[] args) throws Exception {
//获取信道
Channel channel = RabbitUtils.getChannel();
//声明交换机
channel.exchangeDeclare(DIRECT_EXCHANGE, BuiltinExchangeType.DIRECT);
//发送消息
Scanner scanner = new Scanner(System.in);
//发送消息
while (true){
System.out.print("请输入发送的消息:");
String message=scanner.nextLine();
System.out.print("请输入发送消息的路由:");
String routingKey=scanner.nextLine();
//发送消息
channel.basicPublish(DIRECT_EXCHANGE,routingKey,null,message.getBytes("UTF-8"));
System.out.println("生产者发送消息:"+message+",发送路由为:"+routingKey);
}
}
}
3、创建两个消费者接收消息
(1)获取信道,声明队列;
(2)调用queueBind(队列名,交换机名,路由)方法绑定交换机与队列,该方法可以调用多次绑定不通路由;
(3)调用basicConsummer(交换机,路由,接收成功回调,接收失败回调)方法接收消息。
consumer1绑定路由key1
public class Consumer1 {
//交换机名称
public static final String DIRECT_EXCHANGE="direct_exchange";
public static void main(String[] args) throws Exception {
//获得信道
Channel channel = RabbitUtils.getChannel();
String queue_Name="queue1";
//声明队列
channel.queueDeclare(queue_Name,false,false,false,null);
//绑定交换机与队列
channel.queueBind(queue_Name,DIRECT_EXCHANGE,"key1");
//接收消息成功回调函数
DeliverCallback deliverCallback=(deliverTag,message)->{
System.out.println("consumer1接收到消息:"+new String(message.getBody())+",经过路由为:"+message.getEnvelope().getRoutingKey());
};
//接收消息
channel.basicConsume(queue_Name,true,deliverCallback,consumerTag->{});
}
}
consumer2绑定路由key2,key3
public class Consumer2 {
//交换机名称
public static final String DIRECT_EXCHANGE="direct_exchange";
public static void main(String[] args) throws Exception {
//获得信道
Channel channel = RabbitUtils.getChannel();
String queue_Name="queue2";
//声明队列
channel.queueDeclare(queue_Name,false,false,false,null);
//绑定交换机与队列
channel.queueBind(queue_Name,DIRECT_EXCHANGE,"key2");
channel.queueBind(queue_Name,DIRECT_EXCHANGE,"key3");
//接收消息成功回调函数
DeliverCallback deliverCallback=(deliverTag,message)->{
System.out.println("consumer2接收到消息:"+new String(message.getBody())+",经过路由为:"+message.getEnvelope().getRoutingKey());
};
//接收消息
channel.basicConsume(queue_Name,true,deliverCallback,consumerTag->{});
}
}
4、测试
(1)发送消息:”你好,queue1“,通过路由key1,最终只有consumer1接收到;
(2)发送消息:”你好queue2“,通过路由key2,最终只有consumer2接收到;
(3)发送消息:”你好consumer2“,通过路由key3,最终只有consumer2接收到;
(4)发送消息:”你好,通过路由key4“,最终消息丢失;
如下图: