Spring Boot RabbitMQ发布者和接收者在同一项目上

时间:2018-08-16 22:02:07

标签: spring-boot rabbitmq

我有一个应用程序(如微服务),该应用应该从其他应用程序(微服务)发送和接收消息。该应用程序有多个发布者,每个发布者都发布到一个特定的队列,还有几个订阅者类,每个订阅者只订阅一个队列。不幸的是,我的订户类正在消耗与我发布的消息相同的消息。我该怎么办?

这是我的代码: a)发布者1-没有侦听器方法,因为它仅发布到my.queues.queue1

@Configuration
public class RabbitQueue1Publisher{
private static final String QUEUE_NAME = "my.queues.queue1";

    @Bean
    public ConnectionFactory connectionFactory() {
        CachingConnectionFactory connectionFactory = new CachingConnectionFactory("http://127.0.0.1:1675");
        connectionFactory.setUsername("guest");
        connectionFactory.setPassword("guest");
        return connectionFactory;
    }

    @Bean
    public Queue simpleQueue() {
        return new Queue(QUEUE_NAME);
    }

    @Bean
    public MessageConverter jsonMessageConverter(){
        return new Jackson2JsonMessageConverter();
    }

    @Bean
    public RabbitTemplate rabbitTemplate() {
        RabbitTemplate template = new RabbitTemplate(connectionFactory());
        template.setRoutingKey(QUEUE_NAME);
        template.setMessageConverter(jsonMessageConverter());
        return template;
    }
}

b)Publisher 2-也没有侦听器方法,因为它仅发布到my.queues.queue2

@Configuration
public class RabbitQueue2Publisher{
private static final String QUEUE_NAME = "my.queues.queue2";

    @Bean
    public ConnectionFactory connectionFactory() {
        CachingConnectionFactory connectionFactory = new CachingConnectionFactory("http://127.0.0.1:1675");
        connectionFactory.setUsername("guest");
        connectionFactory.setPassword("guest");
        return connectionFactory;
    }

    @Bean
    public Queue simpleQueue() {
        return new Queue(QUEUE_NAME);
    }

    @Bean
    public MessageConverter jsonMessageConverter(){
        return new Jackson2JsonMessageConverter();
    }

    @Bean
    public RabbitTemplate rabbitTemplate() {
        RabbitTemplate template = new RabbitTemplate(connectionFactory());
        template.setRoutingKey(QUEUE_NAME);
        template.setMessageConverter(jsonMessageConverter());
        return template;
    }
}

c)使用者1-从队列3进行消费。有一个监听方法

@Configuration
public class RabbitQueue3Subscriber{
private static final String QUEUE_NAME = "my.queue.queue3";

    @Autowired
    private Queue3Listener Queue3Listener;

    @Bean
    public ConnectionFactory connectionFactory() {
        CachingConnectionFactory connectionFactory = new CachingConnectionFactory("http://127.0.0.1:15672");
        connectionFactory.setUsername("guest");
        connectionFactory.setPassword("guest");
        return connectionFactory;
    }

    @Bean
    public Queue simpleQueue() {
        return new Queue(QUEUE_NAME);
    }

    @Bean
    public MessageConverter jsonMessageConverter(){
        return new Jackson2JsonMessageConverter();
    }

    @Bean
    public RabbitTemplate rabbitTemplate() {
        RabbitTemplate template = new RabbitTemplate(connectionFactory());
        template.setRoutingKey(QUEUE_NAME);
        template.setMessageConverter(jsonMessageConverter());
        return template;
    }

    @Bean
    public SimpleMessageListenerContainer userListenerContainer() {
        SimpleMessageListenerContainer listenerContainer = new SimpleMessageListenerContainer();
        listenerContainer.setConnectionFactory(connectionFactory());
        listenerContainer.setQueues(simpleQueue());
        listenerContainer.setMessageConverter(jsonMessageConverter());
        listenerContainer.setMessageListener(Queue3Listener);
        listenerContainer.setAcknowledgeMode(AcknowledgeMode.AUTO);
        return listenerContainer;
    }
}

d)消费者2-从队列4消费。有一个监听方法

@Configuration
public class RabbitQueue4Subscriber{
private static final String QUEUE_NAME = "my.queue.queue4";

    @Autowired
    private Queue4Listener Queue4Listener;

    @Bean
    public ConnectionFactory connectionFactory() {
        CachingConnectionFactory connectionFactory = new CachingConnectionFactory("http://127.0.0.1:15672");
        connectionFactory.setUsername("guest");
        connectionFactory.setPassword("guest");
        return connectionFactory;
    }

    @Bean
    public Queue simpleQueue() {
        return new Queue(QUEUE_NAME);
    }

    @Bean
    public MessageConverter jsonMessageConverter(){
        return new Jackson2JsonMessageConverter();
    }

    @Bean
    public RabbitTemplate rabbitTemplate() {
        RabbitTemplate template = new RabbitTemplate(connectionFactory());
        template.setRoutingKey(QUEUE_NAME);
        template.setMessageConverter(jsonMessageConverter());
        return template;
    }

    @Bean
    public SimpleMessageListenerContainer userListenerContainer() {
        SimpleMessageListenerContainer listenerContainer = new SimpleMessageListenerContainer();
        listenerContainer.setConnectionFactory(connectionFactory());
        listenerContainer.setQueues(simpleQueue());
        listenerContainer.setMessageConverter(jsonMessageConverter());
        listenerContainer.setMessageListener(Queue4Listener);
        listenerContainer.setAcknowledgeMode(AcknowledgeMode.AUTO);
        return listenerContainer;
    }
}

尽管我正在向不同队列发布和使用不同队列,但最终还是消耗了我产生的相同消息。有人可以指出我做错了什么或提出解决方法吗?

1 个答案:

答案 0 :(得分:0)

这是对我有用的方法。我有Rabbitmq的发行商和消费者。如果它们是同一项目或不同项目的一部分,则不重要。

发布者:

发布者配置

@Configuration
class PublisherConfig{
String queueName = "com.queueName";
    String routingKey = "com.routingKey";
    String exchange = "com.exchangeName";

    @Bean
    Queue queue() {
        return new Queue(queueName, false);
    }

    @Bean
    TopicExchange exchange() {
        return new TopicExchange(exchange);
    }

    @Bean
    Binding binding(Queue queueFoo, TopicExchange exchange) {
        return BindingBuilder.bind(queueFoo).to(exchange).with(routingKey);
    }

    //Required only if you want to pass custom object as part of payload
    @Bean
    public MappingJackson2MessageConverter jackson2Converter() {
        return new MappingJackson2MessageConverter();
    }
}

发布消息

    @Autowired private RabbitMessagingTemplate rabbitMessagingTemplate;
    @Autowired private MappingJackson2MessageConverter mappingJackson2MessageConverter;

    rabbitMessagingTemplate.setMessageConverter(this.mappingJackson2MessageConverter);
    rabbitMessagingTemplate.convertAndSend(exchange, routingKey, employObj)

消费者

消费者配置

@Configuration
public class RabbitMQConfiguration implements RabbitListenerConfigurer {
    public MappingJackson2MessageConverter jackson2Converter() {
        return new MappingJackson2MessageConverter();
    }

    @Bean
    public DefaultMessageHandlerMethodFactory handlerMethodFactory() {
        DefaultMessageHandlerMethodFactory factory = new DefaultMessageHandlerMethodFactory();
        factory.setMessageConverter(jackson2Converter());
        return factory;
    }

    @Override
    public void configureRabbitListeners(RabbitListenerEndpointRegistrar registrar) {
        registrar.setMessageHandlerMethodFactory(handlerMethodFactory());
    }
}

听一条消息

    @RabbitListener(queues = "com.queueName")
    public void receiveMessage(Employee employee) {
        // More code
    }

您可以将Publisher和Listener配置封装在两个不同的@configuration文件中。

希望这对您有帮助


P.S。 OP要求解释。在这里:

交换和路由密钥

发布者将消息发布到具有特定exchange的{​​{1}}。路由键有助于区分消息的类型。 假设: 发送所有用户登录消息,路由键为“ user_logged_in”。 使用“ email_sent”发送所有通过电子邮件发送的消息。

队列:

一旦路由密钥与交换机绑定,就会出现队列。 队列附加了交换和路由密钥,所有已发布的消息都将位于此队列中。

现在,消费者明确地连接到此类队列并监听消息。

因此,发布者配置和使用者配置中的队列名称必须相同。

  

发布商启动后,您实际上可以访问RabbitMq仪表板   并查看交换,路由键和队列以了解其工作原理。