RabbitMQ入门教程(九):首部交换机Headers

来源:互联网 发布:mysql trigger debug 编辑:程序博客网 时间:2024/06/08 10:26

简介

首部交换机和扇形交换机都不需要路由键routingKey,交换机时通过Headers头部来将消息映射到队列的,有点像HTTP的Headers,Hash结构中要求携带一个键“x-match”,这个键的Value可以是any或者all,这代表消息携带的Hash是需要全部匹配(all),还是仅匹配一个键(any)就可以了。相比直连交换机,首部交换机的优势是匹配的规则不被限定为字符串(string)而是Object类型。

  • any: 只要在发布消息时携带的有一对键值对headers满足队列定义的多个参数arguments的其中一个就能匹配上,注意这里是键值对的完全匹配,只匹配到键了,值却不一样是不行的;

  • all:在发布消息时携带的所有Entry必须和绑定在队列上的所有Entry完全匹配

这里写图片描述

生产者

public class Producer {    @Test    public void testBasicPublish() throws IOException, TimeoutException {        ConnectionFactory factory = new ConnectionFactory();        factory.setHost("127.0.0.1");        factory.setPort(AMQP.PROTOCOL.PORT);        factory.setUsername("mengday");        factory.setPassword("mengday");        Connection connection = factory.newConnection();        Channel channel = connection.createChannel();        Map<String, Object> heardersMap = new HashMap<String, Object>();        heardersMap.put("api", "login");        heardersMap.put("version", 1.0);        heardersMap.put("radom", UUID.randomUUID().toString());        AMQP.BasicProperties.Builder properties = new AMQP.BasicProperties().builder().headers(heardersMap);        String message = "Hello RabbitMQ!";        String EXCHANGE_NAME = "exchange.hearders";        channel.basicPublish(EXCHANGE_NAME, "", properties.build(), message.getBytes("UTF-8"));        channel.close();        connection.close();    }}

消费者

public class Consumer1 {    @Test    public void testBasicConsumer1() throws Exception{        ConnectionFactory factory = new ConnectionFactory();        factory.setHost("127.0.0.1");        factory.setPort(AMQP.PROTOCOL.PORT);    // 5672        factory.setUsername("mengday");        factory.setPassword("mengday");        Connection connection = factory.newConnection();        Channel channel = connection.createChannel();        String EXCHANGE_NAME = "exchange.hearders";        channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.HEADERS);        String queueName = channel.queueDeclare().getQueue();        Map<String, Object> arguments = new HashMap<String, Object>();        arguments.put("x-match", "any");        arguments.put("api", "login");        arguments.put("version", 1.0);        arguments.put("dataType", "json");        // 队列绑定时需要指定参数,注意虽然不需要路由键但仍旧不能写成null,需要写成空字符串""        channel.queueBind(queueName, EXCHANGE_NAME, "", arguments);        Consumer consumer = 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(message);            }        };        channel.basicConsume(queueName, true, consumer);        Thread.sleep(100000);    }}

运行结果

先运行消费者,再运行生产者。

这里写图片描述

// all:匹配失败,缺少{"dataType", "json"}Map<String, Object> heardersMap = new HashMap<String, Object>();heardersMap.put("api", "login");heardersMap.put("version", 1.0);// all:匹配成功,生产者多发送一个head没关系Map<String, Object> heardersMap = new HashMap<String, Object>();heardersMap.put("api", "login");heardersMap.put("version", 1.0);heardersMap.put("dataType", "json");heardersMap.put("ext", false);Map<String, Object> arguments = new HashMap<String, Object>();arguments.put("x-match", "all");arguments.put("api", "login");arguments.put("version", 1.0);arguments.put("dataType", "json");//------------------------------------------// any: 匹配成功,只要有一个键值对能满足队列的arguments即可Map<String, Object> heardersMap = new HashMap<String, Object>();heardersMap.put("api", "login");Map<String, Object> arguments = new HashMap<String, Object>();arguments.put("x-match", "any");arguments.put("api", "login");arguments.put("version", 1.0);arguments.put("dataType", "json");// any: 匹配失败,键值对中的key和value必须全部匹配上Map<String, Object> heardersMap = new HashMap<String, Object>();heardersMap.put("api", "regist");Map<String, Object> arguments = new HashMap<String, Object>();arguments.put("x-match", "any");arguments.put("api", "login");arguments.put("version", 1.0);arguments.put("dataType", "json");

直连接和首部类型的比较

  • 绑定规则不同:直连接是一个简单的String;而首部是键值对Entry,而且键值对的value可以是任意类型Object

  • 绑定个数不同:直连接一次只能绑定一个字符串,如果想绑定多个字符串就需要绑定多次或者循环调用queueBind()方法来绑定多次;而首部类型直接可以往Map中添加多个实体Entry即可

  • 映射规则不同:直连接只需要比较路由键是否相等即可,而首部类型除了比较value还要比较key,因为首部类型是Entry类型,需要同时比较key和value,而且首部类型还可以通过x-match来控制匹配的条件,all:需要匹配所有Entry,相当于SQL中的 and操作,any:只需要匹配上一个Entry即可,相当于SQL中的or操作

  • 直连接适用于计较简单的路由,而首部类型相比直连接匹配规则更强大

原创粉丝点击