当前位置: 代码迷 >> 综合 >> springboot+rabbitmq整合五种模式,所遇到的问题,搞了半天,结果就是因为声明的Binding中有个routingKey设置了null,最后我的绑定硬是没有绑定到rabbitmq中;
  详细解决方案

springboot+rabbitmq整合五种模式,所遇到的问题,搞了半天,结果就是因为声明的Binding中有个routingKey设置了null,最后我的绑定硬是没有绑定到rabbitmq中;

热度:99   发布时间:2024-02-23 13:18:52.0

由于笔者粗心大意在做Topic模式时,发现自己建立的Binding一直没有映射到RabbitMq中,明明都写了好了Queue、Exchange、Binding,结果在rabbitmq的管理界面没有绑定关系,抓狂,以下是自己的分析。

不废话直接上错误代码

    /*** 绑定1 消息队列绑定到交换机* 这个routingKey不能为null,没有就"",否则GG* @param fanoutQueue1* @param fanoutExchange* @return*/@Beanpublic Binding fanoutBinding1(Queue fanoutQueue1, FanoutExchange fanoutExchange) {return new Binding(fanoutQueue1.getName(), Binding.DestinationType.QUEUE, fanoutExchange.getName(), null, null);}/*** 绑定2 消息队列绑定到交换机* @param fanoutQueue2* @param fanoutExchange* @return*/@Beanpublic Binding fanoutBinding2(Queue fanoutQueue2, FanoutExchange fanoutExchange) {return BindingBuilder.bind(fanoutQueue2).to(fanoutExchange);}

 

 最后在RabbitAdmin中找到了答案。

/*** Declares all the exchanges, queues and bindings in the enclosing application context, if any. It should be safe* (but unnecessary) to call this method more than once.*/@Override // NOSONAR complexitypublic void initialize() {if (this.applicationContext == null) {this.logger.debug("no ApplicationContext has been set, cannot auto-declare Exchanges, Queues, and Bindings");return;}this.logger.debug("Initializing declarations");Collection<Exchange> contextExchanges = new LinkedList<Exchange>(this.applicationContext.getBeansOfType(Exchange.class).values());Collection<Queue> contextQueues = new LinkedList<Queue>(this.applicationContext.getBeansOfType(Queue.class).values());Collection<Binding> contextBindings = new LinkedList<Binding>(this.applicationContext.getBeansOfType(Binding.class).values());Collection<DeclarableCustomizer> customizers =this.applicationContext.getBeansOfType(DeclarableCustomizer.class).values();.......
//这里是重点,最终将整理好的Exchange、Queue和Binding发送给RabbitMq进行设置。
this.rabbitTemplate.execute(channel -> {declareExchanges(channel, exchanges.toArray(new Exchange[exchanges.size()]));declareQueues(channel, queues.toArray(new Queue[queues.size()]));//向RabbitMQ设置绑定关系,declareBindings方法主要是遍历bindings,挨个的设置。declareBindings(channel, bindings.toArray(new Binding[bindings.size()]));return null;});this.logger.debug("Declarations finished");
}private void declareBindings(final Channel channel, final Binding... bindings) throws IOException {//在这里,如果遇到了有routingKey设置为null的binding就终止了,那么后面未遍历的binding就错过了向RabbitMQ发送绑定的机会for (Binding binding : bindings) {if (this.logger.isDebugEnabled()) {this.logger.debug("Binding destination [" + binding.getDestination() + " (" + binding.getDestinationType()+ ")] to exchange [" + binding.getExchange() + "] with routing key [" + binding.getRoutingKey()+ "]");}try {if (binding.isDestinationQueue()) {if (!isDeclaringImplicitQueueBinding(binding)) {//就是这里抛异常终止遍历的。channel.queueBind(binding.getDestination(), binding.getExchange(), binding.getRoutingKey(),binding.getArguments());}}else {channel.exchangeBind(binding.getDestination(), binding.getExchange(), binding.getRoutingKey(),binding.getArguments());}}catch (IOException e) {logOrRethrowDeclarationException(binding, "binding", e);}}}

这个Binding非常重要,不要轻易写null。在BindingBuilder中默认是

所以建议,还是用框架封装的Builder吧,对应Queue也有QueueBuilder,Exchange也有ExchangeBuilder,Binding有BindingBuilder构建类。利用了建造者模式,构建快捷,方便使用,顺便熟练设计模式。

  相关解决方案