Spring Boot 实践之十一 Spring Boot消息服务(RabbitMQ消息中间件/Spring Boot与RbbitMQ整合实现)

注:实践内容参考人民邮电出版社的教程《 Spring Boot企业级开发教程》作者:黑马程序员,上传本文仅以实践过程以供大家共同学习解决问题,如有侵权不当行为,请告知后,我会更正或删除。

1 消息服务概述

1.1 为什么 要使用消息服务

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
1592295685263.png
在这里插入图片描述
在这里插入图片描述

1.2 常用消息中间件介绍

在这里插入图片描述

2 RabbitMQ消息中间件

2.1 RabbitMQ简介

在这里插入图片描述

2.2 RabbitMQ工作模式介绍

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3 RabbitMQ安装以及整合环境搭建

3.1 安装RabbitMQ

在这里插入图片描述
在这里插入图片描述

2.RabbitMQ安装

  • (1)安装Erlang语言包,这里演示电脑为64位,安装的是otp_win64_21.2.exe

在这里插入图片描述

安装过程提示的运行组件也请一并安装
在这里插入图片描述

  • (2)成功安装语言包后安装Rabbitmq,这里演示安装的是rabbitmq-server-3.7.9.exe

在这里插入图片描述

  • (3)配置环境变量

    安装完RabbitMQ后,系统环境变量会自动增加一个变量名为ERLANG——HOME的变量配置,配置路径是Erlang选择安装的具体路径,无需修改。如图:
    1592379747518.png

    选择用户变量path,添加ERLANG_HOME环境变量,如图:
    在这里插入图片描述

    3.RabbitMQ可视化效果展示

    • 运行安装后开始菜单下的RabbitMQ Server的RabbitMQ Comand Prompt,输入 rabbitmqctl status ,如图,说明安装成功。
      在这里插入图片描述

    • 输入命令rabbitmq-plugins enable rabbitmq_management,这样就可以添加可视化插件了
      在这里插入图片描述
      在这里插入图片描述

    3.2 Spring Boot整合RabbitMQ环境搭配
  • (1)使用Spring Initializr方式创建项目,选择Web依赖和RabbitMQ依赖,如图:
    在这里插入图片描述

  • (2)在全局配置文件添加RabbitMQ消息中间件的连接配置

    # 配置RabbitMQ消息中间件连接配置 
    spring.rabbitmq.host=localhost
    spring.rabbitmq.port=5672
    spring.rabbitmq.username=guest
    spring.rabbitmq.password=guest
    #配置RabbitMQ虚拟主机路径/,默认可以省略
    spring.rabbitmq.virtual-host=/
    

4 Spring Boot与RabbitMQ整合实现

Spring Boot对RabbitMQ的6种工作模式都进行了非常好的整合实现,并集成了多种方式的整合支持,包括基于API的方式、基于配置类的方式、基于注解的方式。下面,选取常用的三种工作模式完成在Spring Boot项目中的消息服务整合实现。

4.1 Publish/Subscribe(发布订阅模式)

Spring Boot整合RabbitMQ中间件实现消息服务,主要围绕三个部分的工作进行展开:定制中间件、消息发送者发送消息、消息消费者接收消息 。下面,以用户注册成功后同时发送邮件通知和短信通知这一场景为例,分别使用基于API,基于配置类和基于注解这三种方式实现Publish/Subscribe工作模式的整合。

1.基于API的方式
在这里插入图片描述

  • 1)使用AmqpAdmin定制消息发送组件

    • 在项目的测试类Chapter08ApplicationTests.java中引入AmqpAdmin管理类定制Publish/Subscribe工作模式所需的消息组件,内容如下:

      @Autowired
      private AmqpAdmin amqpAdmin;
       //使用AmqpAdmin管理员API定制消息组件
      @Test
      public void amqpAdmin() {
          // 1、定义fanout类型的交换器
          amqpAdmin.declareExchange(new FanoutExchange("fanout_exchange"));
          // 2、定义两个默认持久化队列,分别处理email和sms
          amqpAdmin.declareQueue(new Queue("fanout_queue_email"));//注意对Queue正确导包
          amqpAdmin.declareQueue(new Queue("fanout_queue_sms"));
          // 3、将队列分别与交换器进行绑定
          amqpAdmin.declareBinding(new Binding("fanout_queue_email", Binding.DestinationType.QUEUE,"fanout_exchange","",null));
          amqpAdmin.declareBinding(new Binding("fanout_queue_sms",Binding.DestinationType.QUEUE,"fanout_exchange","",null));
      }
      
    • 执行测试类amqpAdmin(),可看到效果
      在这里插入图片描述

    • 点击RabbitMQ中的fanout_exchange,可以查看到两个默认持久化队列
      在这里插入图片描述

    • 点击队列Queues,可以查看消息信息发送和接收情况,如图:
      在这里插入图片描述

  • 2)消息发送者发送消息

    完成消息组件的定制工作后,创建消息发送者发送消息到消息队列中,在进行发送消息时,将会定制一个实体类进行消息传送,需要预先创建一个实体类对象。

    • 在项目中创建domain包,并在该包下创建一个实体类User,User.java内容如图:
      在这里插入图片描述

    • 在项目测试类中添加Spring框架提供的RabbitTemplate模板类实现消息发送,代码如下:

      @Autowired
      private RabbitTemplate rabbitTemplate;
      
       //Publish/Subscribe工作模式消息发送端
      @Test
      public void psubPublisher() {
          User user=new User();//注意对User对象进行正确导包为自定义的User实体类
          user.setId(1);
          user.setUsername("石头");
          //RabbitTemplate模板类实现消息发送,第1个参数为交换器,第二个参数为路由键,使用Publish/Subscribe工作模式可以为空,第三个参数为发送的消息内容,接收Object类型
          rabbitTemplate.convertAndSend("fanout_exchange","",user);
      }
      

在这里插入图片描述在这里插入图片描述

  • 在项目com.itheima下中创建config包,并在该包下创建一个RabbitMQ消息配置类RabbitMQConfig,实现JSON格式消息转换器替换默认转换器,内容如下:

    package com.itheima.config;
    
    import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
    import org.springframework.amqp.support.converter.MessageConverter;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class RabbitMQConfig {
        //定制JSON格式的消息转换器
        @Bean //把返回值存到容器供使用
        public MessageConverter messageConverter(){
            return new Jackson2JsonMessageConverter();
        }
    }
    
  • 再运行测试方法 psubPublisher(),进行消息的发布,执行成功后刷新http://localhost:15672/#/queues,效果如图:
    在这里插入图片描述
    可以看到Ready为1,消息发布成功并暂存在队列中。

  • 3)消息接收者接收消息

    • 在项目com.itheima下创建包service,在包下创建一个针对对RabbitMQ消息中间件进行消息接收和处理的业务类RabbitMQService.java,内容如下:

      package com.itheima.service;
      
      import org.springframework.amqp.core.Message;
      import org.springframework.amqp.rabbit.annotation.RabbitListener;
      import org.springframework.stereotype.Service;
      
      @Service
      public class RabbitMQService {
      
      //     * Publish/Subscribe工作模式接收,处理邮件业务
          @RabbitListener(queues = "fanout_queue_email")//监听"fanout_queue_email"的消息
          public void psubConsumerEmail(Message message) {//Message导入含amqp的包
              byte[] body = message.getBody();
              String s = new String(body);
              System.out.println("邮件业务接收到消息: "+s);
      
          }
      
      //     Publish/Subscribe工作模式接收,处理短信业务
      
          @RabbitListener(queues = "fanout_queue_sms") //监听"fanout_queue_sms"的消息
          public void psubConsumerSms(Message message) {
              byte[] body = message.getBody();
              String s = new String(body);
              System.out.println("短信业务接收到消息: "+s);
          }
      }
      
    • 启动项目核心引导类,运行效果如图:
      在这里插入图片描述

      可以看到,控制台输出了监听到的消息后的处理。并通过RabbitMQ可视化管理页面的Queues面板查看队列消息情况,会发现两个队列中存储的消息已经自动删除。如图:
      在这里插入图片描述

2.基于配置类的方式
在这里插入图片描述

package com.itheima.config;

import org.springframework.amqp.core.*;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class RabbitMQConfig {
    //定制JSON格式的消息转换器
    @Bean
    public MessageConverter messageConverter(){
        return new Jackson2JsonMessageConverter();
    }

    //使用基于配置类的方式定制消息中间件,流程与测试类中使用AmqpAdmin管理员API定制消息组件类同,
    //不同之处是一个通过测试类实现,一个通过配置类实现
    // 1、定义fanout类型的交换器
    @Bean
    public Exchange fanout_exchange(){//导入org.springframework.amqp.core.*;
        return ExchangeBuilder.fanoutExchange("fanout_exchange").build();
    }
    // 2、定义两个不同名称的消息队列
    @Bean
    public Queue fanout_queue_email(){
        return new Queue("fanout_queue_email");
    }
    @Bean
    public Queue fanout_queue_sms(){
        return new Queue("fanout_queue_sms");
    }
    // 3、将两个不同名称的消息队列与交换器进行绑定
    @Bean
    public Binding bindingEmail(){
        return BindingBuilder.bind(fanout_queue_email()).to(fanout_exchange()).with("").noargs();
    }
    @Bean
    public Binding bindingSms(){
        return BindingBuilder.bind(fanout_queue_sms()).to(fanout_exchange()).with("").noargs();
    }
}

注释Chapter08ApplicationTests.java中的使用AmqpAdmin管理员API定制消息组件部分的代码,运行psubPublisher(),两者测试效果相同,消息消费者可以自动监听并消费消息队列中存在的消息。
在这里插入图片描述

3.基于注解的方式
在这里插入图片描述

package com.itheima.service;

import com.itheima.domain.User;
import org.springframework.amqp.core.Message;
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.Service;

@Service
public class RabbitMQService {

/*//     * Publish/Subscribe工作模式接收,处理邮件业务
    @RabbitListener(queues = "fanout_queue_email")//监听"fanout_queue_email"的消息
    public void psubConsumerEmail(Message message) {//Message导入含amqp的包
        byte[] body = message.getBody();
        String s = new String(body);
        System.out.println("邮件业务接收到消息: "+s);

    }

//     Publish/Subscribe工作模式接收,处理短信业务

    @RabbitListener(queues = "fanout_queue_sms") //监听"fanout_queue_sms"的消息
    public void psubConsumerSms(Message message) {
        byte[] body = message.getBody();
        String s = new String(body);
        System.out.println("短信业务接收到消息: "+s);
    }*/

    //1.1、Publish/Subscribe工作模式接收,处理邮件业务
    @RabbitListener(bindings =@QueueBinding(value =@Queue("fanout_queue_email"), exchange =@Exchange(value = "fanout_exchange",type = "fanout")))
    public void psubConsumerEmailAno(User user) {
        System.out.println("邮件业务接收到消息: "+user);
    }
   //1.2、Publish/Subscribe工作模式接收,处理短信业务
    @RabbitListener(bindings =@QueueBinding(value =@Queue("fanout_queue_sms"),exchange =@Exchange(value = "fanout_exchange",type = "fanout")))
    public void psubConsumerSmsAno(User user) {
        System.out.println("短信业务接收到消息: "+user);
    }
}

在这里插入图片描述

4.2 Routing路由模式

这里,我们以不同级别日志信息采集处理这一场景为例,使用基于注解的方式来实现Routing路由模式的整合讲解。

  • 1)使用基于注解的方式定制消息组件和消息消费者

    • 打开进行消息接收和处理的业务类RabbitService,注释掉之前Publish/Subscribe工作模式。

    • 在该类中使用@RabbitListener注解及其相关属性定制Routing路由模式的消息组件,代码如下:

      //2.1、路由模式消息接收,处理error级别日志信息
      @RabbitListener(bindings =@QueueBinding(value =@Queue("routing_queue_error"),exchange =@Exchange(value = "routing_exchange",type = "direct"),key = "error_routing_key"))
      public void routingConsumerError(String message) {
          System.out.println("接收到error级别日志消息: "+message);
      }
      //2.2、路由模式消息接收,处理info、error、warning级别日志信息
      
      @RabbitListener(bindings =@QueueBinding(value =@Queue("routing_queue_all"),exchange =@Exchange(value = "routing_exchange",type = "direct"),key = {"error_routing_key","info_routing_key","warning_routing_key"}))
      public void routingConsumerAll(String message) {
          System.out.println("接收到info、error、warning等级别日志消息: "+message);
      }
      

在这里插入图片描述

  • 2)消息发送者发送消息

    打开测试类,添加Routing工作模式消息发送端,代码如下:

        //2、Routing工作模式消息发送端
        @Test
        public void routingPublisher() {
            rabbitTemplate.convertAndSend("routing_exchange","error_routing_key","routing send  error message");
            //参数说明:"routing_exchange":交换器名称;"error_routing_key":当前消息的日志级别error级别;"routing send  error message":具体要发送的消息
        }
    
  • 3)运行测试类中的routingPublisher(),效果如图:
    在这里插入图片描述

    查看浏览器端,交换器(Exchanges)多了routing_exchange,如图:
    在这里插入图片描述

    Queues也多了routing_queue_all和routing_queue_error,如图:
    在这里插入图片描述

4.3 Topic(通配符模式)

以不同用户对邮件和短信的订阅需求这一场景为例,使用使用基于注解的方式来实现Topic(通配符模式)的整合讲解。

  • 1)使用基于注解的方式定制消息组件和消息消费者

    • 打开进行消息接收和处理的业务类RabbitService,在该类中使用@RabbitListener注解及其相关属性定制Topics路由模式的消息组件,代码如下:

      //3.1、通配符模式消息接收,进行邮件业务订阅处理
      @RabbitListener(bindings =@QueueBinding(value =@Queue("topic_queue_email"),exchange =@Exchange(value = "topic_exchange",type = "topic"),key = "info.#.email.#"))
      public void topicConsumerEmail(String message) {
          System.out.println("接收到邮件订阅需求处理消息: "+message);
      }
      //3.2、通配符模式消息接收,进行短信业务订阅处理
      @RabbitListener(bindings =@QueueBinding(value =@Queue("topic_queue_sms"),exchange =@Exchange(value = "topic_exchange",type = "topic"),key = "info.#.sms.#"))
      public void topicConsumerSms(String message) {
          System.out.println("接收到短信订阅需求处理消息: "+message);
      }
      

在这里插入图片描述

  • 2)消息发送者发送消息

    在测试类中使用RabbitTemplate模板类实现Routing路由模式下的消息 发送,示例代码如下:

    @Test
        public void topicPublisher() {
            // 1、只发送邮件订阅用户消息
    //        rabbitTemplate.convertAndSend("topic_exchange","info.email","topics send  email message");
            // 2、只发送短信订阅用户消息
    //	    rabbitTemplate.convertAndSend("topic_exchange","info.sms","topics send  sms message");
            // 3、发送同时订阅邮件和短信的用户消息
    	    rabbitTemplate.convertAndSend("topic_exchange","info.email.sms","topics send  email and sms message");
        }
    
  • 3)这里提供了三种发送方式 ,我们可以一一测试,如这里使用第3种,发送同时订阅邮件和短信的用户消息 ,运行topicPublisher()效果如图:
    在这里插入图片描述

    浏览器查阅效果同样增加了相关Exchanges和queues,如图:
    在这里插入图片描述

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值