Stringboot整合rabbitmq自动创建队列

现象:队列没有自动创建?why???

当你兴高采烈得添加了maven依赖并心花怒放一般地copy完一下代码却发现,程序启动起来后队列没有创建,交换机也没有创建,瞬间一万只草拟吗涌上心头,开始了百度之路......


    /**
     * 配置交换机实例
     * @return
     */
    @Bean(name = "logCallbackDirectExchange")
    public DirectExchange directExchange() {
        return new DirectExchange(logCallbackExchange);
    }

    /**
     * 配置队列实例,并且设置持久化队列
     * @return
     */
    @Bean(name = "logCallbackQueue")
    public Queue queue() {
        Map map = new HashMap<>();
        // 设置消息100s后过期
        map.put("x-message-ttl", messageValidTime);
        return new Queue(logCallbackQueue, true, false, false, map);
    }

    /**
     * 将队列绑定到交换机上,并设置消息分发的路由键
     * @return
     */
    @Bean(name = "logCallbackDirectExchangeBinding")
    public Binding binding() {
        //用指定的路由键将队列绑定到交换机
        return BindingBuilder.bind(queue()).to(directExchange()).with(logCallbackQueue);
    }

解决办法:

在定义queue和exchange的地方使用AmqpAdmin生命一下即可:

    @Bean
    public AmqpAdmin amqpAdmin(CachingConnectionFactory cachingConnectionFactory){
        AmqpAdmin amqpAdmin = new RabbitAdmin(cachingConnectionFactory);
        amqpAdmin.declareQueue(queue());
        amqpAdmin.declareExchange(directExchange());
        amqpAdmin.declareBinding(binding());
        return amqpAdmin;
    }

当copy完这段代码后,重启服务,原来这么简单,小样儿。

解密:

AmqpAdmin 是spring整合amqp协议之后开放的一个对该协议的便携式操作类,该类可以很方便的声明一个queue/exchange,或者删除一个queue/exchange,或者清空queue/exchange。为什么按照上面一搞就有了呢?因为org.springframework.amqp.rabbit.core.RabbitAdmin#initialize中有这么一段代码:

		Collection contextExchanges = new LinkedList(
				this.applicationContext.getBeansOfType(Exchange.class).values());
		Collection contextQueues = new LinkedList(
				this.applicationContext.getBeansOfType(Queue.class).values());
		Collection contextBindings = new LinkedList(
				this.applicationContext.getBeansOfType(Binding.class).values());
		Collection customizers =
				this.applicationContext.getBeansOfType(DeclarableCustomizer.class).values();

		processDeclarables(contextExchanges, contextQueues, contextBindings);

		final Collection exchanges = filterDeclarables(contextExchanges, customizers);
		final Collection queues = filterDeclarables(contextQueues, customizers);
		final Collection bindings = filterDeclarables(contextBindings, customizers);

        // 中间省略若干行

        this.rabbitTemplate.execute(channel -> {
			declareExchanges(channel, exchanges.toArray(new Exchange[exchanges.size()]));
			declareQueues(channel, queues.toArray(new Queue[queues.size()]));
			declareBindings(channel, bindings.toArray(new Binding[bindings.size()]));
			return null;
		});

从容器中获取Exchange类型和Queue类型以及Binding类型的bean,并进行declare###,原来这么回事儿,小样儿。

PS:在mq的配置类上已经使用注解@Configuration 或者 @Component进行声明,在定义queue或者exchange上也使用了@Bean进行声明,启动的时候定义的bean也是被扫描到的,但是为什么要手动的通过QmqpAdmin进行declare呢?

你可能感兴趣的:(MQ,Spring,spring,spring,boot)