RabbitMQ+Springboot2.x项目搭建

本文详细介绍了如何将RabbitMQ与Spring Boot项目集成,包括配置文件设置、pom文件添加、简单模式及direct路由直连模式的具体实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言:
最初只在普通maven项目中单独配置过rabbitMQ,并简单的实现了各种模式的操作,但总归不是实际开发的配置,甚至于连自己的项目都无法融入。使用别人已经写好的配置直接调用,也不能掌握其中的细节,百度了一番,也没有看到合适的初学者的文章,故写一篇文章来培训自己,也给后来人一点参考。


一、前期准备

必须安装好rabbitmq客户端并配置了用户与虚拟主机信息,才可以进行以下操作

1、application配置文件增加连接到rabbitmq的信息

#配置自己的rabbitmq地址与端口号,这里采用的是application.yml的方式
spring:
  application:
    name: springboot-rabbitMQ
  rabbitmq:
    host: 127.0.0.1
    port: 5672
    username: guest
    password: guest
    virtual-host: /tempHost
    
#项目运行时的端口号,默认8080
server:
  port: 8888

2、添加pom文件

在测试过程中,出现了项目跑起来,也创建了队列,但是访问不到controller的情况,就是因为忘了加pom文件…

		<!--	spring的web支持	-->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<!--	rabbitmq的注解支持	-->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-amqp</artifactId>
		</dependency>

二、简单模式

1、添加配置类

import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;

public class RabbitMQConfig {
    public static String SQFinishRegister = "SQ_FinishRegister";
    //简单模式只需要队列
    //不同的模式单独设置内部类,调用时可区分使用的属性与类
    //全为public static final,放开权限,可在注解中访问到属性值,否则注解无法使用
    //simple_queue_FinishRegister的命名方式容易出现大量冗余名称,降低可读性,故采用简称SQ_业务名称
    //假设完成注册,发送注册成功的短信
    public static class Simple {
        public static class SQueueField {
            public static final String SQFinishRegister = "SQ_FinishRegister";
        }

        //创建bean放在模式配置类中,可以访问所有的内部类属性
        //需要使用这个bean时,只需要调用方法,就可以获取对应的队列类
        @Bean
        public Queue createSimpleQueueWhenRegister() {
            return QueueBuilder.durable(SQueueField.SQFinishRegister).build();
        }
    }

    //对外暴露队列名,使某些方法中调用可以简化代码
    public static String SQFinishRegister() {
        return Simple.SQueueField.SQFinishRegister;
    }
}

2、创建简单模式生产者

import com.mq.rabbitmq.config.RabbitMQConfig;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;


@RestController
public class SimpleProvider {

	//不同于使用redisTemplate时那样,单独设置bean信息注入bean,
	//配置文件中填写了ip账号等信息,spring就会自动注入好相关信息
    @Autowired
    private RabbitTemplate rabbitTemplate;

    @GetMapping("/simple_FinishRegister")
    public void simpleFinishRegister() {
        //参数1:队列名称
        //参数2,发送的消息数据
        rabbitTemplate.convertAndSend(RabbitMQConfig.SQFinishRegister(), "this is simple msg");
    }

}

3、创建简单模式消费者

import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import static com.mq.rabbitmq.config.RabbitMQConfig.Simple.SQueueField.SQFinishRegister;

@Component//需要注册进入ioc才能进行监听
public class SimpleCustomer {

    /**
     * simple消费者
     *    参数@Queue:队列:
     *       参数value:队列名称,不填则使用临时队列
     *       参数declare:是否持久化,默认为true
     *       参数exclusive:是否是独占队列,默认为false
     *       参数autoDelete:是否自动删除,默认为false
     * @param msg
     */
    @RabbitListener(queuesToDeclare = @Queue(value = SQFinishRegister, declare = "true", exclusive = "false", autoDelete = "false")
    )
    public void simpleFinishRegister(String msg) {
        System.out.println("simpleFinishRegister = " + msg);
    }

}

运行简单模式

当项目运行,并访问localhost:8888/simple_FinishRegister时,控制台会输出

simpleFinishRegister = this is simple msg

就代表简单模式与Springboot的合并创建好了

三、direct路由直连模式

在简单模式中创建的RabbitMQConfig配置类中添加direct类的配置

public class RabbitMQConfig {
	//上面是简单模式的配置信息...

    //路由直连模式设置队列,路由值,交换机
    //假设完成购买商品,发送短信和邮箱
    //创建bean放在模式配置类中,可以访问所有的内部类属性
    public static class Direct {

        public static class DQueueField {
            public static final String DQBuyGoods = "DQ_BuyGoods";
        }

        //路由Key不需要创建bean
        public static class DRoutKeyField {
            public static final String DRBuyGoods = "DR_BuyGoods";
        }

        public static class DExchangeField {
            public static final String DEBuyGoods = "DE_BuyGoods";
        }

        @Bean
        public static Queue directQueueWhenBuyGoods() {
            return QueueBuilder.durable(DQueueField.DQBuyGoods).build();
        }

        @Bean
        //不要创建Exchange,要指定是哪种交换机(DirectExchange,FanoutExchange,TopicExchange),不然设置bing连接时会返回值不对应
        public static DirectExchange directExchangeWhenBuyGoods() {
            return ExchangeBuilder.directExchange(DExchangeField.DEBuyGoods).build();
        }

        @Bean
        public static Binding directBindingWhenBuyGoods() {
            return BindingBuilder.bind(directQueueWhenBuyGoods()).to(directExchangeWhenBuyGoods()).with(DRoutKeyField.DRBuyGoods);
        }
    }

    //提供对外暴露字段名的方法,简化调用属性时的代码编写
    public static String DQBuyGoods() {
        return Direct.DQueueField.DQBuyGoods;
    }

    public static String DRBuyGoods() {
        return Direct.DRoutKeyField.DRBuyGoods;
    }

    public static String DEBuyGoods() {
        return Direct.DExchangeField.DEBuyGoods;
    }
}

2、创建直连模式生产者

import com.mq.rabbitmq.config.RabbitMQConfig;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class DirectProvider {
    @Autowired
    private RabbitTemplate rabbitTemplate;

    @GetMapping("/direct_BuyGoods")
    public void directBuyGoods() {
        //idea中ctrl+p可以看到当前方法的参数列表
        //生产者不需要绑定队列,由交换机决定消息发送给谁
        //参数1:交换机名称
        //参数2:路由key
        //参数3:发送的消息数据,已封装可以用object,会自动转换为byte
        for (int i = 0; i < 4; i++) {
            rabbitTemplate.convertAndSend(RabbitMQConfig.Direct.DExchangeField.DEBuyGoods, RabbitMQConfig.DRBuyGoods(), "this is direct msg" + i);
        }
    }
}

3、创建直连模式消费者

import com.mq.rabbitmq.config.RabbitMQConfig;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;


@Component
public class DirectCustomer {

    /**
     * direct消费者
     *
     * @param msg
     */
    //direct消费者需要bind绑定交换机
    //QueueBinding参数:
    //value绑定队列名,如果不声明名称,则创建临时队列,
    //exchange绑定交换机,type指定路由模式的类型(direct或topic),默认direct,name为交换机名称,不指定则使用默认交换机
    //key为路由key,可用{}绑定多个路由key
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(RabbitMQConfig.Direct.DQueueField.DQBuyGoods),
            exchange = @Exchange(
                    type = "direct",
                    name = RabbitMQConfig.Direct.DExchangeField.DEBuyGoods),
            key = {RabbitMQConfig.Direct.DRoutKeyField.DRBuyGoods})
    )
    public void directBuyGoods(String msg) {
        System.out.println("directBuyGoods = " + msg);
    }
}

运行直连模式

重启项目,访问localhost:8888/direct_BuyGoods,看到控制台输出以下信息就代表本地配置成功了

directBuyGoods = this is direct msg0
directBuyGoods = this is direct msg1
directBuyGoods = this is direct msg2
directBuyGoods = this is direct msg3

思考

假设现在为一个direct模式的交换机绑定了两个消费者,会有什么效果呢?
广播模式?工作模式?

增加一个直连模式消费者

    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(RabbitMQConfig.Direct.DQueueField.DQBuyGoods),
            exchange = @Exchange(
                    type = "direct",
                    name = RabbitMQConfig.Direct.DExchangeField.DEBuyGoods),
            key = {RabbitMQConfig.Direct.DRoutKeyField.DRBuyGoods})
    )
    public void directBuyGoods2(String msg) {
        System.out.println("directBuyGoods2 = " + msg);
    }

重启项目,再次访问localhhost:8888/direct_BuyGoods,发现控制台输出了

directBuyGoods2 = this is direct msg0
directBuyGoods = this is direct msg1
directBuyGoods2 = this is direct msg2
directBuyGoods = this is direct msg3

当直连模式不使用临时队列,而使用声明后的队列,并绑定了两个消费者后,变成了带路由的工作模式

回想一下work模式应该不难理解,单条队列绑定两个消费者,就是work模式,平均分配消息,只不过这里多了个路由key

总结,其实RabbitMQ的模式中,其实交换机和队列是分开设计的

在路由系列中(fanout,direct,topic),
    direct和topic实际上只关注了交换机的路由编写方式,与队列上有多少个消费者无关,
    fanout也是只关注谁绑定了交换机,究竟有多少个消费者绑定,生产者并不关心
在非路由系列中(simple,work)
	关注的是消费者如何与消息队列绑定,消息队列如何分发消息给消费者

其实在工作当中不必按照固定的模式,而是应该按照实际需求,灵活的配置消息分发方式。

2020-09-26 pm


展望1——完成其余模式的编写

展望2——改进代码

未完待续...

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值