上一篇我們已經學習了默認的交換機,其實默認的交換機也是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
我們看到消息都已經被消費掉了,直連接其實很簡單,默認的也是使用這樣的,所以默認的效果,直連接是一樣的。