Headers类型Exchange

前面讲过fanout,direct,topic类型的exchange的使用,还有一个headers类型的exchange未提到如何使用它,现在我们就来看看header exchange该如何使用以及在哪些场景下使用这种类型的exchange。

一、Headers

headers exchange主要通过发送的request message中的header进行匹配,其中匹配规则(x-match)又分为all和any:

  • all代表必须所有的键值对匹配,
  • any代表只要有一个键值对匹配即可。

headers exchange的默认匹配规则(x-match)是any。说明如下:

  1. 我们使用Headers Exchange的时候的匹配到Queue的规则是headers中的参数,只要参数匹配即可实现消息入列
  2. 使用Headers Exchange的时候匹配规则和当前的route key无关
  3. 可以使用x-match参数方式设定匹配规则
  4. 可以使用x-开头,即上面的描述

架构图如下:

二、通过接口创建header类型的交换机

2.1.生产者

编写生产者代码如下:

package com.augus.header;

import com.augus.util.RabbitMQConnectionUtil;
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import org.junit.Test;

import java.io.IOException;
import java.util.HashMap;
import java.util.concurrent.TimeoutException;

public class Publisher {
    public static final String HRADER_EXCHANE = "head-exchange";
    public static final String HRADER_QUEUE = "head-queue";
    @Test
    public void publish() throws IOException, TimeoutException {
        //创建连接
        Connection connection = RabbitMQConnectionUtil.getConnection();

        //创建channel
        Channel channel = connection.createChannel();

        //构建交换机和队列,并基于header的方式实现绑定
        channel.exchangeDeclare(HRADER_EXCHANE, BuiltinExchangeType.HEADERS); //创建交换机,指定交换机的类型
        channel.queueDeclare(HRADER_QUEUE,true,false,false,null);//创建队列

        HashMap<String, Object> map = new HashMap<>();
        /**
         * "x-match","all" 多个header的key-value要求全部匹配上!
         * "x-match","any" 多个header的key-value只要可以匹配上一个就可以
         */
        map.put("x-match","all");
        map.put("name","augus");
        map.put("age","18");

        //绑定方式这里routingKey就不需要了,所以为空
        channel.queueBind(HRADER_QUEUE,HRADER_EXCHANE,"",map);

        //发送消息

        //构建添加
        HashMap<String, Object> headers = new HashMap<>();
        headers.put("name","augus");
        headers.put("age","18");

        AMQP.BasicProperties props =
                new AMQP.BasicProperties()
                        .builder()
                        .headers(headers)
                        .build();

        channel.basicPublish(HRADER_EXCHANE,"",props,"明天周五了".getBytes());

        System.out.println("发送消息成功");
    }
}

2.2.测试

启动RabbitMQ,上面的生产者x-match值为all,要求发送信息携带的header需要全部匹配,执行发送消息到队列,如下:

先删除创建的队列,然后故意将age这个键改错,由于方式是all,要求全部匹配,执行发送消息到队列,如下队列中并没有消息:

查看队列:

三、通过springboot整合RabbitMQ创建header类型的交换机

3.1.创建交换机绑定队列

在config包下创建HeaderConfig ,让一个header类型的交换机绑定两个队列,分别测试all和any

package com.augus.rabbitmq02.config;

import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;

@Configuration
public class HeaderConfig {
    public static final String EXCHANGE_NAME = "head—exchange";
    public static final String QUEUE_NAME1 = "head-queue01";
    public static final String QUEUE_NAME2 = "head-queue02";

    /**
     * 创建交换机
     * @return
     */
    @Bean
    public HeadersExchange headersExchange(){
        return ExchangeBuilder.headersExchange(EXCHANGE_NAME).build();
    }

    @Bean
    public Queue queue01(){
        return QueueBuilder.durable(QUEUE_NAME1).build();
    }

    @Bean
    public Queue queue02(){
        return QueueBuilder.durable(QUEUE_NAME2).build();
    }

    /**
     * 交换机和队列1绑定
     * @param headersExchange 交换机
     * @param queue01 队列1
     * @return
     */
    @Bean
    public Binding headerBind01(HeadersExchange headersExchange,Queue queue01){
        HashMap<String, Object> map = new HashMap<>();
        map.put("x-match","all");
        map.put("name", "jack");
        map.put("age", "23");
        return BindingBuilder.bind(queue01).to(headersExchange).whereAll(map).match();
    }


    /**
     * 交换机和队列2绑定
     * @param headersExchange 交换机
     * @param queue02 队列2
     * @return
     */
    @Bean
    public Binding headerBind02(HeadersExchange headersExchange,Queue queue02){
        HashMap<String, Object> map = new HashMap<>();
        map.put("x-match","any");
        map.put("name", "augus");
        map.put("age", "18");
        return BindingBuilder.bind(queue02).to(headersExchange).whereAny(map).match();

    }
}

3.2.编写生产者

创建两个生产者分别给两个队列发送消息,如下:

package com.augus.rabbitmq02;

import com.augus.rabbitmq02.config.HeaderConfig;
import org.junit.jupiter.api.Test;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
public class HeaderPublisher {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Test
    public void send1(){
        rabbitTemplate.convertAndSend(HeaderConfig.HEADER_EXCHANGE, "", "暮霭程程楚天阔", new MessagePostProcessor() {
            @Override
            public Message postProcessMessage(Message message) throws AmqpException {
                //设置消息的关联ID
                message.getMessageProperties().setHeader("name","jack");
                message.getMessageProperties().setHeader("age","23");
                return message;
            }
        });

        System.out.println("消息发送成功!!!");
    }

    @Test
    public void send2(){
        rabbitTemplate.convertAndSend(HeaderConfig.HEADER_EXCHANGE, "", "念去去千里烟波", new MessagePostProcessor() {
            @Override
            public Message postProcessMessage(Message message) throws AmqpException {
                //设置消息的关联ID
                message.getMessageProperties().setHeader("name","augus");
                //故意只写一个条件
                //message.getMessageProperties().setHeader("age","18");
                return message;
            }
        });

        System.out.println("消息发送成功!!!");
    }
}
posted @ 2023-09-21 23:20  酒剑仙*  阅读(50)  评论(0)    收藏  举报