RabbitMQ基础用法

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

 RabbitMQ基础用法


简介

Rabbitmq是实现了一个 AMQP(Advanced Message Queuing Protocol)高级消息队列协议的消息队列服务,是面向消息的中间件

四大概念

生产者:负责产生数据
交换机:接收来自生产者的消息,并将消息推送到队列中。决定消息是要推送给特定队列,还是推送给多个队列,还是丢弃。
队列:存储消息。
消费者:接收消息。

简单些,可以想象成购物,在购物平台下单后,快递员会把包裹送到你的收件人地址处。

一、主要流程

生产者(Producer)与消费者(Consumer)和 RabbitMQ 服务(Broker)建立连接, 然后生产者发布消息(Message)同时需要携带交换机(Exchange) 名称以及路由规则(Routing Key),这样消息会到达指定的交换机,然后交换机根据路由规则匹配对应的 Binding,最终将消息发送到匹配的消息队列(Quene),最后 RabbitMQ 服务将队列中的消息投递给订阅了该队列的消费者(消费者也可以主动拉取消息)。

二、RabbitTemplate的使用步骤

1.引入库

pom.xml中引入依赖:

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

2.声明队列

代码如下(示例):

/**
 * description
 * 客户创建审批/客户属性修改审批队列
 *
 * @author zzq 2023/07/14 15:07
 */
public interface CstQueueDefinition {
    //客户创建工作流执行,同步代办到iflow
    String IFLOW_CST_PROCESS_QUEUE = "iflowCstProcessQueue";
    //客户创建工作流终止,终止iflow代办
    String IFLOW_CST_END_QUEUE = "iflowCstEndQueue";
    //客户创建工作流转交和加签
    String IFLOW_CST_ON_DELEGATE_AND_ADD_SIGN_QUEUE = "iflowCstOnDelegateAndAddSign";
    //客户创建工作流发邮件
    String APPROVE_CST_EMAIL_QUEUE = "approveCstEmailQueue";

    //客户属性修改工作流执行,同步代办到iflow
    String IFLOW_CST_UPDATE_PROCESS_QUEUE = "iflowCstUpdateProcessQueue";
}

3.RabbitConfig配置队列、交换器

package com.h3c.pms.customer.config;

import com.h3c.pms.starter.core.config.CstQueueDefinition;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

@Component
public class RabbitConfig {

    /**
     /**
     * Queue(String name, boolean durable, boolean exclusive, boolean 
     * autoDelete,Map<String, Object> arguments)
     * 1、name:名称;
     * 2、durable:持久性,是否持久化至硬盘(若要使队列中消息不丢失,
     *    同时也需要将消息声明为持久化);
     * 3、exclusive:是否声明该队列是否为连接(connection)独占,若为独占,
     *    连接关闭后队列即被删除;
     * 4、autoDelete:自动删除,若没有消费者订阅该队列,队列将被删除;
     * 5、arguments:其他参数
     * 客户创建工作流审批通过/审批拒绝
     */
    @Bean
    public Queue iflowCstProcessQueue() {
        return new Queue(CstQueueDefinition.IFLOW_CST_PROCESS_QUEUE, true, false, false);
    }

    /**
     * 客户创建审批终止
     */
    @Bean
    public Queue iflowCstEndQueue() {
        return new Queue(CstQueueDefinition.IFLOW_CST_END_QUEUE, true, false, false);
    }

    /**
     * 客户创建转交、加签
     */
    @Bean
    public Queue iflowCstOnDelegateAndAddSign() {
        return new Queue(CstQueueDefinition.IFLOW_CST_ON_DELEGATE_AND_ADD_SIGN_QUEUE, true, false, false);
    }

    /**
     * 客户创建工作流发邮件
     */
    @Bean
    public Queue approveCstEmailQueue() {
        return new Queue(CstQueueDefinition.APPROVE_CST_EMAIL_QUEUE, true, false, false);
    }

    /**
     * 客户属性修改工作流审批通过/审批拒绝
     */
    @Bean
    public Queue iflowCstUpdateProcessQueue() {
        return new Queue(CstQueueDefinition.IFLOW_CST_UPDATE_PROCESS_QUEUE, true, false, false);
    }
}

4.生产者(Producer)

import org.springframework.amqp.rabbit.core.RabbitTemplate;

@Service
@Slf4j
public class ActWorkflowServiceImpl implements ActWorkflowService {

    @Autowired
    private RabbitTemplate rabbitTemplate;

 /**
     * 审批动作后,发iflow和email
     * 当前操作人工号
     * 当前审批任务信息
     * 当前审批用户操作信息(前端传的)
     */
    @Override
    public void executeAfterActivitiExecuteTaskAction(String employeeCode,      ActProcTaskInfo task, TaskActionRequestExt actionRequest){

        //虚拟工作流
        String businessKey = task.getBusinessKey();
        if(businessKey.endsWith("-Y")){
           return;
        }

        String action = actionRequest.getAction();
        //加签
        if("AddSign".equalsIgnoreCase(action) || "ApproveAndAddSign".equalsIgnoreCase(action)){
            ActDelegateORAddSignInfo actDelegateORAddSignInfo = new ActDelegateORAddSignInfo();
            BeanUtils.copyProperties(task, actDelegateORAddSignInfo);
            actDelegateORAddSignInfo.setEmployeeNums(actionRequest.getAssignList());
            String jsonMsg = JSON.toJSONString(actDelegateORAddSignInfo);
            if(businessKey.startsWith("ADV-")) {
                rabbitTemplate.convertAndSend(AdvQueueDefinition.IFLOW_ADV_ON_DELEGATE_AND_ADD_SIGN_QUEUE, jsonMsg);
            } else if(businessKey.startsWith("ORDER-")) {
                rabbitTemplate.convertAndSend(OrderQueueDefinition.IFLOW_ORDER_ON_DELEGATE_AND_ADD_SIGN_QUEUE, jsonMsg);
            } else if(businessKey.startsWith("LOAN-")){
                log.info("借货工作流加签操作队列推送:{},值:{}",LoanQueueDefinition.IFLOW_LOAN_ON_DELEGATE_AND_ADD_SIGN_QUEUE,jsonMsg);
                rabbitTemplate.convertAndSend(LoanQueueDefinition.IFLOW_LOAN_ON_DELEGATE_AND_ADD_SIGN_QUEUE, jsonMsg);
            }else if(businessKey.startsWith("CST-")){
                log.info("客户创建审批流加签操作队列推送:{},值:{}", CstQueueDefinition.IFLOW_CST_ON_DELEGATE_AND_ADD_SIGN_QUEUE,jsonMsg);
                rabbitTemplate.convertAndSend(CstQueueDefinition.IFLOW_CST_ON_DELEGATE_AND_ADD_SIGN_QUEUE, jsonMsg);
            }
            return;
        }
        //转交
        if("delegate".equalsIgnoreCase(action)){
            ActDelegateORAddSignInfo actDelegateORAddSignInfo = new ActDelegateORAddSignInfo();
            BeanUtils.copyProperties(task, actDelegateORAddSignInfo);
            actDelegateORAddSignInfo.setEmployeeNums(Arrays.asList(actionRequest.getAssignee()));
            String jsonMsg = JSON.toJSONString(actDelegateORAddSignInfo);
            if(businessKey.startsWith("ADV-")) {
                rabbitTemplate.convertAndSend(AdvQueueDefinition.IFLOW_ADV_ON_DELEGATE_AND_ADD_SIGN_QUEUE, jsonMsg);
            } else if(businessKey.startsWith("ORDER-")) {
                rabbitTemplate.convertAndSend(OrderQueueDefinition.IFLOW_ORDER_ON_DELEGATE_AND_ADD_SIGN_QUEUE, jsonMsg);
            }else if(businessKey.startsWith("LOAN-")){
                log.info("借货工作流delegate转交操作队列推送:{},值:{}",LoanQueueDefinition.IFLOW_LOAN_ON_DELEGATE_AND_ADD_SIGN_QUEUE,jsonMsg);
                rabbitTemplate.convertAndSend(LoanQueueDefinition.IFLOW_LOAN_ON_DELEGATE_AND_ADD_SIGN_QUEUE, jsonMsg);
            }
            return;
        }
        //审批
        if("complete".equalsIgnoreCase(action)){
            List<org.activiti.rest.service.api.engine.variable.RestVariable> variables = actionRequest.getVariables();
            String approveResult = "";
            if (CollectionUtils.isNotEmpty(variables)) {
                approveResult =  (String) variables.stream().filter(v->"approveResult".equalsIgnoreCase(v.getName()))
                        .map(v->v.getValue()).findFirst().orElse("");
            }
            if("Rejected".equalsIgnoreCase(approveResult)){
                /**
                 * 拒绝时终止掉流程(正常情况下会终止,但是存在并行网关时不会终止,要手动终止)
                 * 一开始是chenliang写的,感觉就是hzero activiti源码有bug
                 * 我不太懂,但是大受震撼~ 然后转手给他抄到了我这里~
                 */
                int actTaskCount = workflowMapper.selectCountRuTask(task.getProcInstId());
                int actProcessCount = workflowMapper.selectCountNullEndTime(task.getProcInstId());
                if(actTaskCount > 0 || actProcessCount > 0) {
                    try{
                        activitiService.deleteProcessInstance(task.getProcInstId());
                    } catch (Exception e){
                        log.error("出错啦:", e);
                    }
                }
            }
            if("Approved".equalsIgnoreCase(approveResult) || "Rejected".equalsIgnoreCase(approveResult)){
                if(businessKey.startsWith("ADV-")) {
                    rabbitTemplate.convertAndSend(AdvQueueDefinition.IFLOW_ADV_PROCESS_QUEUE, businessKey);

                } else if(businessKey.startsWith("ORDER-")) {
                    rabbitTemplate.convertAndSend(OrderQueueDefinition.IFLOW_ORDER_PROCESS_QUEUE, businessKey);
                    String isSendEmail = LovValueHelper.getMeaningOf("H3CSYS.SYSTEM_IS_SEND_MAIL","is_send",lovAdapter);
                    if("1".equals(isSendEmail)) {
                        //报单这里有一个发邮件功能,总之先保留吧...
                        ActSendEmailMsg emailMsg = new ActSendEmailMsg();
                        emailMsg.setTaskId(task.getTaskId());
                        emailMsg.setProcInstId(task.getProcInstId());
                        emailMsg.setBusinessKey(task.getBusinessKey());
                        emailMsg.setTaskApproveResult(action);
                        emailMsg.setComment(actionRequest.getComment());
                        String jsonMsg = JSON.toJSONString(emailMsg);
                        rabbitTemplate.convertAndSend(OrderQueueDefinition.APPROVE_ORDER_EMAIL_QUEUE, jsonMsg);
                    }
                }else if(businessKey.startsWith("LOAN-")){
                    log.info("借货工作流complete操作队列推送:{},值:{}",LoanQueueDefinition.IFLOW_LOAN_PROCESS_QUEUE,businessKey);
                    rabbitTemplate.convertAndSend(LoanQueueDefinition.IFLOW_LOAN_PROCESS_QUEUE, businessKey);
                }else if(businessKey.startsWith("CST-")){
                    log.info("客户创建工作流complete操作队列推送:{},值:{}",CstQueueDefinition.IFLOW_CST_PROCESS_QUEUE,businessKey);
                    rabbitTemplate.convertAndSend(CstQueueDefinition.IFLOW_CST_PROCESS_QUEUE, businessKey);
                }else if(businessKey.startsWith("CST_UPDATE-")){
                    log.info("客户属性修改工作流complete操作队列推送:{},值:{}",CstQueueDefinition.IFLOW_CST_UPDATE_PROCESS_QUEUE,businessKey);
                    rabbitTemplate.convertAndSend(CstQueueDefinition.IFLOW_CST_UPDATE_PROCESS_QUEUE, businessKey);
                }
            }
            return;
        }
    }
}

5.消费者(Consumer)

package com.h3c.pms.customer.app.task;

import com.h3c.pms.customer.app.service.CstIflowService;
import com.h3c.pms.starter.core.config.CstQueueDefinition;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
@Slf4j
public class IflowCstProcessConsumer {
    @Autowired
    private CstIflowService cstIflowService;

    @RabbitListener(queues = {CstQueueDefinition.IFLOW_CST_PROCESS_QUEUE})
    public void consumeMessage(String businessKey, Channel channel, Message message){
        try{
            System.out.println("客户新建开始消费");
            cstIflowService.iflowCstProcessQueue(businessKey);
        }catch (Exception e){
            //@TODO 可以记个日志
            log.error("出错啦:", e);
        }
    }
}

总结

(1)异步处理:将一些不重要的信息,适用MQ进行异步处理,较少主流程的响应时间;

(2)解耦:使用MQ转发消息,可使得服务间不再相互依赖,达到解耦的目的,提高系统灵活性,扩展性;

(3)消峰:使用MQ队列,避免高并发压垮系统、数据库、系统等,提高系统响应速度、吞吐量等;

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
RabbitMQ是一个使用Erlang实现的高并发高可靠AMQP消息队列服务器。它支持消息的持久化、事务、拥塞控制、负载均衡等特性,使得RabbitMQ在各种应用场景下被广泛使用。RabbitMQ与Erlang和AMQP密切相关。 Erlang是一种编程语言,它特别适合构建高并发、分布式、实时的系统。RabbitMQ使用Erlang作为其底层开发语言,这使得它能够充分利用Erlang在并发处理和容错性方面的优势。 AMQP(Advanced Message Queuing Protocol)是一个开放标准的消息队列协议,用于在应用程序之间进行可靠的消息传递。RabbitMQ实现了AMQP协议,这意味着它可以与其他遵循AMQP协议的应用程序进行通信,实现可靠的消息传递机制。 要使用RabbitMQ,可以通过Docker安装,使用以下命令运行一个带有管理界面的RabbitMQ容器: ``` docker run -itd --rm --name rabbitmq -p 5672:5672 -p 15672:15672 rabbitmq:3-management ``` 在编写RabbitMQ程序时,可以利用其支持的多种消息模型,例如发布-订阅模型、工作队列模型、路由模型等,根据具体需求选择合适的模型来实现消息传递。 在配置RabbitMQ环境时,可以设置RABBITMQ_SERVER环境变量,并将RabbitMQ的安装路径添加到系统的path变量中,以方便在命令行中直接使用RabbitMQ命令。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [RabbitMQ使用详解](https://blog.csdn.net/qq_43410878/article/details/123656765)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值