RabbitMQ實戰篇:Direct - 直連交換機

上一篇我們已經學習了默認的交換機,其實默認的交換機也是Direct  直連交換機,只是使用了系統默認的,這一篇我們來學習Direct 交換機,內容和上一篇大致相同,稍微有些不同的地方我會說明。

首先我們還是先定義一個queue,和Direct 交換機,以及通過路由key將這個queue綁定到Direct  交換機上



import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.lwl.rabbitmq.constant.Constants;

/**
 * 發送消息 配置發送消息的隊列queue
 * @author lwl
 * @create 2018年8月10日 下午2:37:38
 * @version 1.0
 */
@Configuration
public class SendMessageConfig {

	/**
	 * 定義一個隊列,queue
	 * @return
	 * @author lwl
	 * @create 2019年6月20日 下午2:04:36
	 */
    @Bean
    public Queue DirectQueue() {
    	return new Queue(Constants.DIRECT_QUEUE);
    }
    
    /**
     * 定義Direct 直連交換機
     * @return
     * @author lwl
     * @create 2019年6月20日 下午2:04:57
     */
    @Bean
    DirectExchange exchange() {
        return new DirectExchange(Constants.DIRECT_NAME);
    }
    
    /**
     * 使用Direct 直連接,routekey 爲 direct.queue.exchange
     * @param queueMessage
     * @param exchange
     * @return
     * @author lwl
     * @create 2019年6月14日 上午10:51:21
     */
    @Bean
    Binding bindingExchangeMessage(Queue DirectQueue, DirectExchange exchange) {
        return BindingBuilder.bind(DirectQueue).to(exchange).with(Constants.ROUTING_KEY);
    }
    
    /**
     * 定義第二個queue
     * @return
     * @author lwl
     * @create 2019年6月20日 下午2:05:36
     */
    @Bean
    public Queue DirectQueue2() {
    	return new Queue(Constants.DIRECT_QUEUE_TWO);
    }
    
    /**
     * 使用同樣的路由key,將第二個queue綁定到同一個exchange上
     * @param DirectQueue2
     * @param exchange
     * @return
     * @author lwl
     * @create 2019年6月20日 下午2:05:52
     */
    @Bean
    Binding bindingExchangeMessage2(Queue DirectQueue2, DirectExchange exchange) {
        return BindingBuilder.bind(DirectQueue2).to(exchange).with(Constants.ROUTING_KEY);
    }
}

這裏有點特殊,我們定義了2個queue,使用同一個路由key,綁定到同一個exchange,接下來我會告訴你們這樣做有什麼效果

接下來我們來看一下生產者:


import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.lwl.rabbitmq.constant.Constants;

/**
 * 生成者
 * @author lwl
 * @create 2019年6月14日 上午10:56:41
 * @version 1.0
 */
@Component
public class Producer {

	@Autowired
    private AmqpTemplate template;

    /**
     * 帶有路由key的直連交換機
     * @param message
     * @author lwl
     * @create 2019年6月14日 上午10:54:54
     */
    public void sendDirect(Object message){
    	template.convertAndSend(Constants.DIRECT_NAME,Constants.ROUTING_KEY,message);
    }
    
	
}

這裏我們看一下這個方法template.convertAndSend(Constants.DIRECT_NAME,Constants.ROUTING_KEY,message);

/**
	 * Convert a Java object to an Amqp {@link Message} and send it to a specific exchange
	 * with a specific routing key.
	 *
	 * @param exchange the name of the exchange
	 * @param routingKey the routing key
	 * @param message a message to send
	 * @throws AmqpException if there is a problem
	 */
	void convertAndSend(String exchange, String routingKey, Object message) throws AmqpException;

第一個參數就是我們之前定義的exchange 名稱,第二個是路由key,第三個參數就是我們想要發送的消息內容

接下來看看消費者:


import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import com.lwl.rabbitmq.constant.Constants;

/**
 * 消費者
 * @author lwl
 * @create 2019年6月14日 上午10:57:11
 * @version 1.0
 */
@Component
@RabbitListener(queues = Constants.DIRECT_QUEUE)
public class DirectConsumer {

	@RabbitHandler
    public void process(String hello) {
		System.out.println();
		System.out.println("-----------------------客戶端  1  收到數據 -----------------------");
        System.out.println(Constants.DIRECT_QUEUE+ " --> Receiver1  : " + hello);
        System.out.println();
    }
	
}
package com.lwl.rabbitmq.consumer;

import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import com.lwl.rabbitmq.constant.Constants;

/**
 * 消費者
 * @author lwl
 * @create 2019年6月14日 上午10:57:11
 * @version 1.0
 */
@Component
@RabbitListener(queues = Constants.DIRECT_QUEUE_TWO)
public class DirectConsumer4 {

	@RabbitHandler
    public void process(String hello) {
		System.out.println();
		System.out.println("-----------------------客戶端 4  收到數據 -----------------------");
        System.out.println(Constants.DIRECT_QUEUE_TWO+ " --> Receiver4  : " + hello);
        System.out.println();
    }
	
}

剛纔我們定義了2個隊列Queue,所以我們要分別寫2 個類去接收數據。

接下來我們寫一個測試用例:

/**
	 * 發送消息(此時把DirectConsumer,DirectConsumer2 ,DirectConsumer3, DirectConsumer4  註釋掉)
	 * @author lwl
	 * @create 2019年6月20日 下午2:16:54
	 */
	@Test
	public void sendMessage() {
		String message = "我是Direct 發送的消息33333333";
		producer.sendDirect(message);
		System.out.println("--------------------------------發送完畢--------------------------------");
		System.out.println();
	}

我們看一下運行結果:

2個隊列Queue都收到了,爲什麼會都接收到呢?

如果有兩個接收程序用了各自的queue,但使用相同的routingKey去綁定direct exchange的話,分發的行爲是複製的,也就是說每個程序都會收到這個消息的副本。行爲相當於fanout類型的exchange。 

看一下接收測試:

/**
	 * 接收消息(此時把DirectConsumer, DirectConsumer4 打開)
	 * @author lwl
	 * @create 2019年6月20日 下午2:16:54
	 */
	@Test
	public void getMessage() {
		
	}

運行結果:

-----------------------客戶端  1  收到數據 -----------------------
direct_queue --> Receiver1  : 我是Direct 發送的消息33333333


-----------------------客戶端 4  收到數據 -----------------------
direct_queue_2 --> Receiver4  : 我是Direct 發送的消息33333333

我們看到消息都已經被消費掉了,直連接其實很簡單,默認的也是使用這樣的,所以默認的效果,直連接是一樣的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章