Java交换机案例如何绑定队列

wen java案例 23

本文目录导读:

Java交换机案例如何绑定队列

  1. 基本绑定示例
  2. 不同交换机类型的绑定示例
  3. 完整的生产者-消费者示例
  4. 其他绑定方法
  5. 注意事项

在Java中绑定交换机和队列通常使用RabbitMQ客户端,以下是完整的绑定示例:

基本绑定示例

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
public class RabbitMQBindingExample {
    public static void main(String[] args) throws Exception {
        // 1. 创建连接工厂
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        factory.setUsername("guest");
        factory.setPassword("guest");
        // 2. 创建连接和通道
        try (Connection connection = factory.newConnection();
             Channel channel = connection.createChannel()) {
            // 3. 声明交换机(如果不存在则创建)
            String exchangeName = "my_exchange";
            String exchangeType = "direct"; // direct, topic, fanout, headers
            channel.exchangeDeclare(exchangeName, exchangeType, true);
            // 4. 声明队列(如果不存在则创建)
            String queueName = "my_queue";
            channel.queueDeclare(queueName, true, false, false, null);
            // 5. 绑定队列到交换机
            String routingKey = "my_routing_key";
            channel.queueBind(queueName, exchangeName, routingKey);
            System.out.println("队列 " + queueName + " 已绑定到交换机 " + exchangeName + 
                             ",路由键: " + routingKey);
        }
    }
}

不同交换机类型的绑定示例

Direct Exchange(直接交换机)

// 交换机声明
channel.exchangeDeclare("direct_exchange", "direct", true);
// 队列声明
channel.queueDeclare("order_queue", true, false, false, null);
channel.queueDeclare("payment_queue", true, false, false, null);
// 绑定队列到指定路由键
channel.queueBind("order_queue", "direct_exchange", "order.create");
channel.queueBind("payment_queue", "direct_exchange", "payment.success");
// 发送消息时指定路由键
channel.basicPublish("direct_exchange", "order.create", null, message.getBytes());

Topic Exchange(主题交换机)

// 交换机声明
channel.exchangeDeclare("topic_exchange", "topic", true);
// 队列声明
channel.queueDeclare("all_logs_queue", true, false, false, null);
channel.queueDeclare("error_logs_queue", true, false, false, null);
// 使用通配符绑定
channel.queueBind("all_logs_queue", "topic_exchange", "log.*");      // 匹配所有日志
channel.queueBind("error_logs_queue", "topic_exchange", "log.error"); // 只匹配错误日志
// 通配符规则:
// * 匹配一个单词
// # 匹配零个或多个单词
// log.*       匹配 log.info, log.error, log.warn
// log.#       匹配 log, log.info, log.error.database

Fanout Exchange(扇形交换机)

// 交换机声明 - 广播到所有绑定的队列
channel.exchangeDeclare("fanout_exchange", "fanout", true);
// 队列声明
channel.queueDeclare("queue1", true, false, false, null);
channel.queueDeclare("queue2", true, false, false, null);
// 绑定 - 路由键被忽略(传空字符串或null)
channel.queueBind("queue1", "fanout_exchange", "");
channel.queueBind("queue2", "fanout_exchange", "");
// 发送消息 - 所有绑定的队列都会收到
channel.basicPublish("fanout_exchange", "", null, "广播消息".getBytes());

Headers Exchange(头交换机)

import java.util.HashMap;
import java.util.Map;
// 交换机声明
channel.exchangeDeclare("headers_exchange", "headers", true);
// 队列声明
channel.queueDeclare("queue_headers", true, false, false, null);
// 设置绑定参数
Map<String, Object> headers = new HashMap<>();
headers.put("type", "order");
headers.put("priority", "high");
// 使用头匹配绑定
channel.queueBind("queue_headers", "headers_exchange", "", 
                  new HashMap<String, Object>() {{
                      put("x-match", "all"); // all = 所有头都匹配, any = 任意一个匹配
                      put("type", "order");
                      put("priority", "high");
                  }});
// 发送消息时设置头
Map<String, Object> messageHeaders = new HashMap<>();
messageHeaders.put("type", "order");
messageHeaders.put("priority", "high");
AMQP.BasicProperties props = new AMQP.BasicProperties.Builder()
    .headers(messageHeaders)
    .build();
channel.basicPublish("headers_exchange", "", props, "头匹配消息".getBytes());

完整的生产者-消费者示例

生产者代码

public class MessageProducer {
    private final static String EXCHANGE_NAME = "demo_exchange";
    private final static String QUEUE_NAME = "demo_queue";
    private final static String ROUTING_KEY = "demo.key";
    public static void main(String[] args) throws Exception {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        try (Connection connection = factory.newConnection();
             Channel channel = connection.createChannel()) {
            // 声明交换机
            channel.exchangeDeclare(EXCHANGE_NAME, "direct", true);
            // 声明队列
            channel.queueDeclare(QUEUE_NAME, true, false, false, null);
            // 绑定
            channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, ROUTING_KEY);
            // 发送消息
            String message = "Hello RabbitMQ!";
            channel.basicPublish(EXCHANGE_NAME, ROUTING_KEY, null, message.getBytes());
            System.out.println(" [x] 发送 '" + message + "'");
        }
    }
}

消费者代码

public class MessageConsumer {
    private final static String EXCHANGE_NAME = "demo_exchange";
    private final static String QUEUE_NAME = "demo_queue";
    private final static String ROUTING_KEY = "demo.key";
    public static void main(String[] args) throws Exception {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();
        // 声明交换机(需与生产者一致)
        channel.exchangeDeclare(EXCHANGE_NAME, "direct", true);
        // 声明队列(需与生产者一致或获取服务端生成的队列名)
        channel.queueDeclare(QUEUE_NAME, true, false, false, null);
        // 绑定
        channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, ROUTING_KEY);
        // 消费消息
        DeliverCallback deliverCallback = (consumerTag, delivery) -> {
            String message = new String(delivery.getBody(), "UTF-8");
            System.out.println(" [x] 收到 '" + message + "'");
        };
        channel.basicConsume(QUEUE_NAME, true, deliverCallback, consumerTag -> {});
        System.out.println(" [*] 等待消息...");
    }
}

其他绑定方法

批量绑定

// 单个队列绑定多个路由键
channel.queueBind("queue", "exchange", "key1");
channel.queueBind("queue", "exchange", "key2");
channel.queueBind("queue", "exchange", "key3");
// 或者使用循环
String[] routingKeys = {"create", "update", "delete"};
for (String key : routingKeys) {
    channel.queueBind("queue", "exchange", key);
}

解绑操作

// 解绑队列和交换机的绑定
channel.queueUnbind("queue", "exchange", "routing_key");
// 删除交换机
channel.exchangeDelete("exchange_name");
// 删除队列
channel.queueDelete("queue_name");

使用临时队列

// 声明临时队列(系统自动生成名称)
String tempQueue = channel.queueDeclare().getQueue();
// 绑定临时队列到交换机
channel.queueBind(tempQueue, "exchange", "routing_key");
// 消费者使用临时队列
channel.basicConsume(tempQueue, true, deliverCallback, consumerTag -> {});

注意事项

  1. 绑定顺序:先声明交换机和队列,再进行绑定
  2. 持久化:交换机、队列、消息都可以设置持久化
  3. 重复绑定:相同的绑定不会产生错误,但可能会有性能影响
  4. 路由键:不同交换机类型对路由键的处理不同
  5. 资源清理:使用后记得关闭连接和通道

这些示例涵盖了Java中使用RabbitMQ进行交换机-队列绑定的主要场景,可以根据实际需求选择合适的交换机类型和绑定方式。

抱歉,评论功能暂时关闭!