springboot整合rabbitmq实战

SpringBoot整合RabbitMQ非常简单,官网有对应的starter,可以自动装配。本文使用官网的starter整合rabbitmq。个人觉得官方有starter的组件就使用starter整合,不要再像以前那样自己写配置客户端,也不要二次封装,因为见过一些别人封装的代码,觉得把rabbitmq很多功能阉割了,也没有springboot提供的starter好用灵活。

下面开始集成rabbitmq

首先pom.xml中引入starter

        
            org.springframework.boot
            spring-boot-starter-amqp
        

application.properties配置文件中添加rabbitmq配置信息

spring.rabbitmq.host=192.168.2.198
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest2018
spring.rabbitmq.publisher-confirms=true
spring.rabbitmq.virtual-host=/
#并行消费者数量
spring.rabbitmq.constomers=5
spring.rabbitmq.max-constomers=20

定义一个queue的枚举类

public enum QueueConstants {
    QUEUE_TEST1("queue_test_one", "队列1"),
    QUEUE_TEST2("queue_test_two", "队列2");

    String code;
    String desc;

    QueueConstants(String code, String desc) {
        this.code = code;
        this.desc = desc;
    }

    public String getCode() {
        return code;
    }

    public String getDesc() {
        return  desc;
    }
}

新建一个配置类,用于配置rabbitmq的queue, exchange, binding及customers,自定义messageConverter等等。配置完成后项目启动可以自动建立对应的queue和exchange。当然也可以通过rabbitmq控制台创建。注意:通过控制台创建,queue和exchange的属性(如:durable, autoDelete等)要和此处相对应,否则启动会报异常:Caused by: com.rabbitmq.client.ShutdownSignalException: channel error; protocol method: #method(reply-code=406, reply-text=PRECONDITION_FAILED - inequivalent arg 'durable' for exchange 'maxwell' in vhost '/': received 'true' but current is 'false', class-id=40, method-id=10)

import com.xhd.constants.QueueConstants;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class RabbitmqConfig {
    /**
     * 此处使用自动装配,定义customers和max-customers
     * @param connectionFactory
     * @return
     */
    @Bean
    @ConfigurationProperties(prefix = "spring.rabbitmq")
    public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(ConnectionFactory connectionFactory) {
        SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory);
//        factory.setMessageConverter(new FastJsonMessageConverter());
        return factory;
    }

    @Bean("queue1")
    public Queue queue1() {
        return new Queue(QueueConstants.QUEUE_TEST1.getCode());
    }
    @Bean("queue2")
    public Queue queue2() {
        return new Queue(QueueConstants.QUEUE_TEST2.getCode());
    }

    /**
     * 定义exchange. 根据需要定义不同的exchange
     * @return
     */
    @Bean
    public TopicExchange exchange() {
        return new TopicExchange("exchange_test", true, false);
    }

    @Bean
    Binding bindingExchangeQueue(@Qualifier("queue1") Queue queue, TopicExchange exchange) {
        return BindingBuilder.bind(queue).to(exchange).with("topic.message");
    }

    @Bean
    Binding bindingExchangeMessages(@Qualifier("queue2") Queue queueMessages, TopicExchange exchange) {
        return BindingBuilder.bind(queueMessages).to(exchange).with("topic.#");
    }
}

发送消息

    @Autowired
    private AmqpTemplate rabbitTemplate;

    /**
     * 发送字符串消息
     */
    @Test
    public void sendToMQ() {
        String content = "this is test content";
        rabbitTemplate.convertAndSend(QueueConstants.QUEUE_TEST1.getCode(), content);
    }

    /**
     * 直接发送对象
     */
    @Test
    public void sendToMQ2() {
        User user = new User();
        user.setId(190L);
        user.setUsername("xxxxx");
        user.setEmail("[email protected]");
        rabbitTemplate.convertAndSend(QueueConstants.QUEUE_TEST2.getCode(), user);
    }

监听消息并接收

import com.rabbitmq.client.Channel;
import com.xhd.domain.User;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

@Component
@Slf4j
public class RabbitmqConsumer {

    @RabbitHandler
    @RabbitListener(queues = "queue_test_one")
    public void processQueue1(Message message, Channel channel) {
//        //处理成功,消息已消费
//        channel.basicAck(message.getMessageProperties().getDeliveryTag(), true);
//        //处理失败,重新放入队列并重试
//        channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);
//        //处理失败,丢在一边不重试
//        channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, false);
        log.info("data:" + message);
    }

    @RabbitHandler
    @RabbitListener(queues = "queue_test_one")
    public void processQueue13(String data) {
        try {
            log.info("data:" + data);
            //业务处理 ...

        } catch (Exception e) {
            log.error("peocess error", e);
            throw new RuntimeException("process error", e); //抛出异常, 消息重新入列并重试
        }

    }

    @RabbitHandler
    @RabbitListener(queues = "queue_test_two")
    public void processQueue2(User user) {
        log.info("user:" + user);
    }
}

参考资料:https://docs.spring.io/spring-amqp/docs/2.0.2.RELEASE/reference/html/

你可能感兴趣的:(springboot)