springboot 集成rabbtiMq

本文详细介绍了RabbitMQ中消息队列topic、交换器exchange和路由键routKey的概念及它们之间的关系。讲解了direct和topic类型的exchange工作原理,并通过代码示例展示了如何在SpringBoot中集成RabbitMQ,创建和绑定topic、exchange。此外,还提供了自动创建队列和交换器的代码实现。

本文主要解决以下几个问题

1、rabbtiMq的消息队列topic,交换器exchange 和 路由key  routKey的概念及关系

2、rabbitMq 消息的生产和消费的规则逻

3、springboot集成rabbitMq

4、通过代码自动创建 topic 、exchange、以及指定routKey绑定 topic 和 exchange

一、rabbtiMq的消息队列topic,交换器exchange 和 路由key  routKey的概念及关系

1、消息队列topic:  本质就是一个queue, 用来存储消息,具体可分为 消息队列,延迟队列,和死信队列。创建一个queue, 如下操作即可

public Queue(String name, boolean durable, boolean exclusive, boolean autoDelete,
      @Nullable Map<String, Object> arguments)

Params:
name – the name of the queue - must not be null; set to "" to have the broker generate the name.
durable – true if we are declaring a durable queue (the queue will survive a server restart)
exclusive – true if we are declaring an exclusive queue (the queue will only be used by the declarer's connection)
autoDelete – true if the server should delete the queue when it is no longer in use
arguments – the arguments used to declare the queue

创建延迟队列,则设置arguments 参数,设置 ttl的延迟时间即可,时间单位为毫秒

Map<String, Object> args = new HashMap<String, Object>();

args.put("x-message-ttl", 6000);

2、交换器exchange

exchange的类型主要分为direct、topic和 fanout

direct类型-直连交换机: 

最直接的理解,就是queue 和exchange 通过routKey 一对一绑定。

例如:queueA、exchange_direct 通过routKey 绑定,发消息时,指定exchange为exchange_direct,  指定路由键为  routKey, 则消息会被路由到队列queueA上,供消费者监听队列queueA并消费对应的消息

topic类型-主题交换机:

topic类型的交换机,对绑定queue的routKey,支持通配符匹配。

routKey为#:  topicExchange和queue绑定,发消息时,不指定routKey, 消费者会接收所有和#绑定的消息队列,此时功能和 fanout类型的exchange一致

routKey为routKey.#,    queueA,queueB 和 topicExchange 分别通过 routKey.# 进行绑定,发消息时,指定routKey为, routKey.a  或者 routKey.b,  对于消费者监听 queueA 和queueB 都能同时接收到消息

routKey为 *.routKey.* :   queueA 通过 a.routKey.b 和topicExchange 绑定, queueB 通过*.routKey.* 和 topicExchange绑定, 发消息时,指定 routKey 为  a.routKey.b。   则消费者监听消息时,  queueA 和queueB 都能接收到消息

routKey为 routKey时,  queueA 通过routKey 和 topicExchange 绑定,这个功能和 directExchange功能一致

二、rabbitMq 消息的生产和消费的规则逻

三、springboot集成rabbitMq

基础连接信息

public abstract class BaseMQConfig {
    private static final int CHANNEL_CACHE_SIZE = 180_000;
    private static final int CONNECTION_CACHE_SIZE = 1024;


    private String host = "";
    private Integer port = 5672;
    private String user = "root";
    private String password = "root";


    protected CachingConnectionFactory createConnectionFactory(String virtualHost) {
        CachingConnectionFactory connectionFactory = new CachingConnectionFactory(host, port);
        connectionFactory.setCacheMode(CachingConnectionFactory.CacheMode.CONNECTION);
        connectionFactory.setChannelCacheSize(CHANNEL_CACHE_SIZE);
        connectionFactory.setConnectionCacheSize(CONNECTION_CACHE_SIZE);
        connectionFactory.setUsername(user);
        connectionFactory.setPassword(password);
        connectionFactory.setPublisherReturns(false);
        connectionFactory.setPublisherConfirms(false);
        if (StringUtils.isNotBlank(virtualHost)) {
            connectionFactory.setVirtualHost(virtualHost);
        }
        return connectionFactory;
    }

    protected Binding createBinding(AmqpAdmin amqpAdmin, Queue queue, Exchange exchange) {
        Binding binding;
        if (exchange instanceof FanoutExchange) {
            binding = BindingBuilder.bind(queue)
                                    .to((FanoutExchange) exchange);
        } else if (exchange instanceof DirectExchange) {
            binding = BindingBuilder.bind(queue)
                                    .to((DirectExchange) exchange)
                                    .with(queue.getName());
        } else {
            return null;
        }
        amqpAdmin.declareBinding(binding);
        return binding;
    }

    protected RabbitTemplate createTemplate(ConnectionFactory connectionFactory, String exchange) {
        RabbitTemplate template = techRabbitBuilder.createRabbitTemplate(connectionFactory);
        template.setExchange(exchange);
        return template;
    }



    public abstract ConnectionFactory connectionFactory();

    public abstract AmqpAdmin amqpAdmin(ConnectionFactory connectionFactory);

    public abstract Exchange exchange();

    public abstract RabbitTemplate template(ConnectionFactory connectionFactory);

}

基于不同的消息队列,创建不同的admin template 和绑定关系,确保 bean的别名不同即可

@Configuration
public class CalculateMQConfig extends BaseMQConfig {

    public static final String CALBenefit_QUEUE_NAME = "queue_demo";
    public static final String CALBenefit_ROUTING_KEY = "routing.key_demo";
    public static final String CALBenefit_MEMBER_EXCHANGE = "exchange_demo";
    private static final String CALBenefit_VIRTUAL_HOST = "demo_vhost";


    public static final String NOTIFYUSER_QUEUE_NAME = "notify_user";
    public static final String NOTIFYUSER_ROUTING_KEY = "notify_user.key";

    @Bean(name = "calBenefitConnection")
    public ConnectionFactory connectionFactory() {
        return createConnectionFactory(CALBenefit_VIRTUAL_HOST);
    }

    @Bean(name = "calBenefitAmqpAdmin")
    public AmqpAdmin amqpAdmin(@Qualifier("calBenefitConnection") ConnectionFactory calBenefitConnection) {
        return new RabbitAdmin(calBenefitConnection);
    }

    @Bean(name = "calBenefitExchange")
    public DirectExchange exchange() {
        return new DirectExchange(CALBenefit_MEMBER_EXCHANGE);
    }

    @Bean(name = "calBenefitRabbitTemplate")
    public RabbitTemplate template(@Qualifier("calBenefitConnection") ConnectionFactory calBenefitConnection) {
        return createTemplate(calBenefitConnection, CALBenefit_MEMBER_EXCHANGE);
    }

    @Bean(name = "calBenefitQueue")
    public Queue contractQueue() {
        return new Queue(CALBenefit_QUEUE_NAME);
    }

    @Bean(name = "calBenefitBinding")
    public Binding contractBinding(@Qualifier("calBenefitAmqpAdmin") AmqpAdmin blackHoleAmqpAdmin,
                                   @Qualifier("calBenefitQueue") Queue contractQueue,
                                   @Qualifier("calBenefitExchange") DirectExchange contractExchange) {
        Binding binding = BindingBuilder.bind(contractQueue)
                .to(contractExchange)
                .with(CALBenefit_ROUTING_KEY);
        blackHoleAmqpAdmin.declareBinding(binding);
        return binding;
    }

    //若为多个不同host的消费者的配置,该bean 可在消费者监听时指定该bean,见下面的消费者配置
    @Bean(name="rabbitListenerContainerFactory")//和kafka的配置仓库类一莫一样很牛逼的
    public RabbitListenerContainerFactory<SimpleMessageListenerContainer> tt(){
        //ConcurrentKafkaListenerContainerFactory

        //消息的统一过滤器
        //MessageConverter messageConverter = new ObjConsert();
        SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
        factory.setConcurrentConsumers(5);//允许同时消费数量为5
        factory.setMaxConcurrentConsumers(10);//允许同时最大消费数量为10
        factory.setReceiveTimeout(10000L);//10秒
        //factory.setMessageConverter(messageConverter);//具体的逻辑要自己在ObjConsert里面写
        factory.setAcknowledgeMode(AcknowledgeMode.AUTO);//设置手动提交
        factory.setConnectionFactory(connectionFactory());
        return  factory;
    }
}

生产者发消息

 @Autowired
    @Qualifier("calBenefitRabbitTemplate_consumer")
    private AmqpTemplate rabbitTemplateConsumer;

    @GetMapping("/test")
    public void test() {
        String msg = "这是个消息";
        this.rabbitTemplateConsumer.convertAndSend(CalculateMQConfig.CALBenefit_MEMBER_EXCHANGE, CalculateMQConfig.CALBenefit_ROUTING_KEY, msg);
}

消费者 

containerFactory 可以指定消费者对应的连接,若生产者和消费者属于同一host, 则可以不配置,若同一个项目,既有生产者,又有消费者,且生产者和消费者属于不同的连接,则可以指定containerFactory确定是走那个连接进行消费

@Slf4j
@Component
@RabbitListener(containerFactory="rabbitListenerContainerFactory",bindings = {@QueueBinding(value = @Queue(value = CalculateMQConfig.CALBenefit_QUEUE_NAME, durable = "true"),
        exchange = @Exchange(value = CalculateMQConfig.CALBenefit_MEMBER_EXCHANGE, durable = "true"), key =
        CalculateMQConfig.CALBenefit_ROUTING_KEY)})
public class CalculateReceiver {
    
    @RabbitHandler
    public void process(String message) {
        log.info("事件 接受消息,message = {}", message);
    
    }


}

四、通过代码自动创建 topic 、exchange、以及指定routKey绑定 topic 和 exchange

通过amqbAdmint 创建和通过channel 创建

@Configuration
public class RabbitMqQueueExchangeCreate {

    public static String exchangeStr = "exchange_cutity";
    public static String queueStr = "queue_topic_cutiyu";
    public static String routKeyStr = "routKey.cutity";

    @Autowired
    private AmqpAdmin amqpAdmin;

    @Autowired
    @Qualifier("demoConnectionFactory")
    ConnectionFactory connectionFactory;


    @PostConstruct
    public void init(){

        Exchange exchange = new TopicExchange(exchangeStr);
        Queue queue = new Queue(queueStr);
        Binding noargs = BindingBuilder.bind(queue).to(exchange).with(routKeyStr).noargs();
        amqpAdmin.declareExchange(exchange);
        amqpAdmin.declareQueue(queue);
        amqpAdmin.declareBinding(noargs);

        System.out.println("===========");

        Connection connection = connectionFactory.createConnection();
        Channel channel = connection.createChannel(false);

        try {
            channel.exchangeDeclare(RabbitMqCnst.EXCHANGE_TOPIC_DEMO, BuiltinExchangeType.TOPIC,true);
            channel.exchangeDeclare(RabbitMqCnst.EXCHANGE_FANOUT_DEMO, BuiltinExchangeType.FANOUT,true);

            channel.queueDeclare(RabbitMqCnst.QUEUE_TOPIC_DEMO, false, false, false, null);
            channel.queueDeclare(RabbitMqCnst.QUEUE_TOPIC_DEMO_A_B, false, false, false, null);
            channel.queueDeclare(RabbitMqCnst.QUEUE_TOPIC_DEMO_C_D, false, false, false, null);
            channel.queueDeclare(RabbitMqCnst.E_QUEUE_TOPIC_DEMO_F, false, false, false, null);
            channel.queueDeclare(RabbitMqCnst.G_QUEUE_TOPIC_DEMO_H, false, false, false, null);


            channel.queueBind(RabbitMqCnst.QUEUE_TOPIC_DEMO, RabbitMqCnst.EXCHANGE_TOPIC_DEMO, RabbitMqCnst.ROUTKEY_DEMO);
            channel.queueBind(RabbitMqCnst.QUEUE_TOPIC_DEMO_A_B, RabbitMqCnst.EXCHANGE_TOPIC_DEMO, RabbitMqCnst.ROUTKEY_DEMO_A);
            channel.queueBind(RabbitMqCnst.QUEUE_TOPIC_DEMO_C_D, RabbitMqCnst.EXCHANGE_TOPIC_DEMO, RabbitMqCnst.ROUTKEY_DEMO_X);
            channel.queueBind(RabbitMqCnst.E_QUEUE_TOPIC_DEMO_F, RabbitMqCnst.EXCHANGE_TOPIC_DEMO, RabbitMqCnst.E_ROUTKEY_DEMO_F);
            channel.queueBind(RabbitMqCnst.G_QUEUE_TOPIC_DEMO_H, RabbitMqCnst.EXCHANGE_TOPIC_DEMO, RabbitMqCnst.X_ROUTKEY_DEMO_X);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值