工作流引擎项目解析

API

img编辑

在Camunda中,API的继承关系主要体现在各个服务接口之间。以下是Camunda中一些常见服务接口的继承关系:

  1. ProcessEngineServices 接口:

    • RepositoryService: 负责管理流程定义和部署。

    • RuntimeService: 负责管理流程实例的执行。

    • TaskService: 负责管理流程任务。

    • IdentityService: 负责管理用户、组和身份验证。

    • HistoryService: 负责查询流程历史数据。

    • ManagementService: 提供引擎管理和维护的访问。

  2. ProcessEngine 接口:

    • 该接口是ProcessEngineServices接口的顶级接口,表示整个流程引擎的入口点,通过它可以获取各种服务接口的实例。

  3. RepositoryService 接口的继承关系:

    • RepositoryService

      • DeploymentQuery: 用于查询部署信息。

      • ProcessDefinitionQuery: 用于查询流程定义信息。

  4. RuntimeService 接口的继承关系:

    • RuntimeService

      • ExecutionQuery: 用于查询执行实例信息。

      • ProcessInstanceQuery: 用于查询流程实例信息。

      • VariableInstanceQuery: 用于查询流程变量实例信息。

  5. TaskService 接口的继承关系:

    • TaskService

      • TaskQuery: 用于查询任务信息。

  6. IdentityService 接口的继承关系:

    • IdentityService

      • UserQuery: 用于查询用户信息。

      • GroupQuery: 用于查询用户组信息。

  7. HistoryService 接口的继承关系:

    • HistoryService

      • HistoricProcessInstanceQuery: 用于查询历史流程实例信息。

      • HistoricTaskInstanceQuery: 用于查询历史任务实例信息。

这些继承关系有助于组织和理解Camunda引擎提供的各种服务接口,使开发人员能够更加方便地使用和管理工作流引擎。

案例

设计BPMN

插入模型

imgimg

img

编辑

API:repositoryService.newModel() 新建模型

    @Override
    public void insertModel(WfModelBo modelBo) {
        Model model = repositoryService.newModel();
        model.setName(modelBo.getModelName());
        model.setKey(modelBo.getModelKey());
        model.setCategory(modelBo.getCategory());
        String metaInfo = buildMetaInfo(new WfMetaInfoDto(), modelBo.getDescription());
        model.setMetaInfo(metaInfo);
        // 保存流程模型
        repositoryService.saveModel(model);
    }

思想学习:

将元数据封装到一个类中,流程创建者当前登录用户,判断内容是否为空然后设置最后转JSON

后续需要修改又反序列化-》修改信息-》序列化JSONUtils

    /**
     * 构建模型扩展信息
     * @return
     */
    private String buildMetaInfo(WfMetaInfoDto metaInfo, String description) {
        // 只有非空,才进行设置,避免更新时的覆盖
        if (StringUtils.isNotEmpty(description)) {
            metaInfo.setDescription(description);
        }
        if (StringUtils.isNotEmpty(metaInfo.getCreateUser())) {
            metaInfo.setCreateUser(LoginHelper.getUsername());
        }
        return JsonUtils.toJsonString(metaInfo);
    }

保存/更新BPMN内容

img

API:

repositoryService.getModel

repositoryService.saveModel(newModel)

repositoryService.addModelEditorSource(newModel.getId(), bpmnXmlBytes)

获取模型->XML2BPMN->BPMN获取流程名称和开始节点

思想学习:是否为新版本,更新流程版本

public void saveModel(WfModelBo modelBo) {
        // 查询模型信息
        Model model = repositoryService.getModel(modelBo.getModelId());
        if (ObjectUtil.isNull(model)) {
            throw new RuntimeException("流程模型不存在!");
        }
        BpmnModel bpmnModel = ModelUtils.getBpmnModel(modelBo.getBpmnXml());
        if (ObjectUtil.isEmpty(bpmnModel)) {
            throw new RuntimeException("获取模型设计失败!");
        }
        String processName = bpmnModel.getMainProcess().getName();
        // 获取开始节点
        StartEvent startEvent = ModelUtils.getStartEvent(bpmnModel);
        if (ObjectUtil.isNull(startEvent)) {
            throw new RuntimeException("开始节点不存在,请检查流程设计是否有误!");
        }
        // 获取开始节点配置的表单Key
       if (StrUtil.isBlank(startEvent.getFormKey())) {
           throw new RuntimeException("请配置流程表单");
       }
        Model newModel;
        if (Boolean.TRUE.equals(modelBo.getNewVersion())) {
            newModel = repositoryService.newModel();
            newModel.setName(processName);
            newModel.setKey(model.getKey());
            newModel.setCategory(model.getCategory());
            newModel.setMetaInfo(model.getMetaInfo());
            newModel.setVersion(model.getVersion() + 1);
        } else {
            newModel = model;
            // 设置流程名称
            newModel.setName(processName);
        }
        // 保存流程模型
        repositoryService.saveModel(newModel);
        // 保存 BPMN XML
        byte[] bpmnXmlBytes = StringUtils.getBytes(modelBo.getBpmnXml(), StandardCharsets.UTF_8);
        repositoryService.addModelEditorSource(newModel.getId(), bpmnXmlBytes);
    }

部署(进行流程定义)

API

repositoryService.createDeployment()

repositoryService.createProcessDefinitionQuery()

repositoryService.setProcessDefinitionCategory

核心学习:保存关联表单

img

获取流程名称-》获取BPMN-》部署-》创建流程定义并设计流程分类-》保存关联表单

    public boolean deployModel(String modelId) {
        // 获取流程模型
        Model model = repositoryService.getModel(modelId);
        if (ObjectUtil.isNull(model)) {
            throw new RuntimeException("流程模型不存在!");
        }
        // 获取流程图
        byte[] bpmnBytes = repositoryService.getModelEditorSource(modelId);
        if (ArrayUtil.isEmpty(bpmnBytes)) {
            throw new RuntimeException("请先设计流程图!");
        }
        String bpmnXml = StringUtils.toEncodedString(bpmnBytes, StandardCharsets.UTF_8);
        BpmnModel bpmnModel = ModelUtils.getBpmnModel(bpmnXml);
        String processName = model.getName() + ProcessConstants.SUFFIX;
        // 部署流程
        Deployment deployment = repositoryService.createDeployment()
            .name(model.getName())
            .key(model.getKey())
            .category(model.getCategory())
            .addBytes(processName, bpmnBytes)
            .deploy();
        ProcessDefinition procDef = repositoryService.createProcessDefinitionQuery()
            .deploymentId(deployment.getId())
            .singleResult();
        // 修改流程定义的分类,便于搜索流程
        repositoryService.setProcessDefinitionCategory(procDef.getId(), model.getCategory());
        // 保存部署表单
        return deployFormService.saveInternalDeployForm(deployment.getId(), bpmnModel);
    }

考虑子流程,回朔 

    public boolean saveInternalDeployForm(String deployId, BpmnModel bpmnModel) {
        List<WfDeployForm> deployFormList = new ArrayList<>();
        // 获取开始节点
        StartEvent startEvent = ModelUtils.getStartEvent(bpmnModel);
        if (ObjectUtil.isNull(startEvent)) {
            throw new RuntimeException("开始节点不存在,请检查流程设计是否有误!");
        }
        // 保存开始节点表单信息
        WfDeployForm startDeployForm = buildDeployForm(deployId, startEvent);
        if (ObjectUtil.isNotNull(startDeployForm)) {
//            System.out.println(startDeployForm.getFormKey());
            deployFormList.add(startDeployForm);
        }
        // 保存用户节点表单信息
        Collection<UserTask> userTasks = ModelUtils.getAllUserTaskEvent(bpmnModel);
        if (CollUtil.isNotEmpty(userTasks)) {
            for (UserTask userTask : userTasks) {
                WfDeployForm userTaskDeployForm = buildDeployForm(deployId, userTask);
                if (ObjectUtil.isNotNull(userTaskDeployForm)) {
//                    System.out.println(userTaskDeployForm.getFormKey());
                    deployFormList.add(userTaskDeployForm);
                }
            }
        }
        // 批量新增部署流程和表单关联信息
        return baseMapper.insertBatch(deployFormList);
    }
    
    /**
     * 构建部署表单关联信息对象
     * @param deployId 部署ID
     * @param node 节点信息
     * @return 部署表单关联对象。若无表单信息(formKey),则返回null
     */
    private WfDeployForm buildDeployForm(String deployId, FlowNode node) {
        String formKey = ModelUtils.getFormKey(node);
        if (StringUtils.isEmpty(formKey)) {
            return null;
        }
        Long formId = Convert.toLong(StringUtils.substringAfter(formKey, "key_"));
        //mybatisPlus还是不太懂,待学习
        WfForm wfForm = formMapper.selectById(formId);
        if (ObjectUtil.isNull(wfForm)) {
            throw new ServiceException("表单信息查询错误");
        }
        WfDeployForm deployForm = new WfDeployForm();
        deployForm.setDeployId(deployId);
        deployForm.setFormKey(formKey);
        deployForm.setNodeKey(node.getId());
        deployForm.setFormName(wfForm.getFormName());
        deployForm.setNodeName(node.getName());
        deployForm.setContent(wfForm.getContent());
        return deployForm;
    }

发起流程实例

获取关联表单,进行交互

API

repositoryService.getBpmnModel(definitionId):BpmnModel,通过流程定义获取BPMN(校验

historyService.createHistoricProcessInstanceQuery() .processInstanceId(procInsId),初次获取表单仍未产生流程实例,直接返回表单配置信息。

 historicProcIns.getProcessVariables()

    public FormConf selectFormContent(String definitionId, String deployId, String procInsId) {
        BpmnModel bpmnModel = repositoryService.getBpmnModel(definitionId);
        if (ObjectUtil.isNull(bpmnModel)) {
            throw new RuntimeException("获取流程设计失败!");
        }
        StartEvent startEvent = ModelUtils.getStartEvent(bpmnModel);
        WfDeployForm deployForm = deployFormMapper.selectOne(new LambdaQueryWrapper<WfDeployForm>()
            .eq(WfDeployForm::getDeployId, deployId)
            .eq(WfDeployForm::getFormKey, startEvent.getFormKey())
            .eq(WfDeployForm::getNodeKey, startEvent.getId()));
        FormConf formConf = JsonUtils.parseObject(deployForm.getContent(), FormConf.class);
        if (ObjectUtil.isNull(formConf)) {
            throw new RuntimeException("获取流程表单失败!");
        }
        if (ObjectUtil.isNotEmpty(procInsId)) {
            // 获取流程实例
            HistoricProcessInstance historicProcIns = historyService.createHistoricProcessInstanceQuery()
                .processInstanceId(procInsId)
                .includeProcessVariables()
                .singleResult();
            // 填充表单信息
            ProcessFormUtils.fillFormData(formConf, historicProcIns.getProcessVariables());
        }
        return formConf;
    }

启动(产生流程实例)

产生流程实例,个人将类与对象类比,流程实例就类似为类实例化的具体对象

API

repositoryService.createProcessDefinitionQuery() .processDefinitionId(procDefId).singleResult();

identityService.setAuthenticatedUserId(userIdStr);

identityService.setAuthenticatedUserId(TaskUtils.getUserId());

runtimeService.startProcessInstanceById(procDef.getId(), variables);(流程实例)

key学习:

获取流程定义-》启动流程实例-》启动任务

    /**
     * 根据流程定义ID启动流程实例
     *
     * @param procDefId 流程定义Id
     * @param variables 流程变量
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void startProcessByDefId(String procDefId, Map<String, Object> variables) {
        try {
            ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .processDefinitionId(procDefId).singleResult();
            startProcess(processDefinition, variables);
        } catch (Exception e) {
            e.printStackTrace();
            throw new ServiceException("流程启动错误");
        }
    }
    /**
     * 启动流程实例
     */
    private void startProcess(ProcessDefinition procDef, Map<String, Object> variables) {
       //是否为空且是被挂起
         if (ObjectUtil.isNotNull(procDef) && procDef.isSuspended()) {
            throw new ServiceException("流程已被挂起,请先激活流程");
        }
        // 设置流程发起人Id到流程中
        String userIdStr = TaskUtils.getUserId();
        identityService.setAuthenticatedUserId(userIdStr);
        variables.put(BpmnXMLConstants.ATTRIBUTE_EVENT_START_INITIATOR, userIdStr);
        // 设置流程状态为进行中
        variables.put(ProcessConstants.PROCESS_STATUS_KEY, ProcessStatus.RUNNING.getStatus());
        // 发起流程实例
        ProcessInstance processInstance = runtimeService.startProcessInstanceById(procDef.getId(), variables);
        // 第一个用户任务为发起人,则自动完成任务
      //  wfTaskService.startFirstTask(processInstance, variables);
    }

任务

任务审批

任务状态

待办任务

基础类

完成通过 Complete

API

taskService.createTaskQuery().taskId(taskBo.getTaskId()).singleResult()//获取任务(.list)

repositoryService.getBpmnModel(task.getProcessDefinitionId())

 taskService.addComment  taskService.setAssignee

 taskService.complete(taskBo.getTaskId(),map, localScope);

    public void complete(WfTaskBo taskBo) {
        //根据taskId获取任务
        Task task = taskService.createTaskQuery().taskId(taskBo.getTaskId()).singleResult();

        if (Objects.isNull(task)) {
            throw new ServiceException("任务不存在");
        }
        // 获取 bpmn 模型
        BpmnModel bpmnModel = repositoryService.getBpmnModel(task.getProcessDefinitionId());
        identityService.setAuthenticatedUserId(TaskUtils.getUserId());
        //判断是否为委派
        if (DelegationState.PENDING.equals(task.getDelegationState())) {
            taskService.addComment(taskBo.getTaskId(), taskBo.getProcInsId(), FlowComment.DELEGATE.getType(), taskBo.getComment());
            taskService.resolveTask(taskBo.getTaskId());
        } else {
            taskService.addComment(taskBo.getTaskId(), taskBo.getProcInsId(), FlowComment.NORMAL.getType(), taskBo.getComment());
            //设置审批人
            taskService.setAssignee(taskBo.getTaskId(), TaskUtils.getUserId());
            if (ObjectUtil.isNotEmpty(taskBo.getVariables())) {
                // 获取模型信息
                String localScopeValue = ModelUtils.getUserTaskAttributeValue(bpmnModel, task.getTaskDefinitionKey(), ProcessConstants.PROCESS_FORM_LOCAL_SCOPE);
                System.out.println("localScopeValue"+localScopeValue);
                boolean localScope = Convert.toBool(localScopeValue, false);
                System.out.println("localScope"+localScope);
                Map<String, Object> map = new HashMap<>();

                taskService.complete(taskBo.getTaskId(),map, localScope);

            } else {
                taskService.complete(taskBo.getTaskId());
            }
        }
        // 设置任务节点名称
        taskBo.setTaskName(task.getName());
        // 处理下一级审批人
        if (StringUtils.isNotBlank(taskBo.getNextUserIds())) {
            this.assignNextUsers(bpmnModel, taskBo.getProcInsId(), taskBo.getNextUserIds());
        }
        // 处理抄送用户
        if (!copyService.makeCopy(taskBo)) {
            throw new RuntimeException("抄送任务失败");
        }
    }

Queue ArrayList Iterator

 /**
     * 指派下一任务审批人
     * @param bpmnModel bpmn模型
     * @param processInsId 流程实例id
     * @param userIds 用户ids
     */
    private void assignNextUsers(BpmnModel bpmnModel, String processInsId, String userIds) {
        // 获取所有节点信息
        List<Task> list = taskService.createTaskQuery()
            .processInstanceId(processInsId)
            .list();
        if (list.size() == 0) {
            return;
        }
        Queue<String> assignIds = CollUtil.newLinkedList(userIds.split(","));
        if (list.size() == assignIds.size()) {
            for (Task task : list) {
                taskService.setAssignee(task.getId(), assignIds.poll());
            }
            return;
        }
        // 优先处理非多实例任务
        Iterator<Task> iterator = list.iterator();
        while (iterator.hasNext()) {
            Task task = iterator.next();
            if (!ModelUtils.isMultiInstance(bpmnModel, task.getTaskDefinitionKey())) {
                if (!assignIds.isEmpty()) {
                    taskService.setAssignee(task.getId(), assignIds.poll());
                }
                iterator.remove();
            }
        }
        // 若存在多实例任务,则进行动态加减签
        if (CollUtil.isNotEmpty(list)) {
            if (assignIds.isEmpty()) {
                // 动态减签
                for (Task task : list) {
                    runtimeService.deleteMultiInstanceExecution(task.getExecutionId(), true);
                }
            } else {
                // 动态加签
                for (String assignId : assignIds) {
                    Map<String, Object> assignVariables = Collections.singletonMap(BpmnXMLConstants.ATTRIBUTE_TASK_USER_ASSIGNEE, assignId);
                    runtimeService.addMultiInstanceExecution(list.get(0).getTaskDefinitionKey(), list.get(0).getProcessInstanceId(), assignVariables);
                }
            }
        }
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/549198.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

《大话数据结构》01

1. 什么是数据 数据&#xff1a;是描述客观事物的符号&#xff0c;是计算机中可以操作的对象&#xff0c;是能被计算机识别&#xff0c;并输入给计算机处理的符号集合。数据不仅仅包括整型、实型等数值类型&#xff0c;还包括字符及声音、图像、视频等非数值类型。 比如我们现…

Java --- 类与对象

上篇内容给大家带来了Java的语句与数组的相关内容&#xff0c;那么本期内容比较重要&#xff0c;需要读者们掌握Java面向对象编程的根本&#xff0c;通过这篇博客来让读者浅入理解Java类的一些基本操作。 目录 一.特点&#xff1a; 二.成员变量&#xff1a; 三.访问修饰符&a…

Chatgpt掘金之旅—有爱AI商业实战篇|构建SaaS业务|(二十)

演示站点&#xff1a; https://ai.uaai.cn 对话模块 官方论坛&#xff1a; www.jingyuai.com 京娱AI 一、程序员如何搞副业构建 SAAS 业务&#xff1f; 程序员不仅拥有将抽象概念转化为实际应用的能力&#xff0c;还通常具备强大的逻辑思维和问题解决能力。然而&#xff0c;许…

读书笔记之《如何精心设计提示词来精通ChatGPT》

《如何精心设计提示词来精通ChatGPT》这本书英文标题为&#xff1a;《The Art of Prompt Engineering with chatGPT》&#xff0c;于2023年出版。作者是Nathan Hunter 。 Nathan Hunter简介&#xff1a;ChatGPT培训的创始人。作为一名资深培训师和教学设计师&#xff0c;我在过…

【MogDB】在ORACLE和MogDB中查看存储过程出参游标数据的方式

一、前言 使用ORACLE作为数据库的应用软件中&#xff0c;偶尔会遇到使用游标作为出参的存储过程&#xff0c;这种存储过程迁移到MogDB并不需要进行改造&#xff0c;但是在开发这样的存储过程时&#xff0c;开发人员偶尔会想要在数据库中测试执行一下&#xff0c;看看游标中的数…

OpenHarmony实战开发-Grid和List内拖拽交换子组件位置。

介绍 本示例分别通过onItemDrop()和onDrop()回调&#xff0c;实现子组件在Grid和List中的子组件位置交换。 效果图预览 使用说明&#xff1a; 拖拽Grid中子组件&#xff0c;到目标Grid子组件位置&#xff0c;进行两者位置互换。拖拽List中子组件&#xff0c;到目标List子组件…

MongoDB的go SDK使用集锦

在上一章解读MongoDB官方文档获取mongo7.0版本的安装步骤与基本使用介绍了如何使用mongo shell操作mongo数据库&#xff0c;接下来介绍如何使用sdk来操作数据库&#xff0c;这里以go语言为例&#xff0c;其他语言请查看源文档mongo docs Quick Start 内置数据结构 MongoDB是存…

记第一次踩坑Gradle

今天有个项目只能使用Gradle编译&#xff0c;没办法了&#xff0c;尝试吧。 先去下载了最新版本的Gradle&#xff0c;然后配置好了环境变量&#xff0c;可以在命令行使用gradle命令了。 然后打开项目开始操作一番&#xff0c;但是上来就傻眼了。 我白下载了&#xff0c;又重新下…

每日两题2

不同路径 class Solution { public:int uniquePaths(int m, int n) {vector<vector<int>> dp(m1, vector<int>(n1,0));//创建dp表dp[0][1] 1;//初始化//填表for(int i 1; i < m; i){for(int j 1; j < n; j){dp[i][j] dp[i-1][j] dp[i][j-1];}}ret…

飞书API(4):筛选数据的三种思路

截止到上一篇&#xff0c;终于通过飞书 API 完整获取到飞书多维表的数据。但是&#xff0c;有些场景&#xff0c;比如数据源会出现脏数据&#xff0c;毕竟如果是运营过程多人协作维护的数据&#xff0c;要想保持数据完美简直是天方夜谭&#xff01;再比如我们不需要完整的数据&…

JavaFX项目环境配置

Java版本 JDK15 JavaFX版本 JavaFX SDK 17 sdk下载地址https://gluonhq.com/products/javafx/ https://gluonhq.com/products/javafx/ Java FX sdk 版本不要选择22版本 与 jdk15版本不合 编辑器 配置Eclipse JDK15环境 点击Add 第二步新建一个javafx项目 点击next 勾选Ja…

Aurora 协议学习理解与应用——Aurora 8B10B协议学习

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 Aurora 8B10B协议学习之一&#xff0c;理解协议 概述8B10B数据发送和接收Symbol-Pairs传输调度用户PDU传输过程用户PDU接收过程 流控自然流量控制操作自然流量控制延迟自然流…

微信人脉扩张!多号批量自动加好友,你get到了吗?

微信是我们在拓展社交圈和寻找商业机会时&#xff0c;与更多的人建立联系的重要渠道。但是&#xff0c;手动一个个添加好友显然费时费力&#xff0c;这时候&#xff0c;微信管理系统的批量自动加好友功能就成为了微信人脉扩张的神器。 通过微信管理系统&#xff0c;我们可以轻…

JavaScript 高性能编程 —— 加载和运行

JavaScript 在浏览器中的性能,可认为是开发者所要面对的最重要的可用性问题。此问题因 JavaScript 的阻塞特征而复杂,也就是说,当 JavaScript 运行时其他的事情不能被浏览器处理。 事实上,大多数浏览 器使用单进程处理 UI 更新和 JavaScript 运行等多个任务,而同一时间只能…

C++笔记:类和对象

类和对象 认识类和对象 先来回忆一下C语言中的类型和变量&#xff0c;类型就像是定义了数据的规则&#xff0c;而变量则是根据这些规则来实际存储数据的容器。类是我们自己定义的一种数据类型&#xff0c;而对象则是这种数据类型的一个具体实例。类就可以理解为类型&#xff0c…

配置优先级标记和队列调度示例

配置优先级标记和队列调度示例 组网图形 图1 优先级标记和队列调度示例组网图 优先级标记和队列调度简介配置注意事项组网需求配置思路操作步骤配置文件 优先级标记和队列调度简介 报文进入设备之后&#xff0c;设备会根据相应的规则分配或修改报文各种优先级的值&#xff…

【鸿蒙开发】饿了么页面练习

0. 整体结构 整体划分3部分。店铺部分&#xff0c;购物车部分&#xff0c;金额统计部分。使用 Stack 把3部分堆叠 0.1 整体页面 Index.ets 修改 Index.ets &#xff0c;使用堆叠布局&#xff0c;并居底部对齐 import { ElShop } from ../components/ElShop import { ElShopp…

slRegisterDistribution failed with error: 0x8000000d Error: 0x8000000d ?

powershell用管理员打开&#xff0c;输入Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux 怎么用管理员权限打开powershell&#xff1f;

告别传统开发,轻松套用模板,低代码平台助你快速构建商城与网站

随着人工智能时代的到来&#xff0c;很多复杂的工作再日益变得简单。比如20年前开发一个在线商城完成支付交易&#xff0c;那是一个不得了的事情&#xff0c;现在的零售巨头淘宝和京东就是在那个时代崛起的。新时代涌现出了许多新的工具&#xff0c;比如使用低代码平台搭建的自…

【STL详解 —— priority_queue的使用与模拟实现】

STL详解 —— priority_queue的使用与模拟实现 priority_queue的使用priority_queue的介绍priority_queue的定义方式priority_queue各个接口的使用 priority_queue的模拟实现仿函数priority_queue的模拟实现 priority_queue的使用 priority_queue的介绍 std::priority_queue 是…