springboot项目中RabbitMQ的使用

springboot项目中RabbitMQ的使用

说明:本文是根据我自己项目实际开发中的情况整理的,项目中要从MQ1中消费数据,处理完成后放到MQ2中。
1. pom引入
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
2. yml配置
spring:
    # 消费者
    consumerMq:
        host: 127.0.0.1
        port: 5672
        username: 123
        password: 123
        virtual-host: 478026c-bd27-4918-bd27-478026c9e7a0
    # 生产者MQ
    producerMq:
        host: 127.0.0.2
        port: 5672
        username: 123
        password: 123
        virtual-host: 478026c-bd27-4918-bd27-478026c9e7a0
        #生产者方开启消息确认的配置
        publisher-confirms: true
        publisher-returns: true
3. 创建生产者MQ
package com.demo.config.rabbitConfig;

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;

@Configuration
@Slf4j
public class RabbitConfig {

    /**
     * 消费者MQ
     *
     * @param host
     * @param port
     * @param username
     * @param password
     * @return
     */
    @Bean(name = "consumerConnection")
    @Primary
    public ConnectionFactory consumerConnection(
            @Value("${spring.consumerMq.host}") String host,
            @Value("${spring.consumerMq.port}") int port,
            @Value("${spring.consumerMq.username}") String username,
            @Value("${spring.consumerMq.password}") String password,
            @Value("${spring.consumerMq.virtual-host}") String virtualHost
    ) {
        CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
        connectionFactory.setHost(host);
        connectionFactory.setPort(port);
        connectionFactory.setUsername(username);
        connectionFactory.setVirtualHost(virtualHost);
        connectionFactory.setPassword(password);
        return connectionFactory;
    }

    @Bean(name = "consumerFactory")
    public SimpleRabbitListenerContainerFactory consumerFactory(SimpleRabbitListenerContainerFactoryConfigurer configurer, @Qualifier("consumerConnection") ConnectionFactory connectionFactory) {
        SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
        //初始化消费者数量
        factory.setConcurrentConsumers(2);
        //最大消费者数量
        factory.setMaxConcurrentConsumers(4);
        //手动确认消息
        factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
        configurer.configure(factory, connectionFactory);
        return factory;
    }

    /**
     * 生产者MQ
     * @param host
     * @param port
     * @param username
     * @param password
     * @param virtualHost
     * @param publisherReturns
     * @return
     */
    @Bean("producerFactory")
    public ConnectionFactory producerFactory(
            @Value("${spring.producerMq.host}") String host,
            @Value("${spring.producerMq.port}") int port,
            @Value("${spring.producerMq.username}") String username,
            @Value("${spring.producerMq.password}") String password,
            @Value("${spring.producerMq.virtual-host}") String virtualHost,
            @Value("${spring.producerMq.publisher-returns}") boolean publisherReturns
    ) {
        CachingConnectionFactory connectionFactory = new CachingConnectionFactory(host, port);
        connectionFactory.setHost(host);
        connectionFactory.setPort(port);
        connectionFactory.setUsername(username);
        connectionFactory.setPassword(password);
        connectionFactory.setVirtualHost(virtualHost);
        connectionFactory.setPublisherReturns(publisherReturns);
        return connectionFactory;
    }

    @Bean("rabbitTemplateProducer")
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    public RabbitTemplate createRabbitTemplate(@Qualifier("producerFactory") ConnectionFactory connectionFactory) {
        RabbitTemplate template = new RabbitTemplate(connectionFactory);
        template.setMandatory(true);
        return template;
    }

    /**
     * 创建 RabbitAdmin 类,这个类封装了对 RabbitMQ 管理端的操作!
     * <p>
     * 比如:Exchange 操作,Queue 操作,Binding 绑定 等
     *
     * @return
     */
    @Bean("rabbitAdminProducer")
    public RabbitAdmin rabbitAdmin(@Qualifier("producerFactory") ConnectionFactory connectionFactory) {
        RabbitAdmin rabbitAdmin = new RabbitAdmin(connectionFactory);
        // 只有设置为 true,spring 才会加载 RabbitAdmin 这个类
        rabbitAdmin.setAutoStartup(true);
        return rabbitAdmin;
    }

    /**
     * @return 抽象队列
     */
    @Bean
    public Queue testQueue() {
        //true 是否持久
        return new Queue("test_queue",true);
    }

    /**
     * Direct交换机 起名:directExchange  直连交换机,需要双方遵守routingKey
     */
    @Bean
    public DirectExchange defaultExchange() {
        return new DirectExchange("test_exchange");
    }

    /**
     * 绑定  将队列和交换机绑定, 并设置用于匹配键:directRouting
     */
    @Bean
    public Binding testBinding() {
        return BindingBuilder.bind(testQueue()).to(defaultExchange()).with("test_queue");
    }
}
4. 使用springboot管理的MQ作为消费者(方法所在类对象要被spring管理,比如使用注解@Component)
@RabbitListener(queues = {"test_queue")
@RabbitHandler
public void process(Channel channel, Message message) {
    long tag = 0L;
    try {
        tag = message.getMessageProperties().getDeliveryTag();
        //消息实体转换
        String jsonStr = new String(message.getBody());
        
    } catch (WholeException e) {
        log.error("消费出错!error={}", e.getMessage(), e);
    } finally {
        // false只表示当前消费者收到,true表示所有消费者已收到
         channel.basicAck(tag, false);
    }
}
5. 生产者使用
@Autowired
private AmqpTemplate rabbitTemplateProducer;

public void send(String msgList, String exchange, String queue) {
    try {
        rabbitTemplateProducer.convertAndSend(exchange, queue, msgList);
    } catch (Exception e) {
        log.error("消息写入rabbit出错", e);
    }
}
6. RabbitAdmin或者队列消息数量
// 该方法我在使用的时候主要是在写入之前判断当前队列消息堆积数量,超过设定的阈值就会停止写入并循环判断等待,直到队列数据小于阈值。
@Autowired
private RabbitAdmin rabbitAdminProducer;

public int getQuueMsgCount(String queue){
        AMQP.Queue.DeclareOk declareOk = rabbitAdminProducer.getRabbitTemplate().execute(channel -> channel.queueDeclarePassive(queue));
        return declareOk.getMessageCount();
    }
以上就是我的主要处理的部分,具体逻辑业务我们都有自己的实现没有太大意义。以上对MQ的使用是基于MQ环境服务都搭建完成的前提下完成的,如果你在使用中有问题,请先确保你的MQ环境服务没有问题。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值