RabbitMQ入门

概述

RabbitMQ采用Erlang语言书写,不容易扩展,但是使用较为方便,属于常用消息中间件的一种。

本篇文章主要为入门所用,并没有对RabbitMQ进行详细的介绍,旨在能以最简单的代码能跑出结果,且代码都有详细注释。

基础概念

其中主要需要了解的概念如下:
Queue 队列,是RabbitMQ的内部对象,用于存储消息
Exchange 交换机,生产者将消息发送到交换机,交换机再发送给对应的队列
Binding 绑定,用于绑定交换机和对应的队列,并设置他们之间的路由键
routing key 路由键,用于指定消息的路由规则,也就是消息的传递路径

交换机的种类:
Direct Exchange
直连交换机,要求消息的路由键与绑定的路由键完全一致
Fanout Exchange
扇形交换机,路由键无效,消息会发送到所有与交换机绑定的队列上
Topic Exchange
主题交换机,会进行路由键的匹配,使用符号“#”匹配多个词,符号“ ”匹配不少于一个词,例如topic.1.2 与topic.1的区别
Header Exchange
头交换机,路由键无效,使用头属性进行匹配。

以下会有两个简单的RabbitMQ整合SpringBoot的简单例子,介绍直连主题交换机的使用

image.png

安装Rabbitmq

这里使用Docker进行一个简单的安装

  1. 一台腾讯云服务器,CentOS7,已经关闭linux系统防火墙
  2. 云控制台防火墙已经打开15672/5672两个端口
  3. 安装好docker
    docker拉取镜像,默认最新版
docker pull rabbitmq

image.png
查看自己的镜像

docker images

image.png
直接启动,这里没有设置密码,使用的是默认的

docker run -d -p 5672:5672 -p 15672:15672 --name rabbitmq rabbitmq:latest

image.png
因为默认是没有开启Web显示的版本,所以要手动打开
进入RabbitMQ内部

docker exec -it 43f546fbb437 /bin/bash

打开插件

rabbitmq-plugins enable rabbitmq_management

image.png
直接访问 ip:15672,默认账号与密码均为 guest

image.png

使用

1.整合SpringBoot

添加依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
        </dependency>

2.配置文件

这里如果是本地,填写127.0.0.1
在浏览器上登录时的端口是15672,端口号为安装时自己设定的
用户名和密码这里都是使用默认的

#RabbitMQ的连接配置
spring:
  rabbitmq:
    host: 你的ip
    port: 5672
    username: 默认账号(guest) 
    password: 默认密码(guest)
    virtual-host: /

server:
  port: 8555

3.创建直连交换机

(1)创建配置类

这里选用的是直连交换机
配置类中需要定义队列,交换机,以设置队列和交换机互相绑定
image.png
简单用网上的一个图介绍以下的代码:

  1. 定义直连交换机TestDirectExchange(),以Bean注入
  2. 定义队列TestDirectQueue(),以Bean注入
  3. 将交换机和队列进行绑定,使其形成通路
  4. 消息在被生产出来后,指定对应的交换机发送到对应的队列中
  5. 消费者监听这个队列便可直接消费消息
@Configuration
public class RabbitMQConfig {
    //定义队列
    @Bean
    public Queue TestDirectQueue(){
        // durable:是否持久化,默认是false,持久化队列:会被存储在磁盘上,当消息代理重启时仍然存在,暂存队列:当前连接有效
        // exclusive:默认也是false,只能被当前创建的连接使用,而且当连接关闭后队列即被删除。此参考优先级高于durable
        // autoDelete:是否自动删除,当没有生产者或者消费者使用此队列,该队列会自动删除。
        // return new Queue("TestDirectQueue",true,true,false);

        //一般设置一下队列的持久化就好,其余两个就是默认false
        return new Queue("TestDirectQueue",true);
    }

    /**
     * 定义一个直连交换机
     * 开启持久化
     * 当没被使用时,自动删除
     * @return  返回交换机
     */
    @Bean
    DirectExchange TestDirectExchange(){
        return new DirectExchange("TestDirectExchange",true,false);
    }


    /**
     * 使用路由键TestDirectRouting
     * 绑定当前的 队列 TestDirectQueue() 和 直连交换机 TestDirectExchange()
     * @return  返回绑定
    */
    @Bean
    Binding bindingDirect(){
        return BindingBuilder.bind(TestDirectQueue()).to(TestDirectExchange()).with("TestDirectRouting");
    }

    @Bean
    DirectExchange lonelyDirectExchange() {
        return new DirectExchange("lonelyDirectExchange");
    }
    
}

(2)创建生产者

这里是采用了接口的方式,将消息存储到一个map集合中

  1. 创建消息id,消息内容,消息日期,封装到Map集合中
  2. 使用rabbitTemplate指定对应的交换机和队列发送消息
@RestController
public class SendMessageController {

    @Resource
    RabbitTemplate rabbitTemplate;
    
    @GetMapping("/{messageData}")
    public String sendDirectMessage(@PathVariable("messageData") String msg){

        //设置一个随机数的消息id
        String messageId = String.valueOf(UUID.randomUUID());
        //设置消息内容
//        String messageData = "hello,my friends";
        //设置创建时间
        String createTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        //使用map存储
        Map<String,Object> map = new HashMap<>();
        map.put("messageId",messageId);
        map.put("messageData",msg);
        map.put("createTime",createTime);
        //将消息绑定路由key,发送到直连交换机TestDirectExchange
        rabbitTemplate.convertAndSend("TestDirectExchange","TestDirectRouting",map);
        return "OK!";
    }
    
}

(3)创建消费者

两种方式都可以进行监听:

  • 第一种是放在类上面监听,使用@RabbitHandler注解来表示该方法需要进行rabbit信息的处理
  • 第二种方式是采用方法直接监听
    监听时可以直接使用对应的Map集合来获取数据
//类监听,并选择具体的方法来处理监听
@Component
@RabbitListener(queues = "TestDirectQueue")
public class DirectReceiver {

    @RabbitHandler
    public void process(Map<String,Object> testMessage){
        System.out.println("Direct直连消费者收到消息: "+testMessage.get("messageData"));
    }

}

*********************************************************************************************
//直接方法监听
@Component
public class DirectReceiver {

   @RabbitListener(queues = "TestDirectQueue")
    public void process(Map<String,Object> testMessage){
        System.out.println("Direct直连消费者收到消息: "+testMessage.get("messageData"));
    }
}

4.创建topic交换机

(1)配置文件

topic交换机会进行绑定建的匹配,只有当消息的路由规则和队列绑定的路由规则相符合时,消息才会被发送到对应的队列中

  1. 建立两个队列topic.man与topic.woman
  2. 队列与交换机进行绑定
  3. 绑定时会按照路由键进行适配,topic.#表示两个队列都可以收到消息
@Configuration
public class TopicRabbitConfig {

    //设置绑定建
    public static final String man = "topic.man";
    public static final String woman = "topic.woman";

    //定义两个队列
    @Bean
    public Queue firstQueue(){
        return new Queue("topic.man");
    }

    @Bean
    public Queue secondQueue(){
        return new Queue("topic.woman");
    }

    //定义一个交换机
    @Bean
    TopicExchange topicExchange(){
        return new TopicExchange("topicExchange");
    }

    //使用两个链路,绑定交换机与队列,并设置路由key
    @Bean
    Binding firstBinding(){
        return BindingBuilder.bind(firstQueue()).to(topicExchange()).with(man);
    }

    @Bean
    Binding secondBinding(){
        return BindingBuilder.bind(secondQueue()).to(topicExchange()).with("topic.#");
    }

(2)生产者

这里有两个生产者,topic1发出的消息只能被一种路径接收

    @RequestMapping(value = "/topic1" ,method = RequestMethod.GET)
    public String sendTopicMessage1(String msg){
        //设置一个随机数的id
        String messageId = String.valueOf(UUID.randomUUID());
        //设置时间
        String createTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        Map<String, Object> manMap = new HashMap<>();
        manMap.put("messageId", messageId);
        manMap.put("messageData", msg);
        manMap.put("createTime", createTime);
        //发送消息
        rabbitTemplate.convertAndSend("topicExchange", "topic.man", manMap);
        return "ok1";
        
    }

    @RequestMapping(value = "/topic2" ,method = RequestMethod.GET)
    public String sendTopicMessage2(String msg){
        //设置一个随机数的id
        String messageId = String.valueOf(UUID.randomUUID());
        //设置时间
        String createTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        Map<String, Object> womanMap = new HashMap<>();
        womanMap.put("messageId", messageId);
        womanMap.put("messageData", msg);
        womanMap.put("createTime", createTime);
        //发送消息
        rabbitTemplate.convertAndSend("topicExchange", "topic.woman", womanMap);
        return "ok2";
        
    }

(3)消费者

以路由topic.#推送出去的消息,两个路由都能接收到消息

@Component
public class TopicManReceiver {

    @RabbitHandler
    @RabbitListener(queues = "topic.man")
    public void receive1(Map textMessage){
        System.out.println("topic  man收到消息: "+textMessage.toString());
    }

    @RabbitHandler
    @RabbitListener(queues = "topic.woman")
    public void receive2(Map message){
        System.out.println("topic  woman收到消息: "+message.toString());
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值