springboot-rabbitmq-reply 消息直接回复模式详情

 更新时间:2022年09月20日 16:57:36   作者:保护我方胖虎  
这篇文章主要介绍了springboot-rabbitmq-reply消息直接回复模式详情,文章通过围绕主题展开详细的内容介绍,具有一定的参考价值,感兴趣的小伙伴可以参考一下

一、使用场景

MQ的作用包括了解耦、异步等。

通常生产者只负责生产消息,而不关心消息谁去获取,或者消费结果如何;消费者只负责接收指定的消息进行业务处理而不关心消息从哪里来一级回复业务处理情况。但我们项目中有特殊的业务存在,我们作为消息生产者在生产消息后需要接收消费者的响应结果(说白了就是类似同步调用 请求响应的MQ使用),经过研究,MQ的Reply模式(直接回复模式)就是为此种业务模式而产生。

二、Reply实战

(1)依赖与YML配置

依赖:

我这里只列出最核心的rabbitMq所需依赖

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

配置:

无其余特殊配置,因为reply就是rabbitmq的一种交互方式而已

spring:
  rabbitmq:
    host: 10.50.40.116
    port: 5673
    username: admin
    password: admin

(2)RabbitMq bean配置

package com.leilei.demo;

import org.springframework.amqp.core.FanoutExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
 * @author lei
 * @create 2022-09-19 21:44
 * @desc mq配置
 **/
@Configuration
public class RabbitMqConfig {
    @Bean
    public Queue bizQueue() {
        return new Queue("bizQueue");
    }
    @Bean
    public Queue replyQueue() {
        return new Queue("replyQueue");
    }
    @Bean
    FanoutExchange bizExchange() {
        return new FanoutExchange("bizExchange");
    }
}

业务类:

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Vehicle implements Serializable {
    private Integer id;
    private String name;
}

(3)消息生产端

消息生产端需要做的事情:有生产消息、接受消息消费响应

(1)生产消息

  • 1、生产消息,看业务场景选择是否生成全局唯一自定义的消息ID
  • 2、指定消息消费后响应的队列(Reply)
    /**
     * 生产消息
     *
     * @param
     * @return void
     * @author lei
     * @date 2022-09-19 21:59:18
     */
    public void replySend() {
        MessageProperties messageProperties = new MessageProperties();
        messageProperties.setReplyTo("replyQueue");
        //todo 根据业务,做一个严谨的全局唯一ID,我这里暂时用UUID
        String correlationId = UUID.randomUUID().toString();
        // 我这里指定了唯一消息ID,看业务场景,消费者消费响应后,生产者端可根据消息ID做业务处理
        messageProperties.setCorrelationId(correlationId);
        Vehicle vehicle = new Vehicle(1, "川A0001");
        Message message = new Message(JSON.toJSONString(vehicle).getBytes(), messageProperties);
        rabbitTemplate.convertAndSend("bizExchange","",message);
        System.out.println("生产者发送消息,自定义消息ID为:" + correlationId);
    }

(2)接受Reply响应

消费者消费消息后会将处理结果进行发送到一个队列,我们读取这里队列就可以拿到对应消息的响应结果进行业务处理了

    /**
     * 接收消息响应
     *
     * @param message
     * @return void
     * @author lei
     * @date 2022-09-19 21:59:27
     */
    @RabbitListener(queues = "replyQueue")
    public void replyResponse(Message message) {
        String s = new String(message.getBody());
        String correlationId = message.getMessageProperties().getCorrelationId();
        System.out.println("收到客户端响应消息ID:" + correlationId);
        //todo 根据消息ID可判断这是哪一个消息的响应,我们就可做业务操作
        System.out.println("收到客户端响应消息:" + s);
    }

(4)消息消费端

消息消费端需要做的事有:接受消息然后进行业务处理、响应消息

(1)方法一:sendTo注解+方法返回值

一般来说,我们mq消费者监听方法不需要返回值,我们这里使用sendTo注解,则需要将要响应的消息定义为返回值,sendTo注解中指定要响应到哪个队列

重点:

  • 1、sendTo注解指定要相应的队列(注意和生产端保持一致)
  • 2、方法定义的返回值内容就是要响应的消息,最终会发送到sendTo注解指定要相应的队列
  • 3、这种方法的缺点是消费端的主关性很高,因为sendTo指定的目标队列可以自己瞎写,导致生产者端无法正确收到消息响应,但我相信一般项目中也不会这么干
    /**
     * 方式1   SendTo指定响应队列
     *
     * @param message
     * @return String
     * @author lei
     * @date 2022-09-19 16:17:52
     */
    @RabbitListener(queues ="bizQueue")
    @SendTo("replyQueue")
    public String handleEmailMessage(Message message) {
        try {
            String msg=new String(message.getBody(), StandardCharsets.UTF_8);
            log.info("---consumer接收到消息----{}",msg);
            return "客户端响应消息:"+msg+"处理完成!";
        } catch (Exception e) {
            log.error("处理业务消息失败",e);
        }
        return null;
    }

(2)方法二:读取生产端的消息使用模板发送

与普通的消费者方法一样,只需要RabbitListener注解监听业务队列;但还需要根据消息获取出ReplyTo地址,然后自己消费者方法内部手动发送消息

  • 1、优点,更强烈的感受到消息请求 响应的交互性,流程看起来更清晰
  • 2、缺点,代码不雅
    /**
     * 方式2  message消息获取内部reply rabbitmq手动发送
     *
     * @param message
     * @return String
     * @author lei
     * @date 2022-09-19 16:17:52
     */
    @RabbitListener(queues = "bizQueue")
    public void handleEmailMessage2(Message message) {
        try {
            String msg = new String(message.getBody(), StandardCharsets.UTF_8);
            log.info("---consumer接收到消息----{}", msg);
            String replyTo = message.getMessageProperties().getReplyTo();
            System.out.println("接收到的reply:" + replyTo);
            rabbitTemplate.convertAndSend(replyTo, "客户端响应消息:" + msg + "处理完成!", x -> {
                x.getMessageProperties().setCorrelationId(message.getMessageProperties().getCorrelationId());
                return x;
            });
        } catch (Exception e) {
            log.error("处理业务消息失败",e);
        }
    }

(3)方法三:方法返回值

这种方式与1其实是一致的,但我经过测试,因为生产者消息指定了ReplyTo的地址,消费者端无需自己再次手动指定,即生产消息到哪里,是否响应以及响应消息发送到哪里全由生产端自己空,消费者只需要处理自身业务以及返回结果

   /**
     * 方式三  方法有返回值,返回要响应的数据 (reply 由生产者发送消息时指定,消费者不做任何处理)
     *
     * @param message
     * @return String
     * @author lei
     * @date 2022-09-19 23:17:47
     */
    @RabbitListener(queues ="bizQueue")
    public String handleEmailMessage3(Message message) {
        try {
            String msg=new String(message.getBody(), StandardCharsets.UTF_8);
            log.info("---consumer接收到消息----{}",msg);
            return "客户端响应消息:"+msg+"处理完成!";
        }
        catch (Exception e) {
            log.error("处理业务消息失败",e);
        }
        return null;
    }

(4)测试

生产消息:

消费消息与响应:

收到的响应:

链路:

如此,MQ版本的请求响应模式就完成了,其实很多大佬使用MQ来实现RPC就是用的ReplyTo啦!

到此这篇关于springboot-rabbitmq-reply 消息直接回复模式详情的文章就介绍到这了,更多相关springboot-rabbitmq-reply 内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 使用Backoff策略提高HttpClient连接管理的效率

    使用Backoff策略提高HttpClient连接管理的效率

    这篇文章主要为大家介绍了Backoff策略提高HttpClient连接管理的效率使用解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-10-10
  • 如何解决@NotBlank不生效的问题

    如何解决@NotBlank不生效的问题

    这篇文章主要介绍了如何解决@NotBlank不生效的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-06-06
  • Java Spring中Quartz调度器详解及实例

    Java Spring中Quartz调度器详解及实例

    这篇文章主要介绍了Java Spring中Quartz调度器详解及实例的相关资料,需要的朋友可以参考下
    2017-02-02
  • 详解Java的面向对象和面向过程

    详解Java的面向对象和面向过程

    我们知道,Java是面向对象的编程语言,但是至今仍有不少同学还不太懂”面向对象“的确切含义,今天这篇文章就带大家真正地认识面向对象,感兴趣的同学可以跟着小编一起来学习
    2023-05-05
  • SpringBoot配置文件密码加密与解密的操作代码

    SpringBoot配置文件密码加密与解密的操作代码

    我们在SpringBoot项目当中,会把数据库的用户名密码等配置直接放在yaml或者properties文件中,这样维护数据库的密码等敏感信息显然是有一定风险的,所以我们需要给密码加解密,本文给大家介绍了SpringBoot配置文件密码加密与解密的操作代码,需要的朋友可以参考下
    2024-12-12
  • Springboot 使用 JSR 303 对 Controller 控制层校验及 Service 服务层 AOP 校验 使用消息资源文件对消息国际化

    Springboot 使用 JSR 303 对 Controller 控制层校验及 Service 服务层 AOP 校验

    这篇文章主要介绍了Springboot 使用 JSR 303 对 Controller 控制层校验及 Service 服务层 AOP 校验 使用消息资源文件对消息国际化的相关知识,需要的朋友可以参考下
    2017-12-12
  • 详解Java如何实现基于Redis的分布式锁

    详解Java如何实现基于Redis的分布式锁

    在不同进程需要互斥地访问共享资源时,分布式锁是一种非常有用的技术手段。这篇文章运用图文和实例代码介绍了Java如何实现基于Redis的分布式锁,文章介绍的很详细,对Java和Redis刚兴趣的朋友们可以参考借鉴,下面来一起看看。
    2016-08-08
  • SpringCloud-Hystrix组件使用方法

    SpringCloud-Hystrix组件使用方法

    这篇文章主要介绍了SpringCloud-Hystrix组件使用方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-12-12
  • Java数据结构之图的基础概念和数据模型详解

    Java数据结构之图的基础概念和数据模型详解

    在现实生活中,有许多应用场景会包含很多点以及点点之间的连接,而这些应用场景我们都可以用即将要学习的图这种数据结构去解决。本文主要介绍了图的基础概念和数据模型,感兴趣的可以了解一下
    2022-11-11
  • 解决SpringBoot请求返回字符串中文乱码的问题

    解决SpringBoot请求返回字符串中文乱码的问题

    这篇文章主要介绍了解决SpringBoot请求返回字符串中文乱码的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-05-05

最新评论