交换机topic主题模式
Topic交换机相对于direct交换机更加灵活。
direct交换机只能指定具有相同routingkey的队列,类似于sql的精确查询。
而Topic交换则更像是Like语句,用来模糊匹配routingkey
topic指定routingkey时用".“分隔词语,例如:order.test.key,可以任意用”."分隔多个词,但是最长不能超过255个字节。
匹配规则
*(星号)可以代替一个单词
#(井号)可以替代零个或多个单词
生产者产生多条消息和不同的路由规则
public class TopicExchange {
public static final String EXCHANGE_NAME = "topic_exchange_test";
public static void main(String[] args) {
try {
Channel channel = RabbitMqUtils.getChannel();
channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.TOPIC);
Map<String,String> mapMessage = new HashMap<>();
mapMessage.put("order.jack.wade","向order消息");
mapMessage.put("order.jack.yiyi","向order消息");
mapMessage.put("order.jack.huang.yi","接收不到的消息");
mapMessage.put("warehouse.jack.huang","向warehouse发送消息");
mapMessage.put("warehouse.chen.op","向warehouse发送消息");
mapMessage.put("jackwade.self.nm","向jackwade发送消息");
mapMessage.put("jackwade.self.wade.loop","向jackwade发送消息");
mapMessage.put("jackwade.two.wade.mq.rabbit","向jackwade发送消息");
mapMessage.put("oop.self.nm","向oop.self发送消息");
mapMessage.put("oop.self.wade.loop","向oop.self发送消息");
for(Map.Entry<String,String> message : mapMessage.entrySet()){
//1.交换机名称 2.routingKey 3.其他属性 例如持久化,4.消息
channel.basicPublish(EXCHANGE_NAME,message.getKey(),null,message.getKey().getBytes(StandardCharsets.UTF_8));
System.out.println("生产者发出消息:"+message.getValue());
}
} catch (IOException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
}
}
}
创建消费者
public class TopicExchangeConsumer1 {
//交换机名称
public static final String EXCHANGE_NAME = "topic_exchange_test";
public static final String QUEUE_NAME = "order_queue";
//匹配order开头的routingkey 长度是3个单词
public static final String ROUTING_KEY = "order.*.*";
public static void main(String[] args) throws IOException, TimeoutException {
Channel channel = RabbitMqUtils.getChannel();
/**
* 1.交换机名称
* 2.交换机类型
*/
channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.TOPIC);
//声明一个队列
channel.queueDeclare(QUEUE_NAME,true,false,true,null);
channel.queueBind(QUEUE_NAME,EXCHANGE_NAME,ROUTING_KEY);
System.out.println(ROUTING_KEY+":消费者等待接收消息!");
//接收消息回调
DeliverCallback callback = (consumerTag, message) -> {
String receiveMessage = new String(message.getBody(), Charsets.UTF_8.name());
System.out.println(ROUTING_KEY+"_接收到消息:"+receiveMessage+" 标签:"+consumerTag);
};
//取消消息回调
CancelCallback cancelCallback = consumerTag -> {
System.out.println(ROUTING_KEY+"_消费者取消消费接口回调逻辑:"+consumerTag);
};
channel.basicConsume(QUEUE_NAME,false,callback,cancelCallback);
}
}
消费者2
public class TopicConsumer2 {
//交换机名称
public static final String EXCHANGE_NAME = "topic_exchange_test";
public static final String QUEUE_NAME = "order_queue";
//匹配order开头的routingkey 长度是3个单词
public static final String ROUTING_KEY = "warehouse.*.*";
public static void main(String[] args) throws IOException, TimeoutException {
Channel channel = RabbitConnectUtils.getChanel();
/**
* 1.交换机名称
* 2.交换机类型
*/
channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.TOPIC);
//声明一个队列
channel.queueDeclare(QUEUE_NAME,true,false,true,null);
channel.queueBind(QUEUE_NAME,EXCHANGE_NAME,ROUTING_KEY);
System.out.println(ROUTING_KEY+":消费者等待接收消息!");
//接收消息回调
DeliverCallback callback = (consumerTag, message) -> {
String receiveMessage = new String(message.getBody(), Charsets.UTF_8.name());
System.out.println(ROUTING_KEY+"_接收到消息:"+receiveMessage+" 标签:"+consumerTag);
};
//取消消息回调
CancelCallback cancelCallback = consumerTag -> {
System.out.println(ROUTING_KEY+"_消费者取消消费接口回调逻辑:"+consumerTag);
};
channel.basicConsume(QUEUE_NAME,false,callback,cancelCallback);
}
}
消费者1匹配order开头并且是三个单词的routingke
public static final String ROUTING_KEY = "order.*.*";
输出
消费者2的routingkey 匹配以warehouse开头并且是三个单词的routingkey
public static final String ROUTING_KEY = "warehouse.*.*";
输出
入图片描述
消费者3的routingkey 匹配中间且是三个组成的单词
public static final String ROUTING_KEY = "*.self.*";
输出
消费者4的routingkey 匹配以jackwade开头的routingkey后面的单词长度不限
public static final String ROUTING_KEY = "jackwade.#";