订阅模式 ---- topic(通配符)
Topic类型的Exchange与Direct相比,都是可以根据RoutingKey把消息路由到不同的队列。只不过Topic类型Exchange可以让队列在绑定Routing key 的时候使用通配符!
- Routingkey 一般都是有一个或多个单词组成,多个单词之间以”.”分割,例如: item.insert 通配符规则:
#
:匹配0或多个词(含零个)*
:匹配不多不少恰好1个词(不含零个)- 举例:
audit.#
:能够匹配audit.irs.corporate
或者 `audit.irs``- ``audit.*
:只能匹配
audit.irs`
生产者
主题模式的生产者与之前相比routingKey的设置方式是用
.
进行分割
@ApiModel(value = "AmqpSendController",description = "整合amqp进行消息推送")
@RestController
@RequestMapping("/amqpSend")
public class AmqpSendController {
@Autowired
private AmqpTemplate amqpTemplate;
@Autowired
private RabbitTemplate rabbitTemplate;
private final static String REGEX = "\\d+";
@PostMapping("/topic/{message}")
@ApiOperation(value = "topic 发送消息")
@ApiImplicitParam(name = "message",value = "消息内容",required = true,dataType = "String")
public void topic(@PathVariable(value = "message") String message){
if (!message.matches(REGEX)) {
String routingKey = RabbitMqConstant.ROUTING_TOPIC_ROUTING_INFO+ "." +RabbitMqConstant.ROUTING_TOPIC_ROUTING_WARNING;
System.out.println("direct "+routingKey+" 发送消息:"+message);
amqpTemplate.convertAndSend(RabbitMqConstant.EXCHANGE_TOPIC_CHANGE,routingKey,message);
}else {
String routingKey = RabbitMqConstant.ROUTING_TOPIC_ROUTING_WARNING + "." +RabbitMqConstant.ROUTING_TOPIC_ROUTING_ERROR + "." + RabbitMqConstant.ROUTING_TOPIC_ROUTING_INFO;
System.out.println("direct "+routingKey+" 发送消息:"+message);
amqpTemplate.convertAndSend(RabbitMqConstant.EXCHANGE_TOPIC_CHANGE,routingKey,message);
}
}
}
消费者
消费者方面与之前的相比在routingkey绑定的时候也用了通配符。
注意:这里需要进行全路径通配如:
warning.*
无法匹配warning.info.error
,需要改成warning.* .*
才可以匹配。
@Component
public class RabbitMQListener {
@RabbitListener(
bindings = @QueueBinding(
value = @Queue(value = RabbitMqConstant.QUEUE_TOPIC_QUEUE_ONE),
exchange = @Exchange(value = RabbitMqConstant.EXCHANGE_TOPIC_CHANGE,
type = ExchangeTypes.TOPIC),
key = RabbitMqConstant.ROUTING_TOPIC_ROUTING_INFO+".*"),
ackMode = "MANUAL")
public void topicMessageReceiveOne(Message message, Channel channel) {
try {
String messageBody = new String(message.getBody());
//手动确认消息
if (messageBody.length() < 10) {
System.out.println("One direct " + message.getMessageProperties().getReceivedRoutingKey() + "------------ 消息接收:" + messageBody);
//第一个参数是消息的标记,第二个参数是是否批量处理
channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
} else {
System.out.println(messageBody + ":消息接收失败!");
new RuntimeException("消息长度大于10");
//第一个参数是消息的标记,第二个参数是是否批量处理,第三个参数,是否重新入队,true为重新入队,false为丢弃该消息
channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, false);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@RabbitListener(
bindings = @QueueBinding(
value = @Queue(value = RabbitMqConstant.QUEUE_TOPIC_QUEUE_TWO),
exchange = @Exchange(value = RabbitMqConstant.EXCHANGE_TOPIC_CHANGE,
type = ExchangeTypes.TOPIC),
key = RabbitMqConstant.ROUTING_TOPIC_ROUTING_WARNING+".*"+".*"),
ackMode = "MANUAL")
public void topicMessageReceiveTwo(Message message, Channel channel) {
try {
String messageBody = new String(message.getBody());
//手动确认消息
if (messageBody.length() < 10) {
System.out.println("Two direct " + message.getMessageProperties().getReceivedRoutingKey() + "------------ 消息接收:" + messageBody);
//第一个参数是消息的标记,第二个参数是是否批量处理
channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
} else {
System.out.println(messageBody + ":消息接收失败!");
new RuntimeException("消息长度大于10");
//第一个参数是消息的标记,第二个参数是是否批量处理,第三个参数,是否重新入队,true为重新入队,false为丢弃该消息
channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, false);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}