侧边栏壁纸
博主头像
彼豆博主等级

行动起来,活在当下

  • 累计撰写 14 篇文章
  • 累计创建 17 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

activiti修改流程图重新发布后对正在运行的流程生效

彼豆
2020-12-17 / 0 评论 / 1 点赞 / 12 阅读 / 9630 字

需求

  • 支持在线动态修改流程图

  • 修改流程图发布后对正在运行的流程也要生效

    修改前流程

    修改前A流程实时流程.PNG

    修改后同样一个未审批完成的任务的实时流程图

    修改后流程.PNG

    修改后A流程实时流程.PNG

实现思路

  • 从流程模型表act_re_model中加载流程模型,使用流程设计器修改修改流程。
  • 调用activiti的API部署新的流程。
  • 根据流程定义Key查找正在运行的流程定义。
  • 根据流程定义文件替换BPMN文件

原理分析

act_dynamic_process.PNG

流程引擎中是根据act_ge_bytearray中存储的BPMN二进制信息知道流程的走向的,所以,实现思路就是拿新的BPMN二进制文件替换旧的BPMN文件即可实现新的流程应用到新的流程中。

代码

注意!!:需要清除BpmnModelCacheProcessDefinitionCache否则不生效

// 相关的包
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.JsonNode;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.impl.persistence.entity.ResourceEntity;
///////// Class 省略----------
    @Autowired
    private RepositoryService repositoryService;
/**
     * 部署流程
     *
     * @param modelId 模型id
     * @return result
     */
    @Override
    public Result<Object> deployProcess(String modelId) {

        Model modelData = repositoryService.getModel(modelId);
        // bpmn的json格式
        byte[] jsonBytes = repositoryService.getModelEditorSource(modelId);
        try {
            // 转成json节点对象
            JsonNode modelNode = new ObjectMapper().readTree(jsonBytes);
            // 转成Bpmn
            BpmnModel model = new BpmnJsonConverter().convertToBpmnModel(modelNode);

            if(model.getProcesses().isEmpty()){
                return Result.error("模型不符要求,请至少设计一条主线流程");
            }
            // 转成二进制
            byte[] bpmnBytes = new BpmnXMLConverter().convertToXML(model);
            // 部署发布模型流程
            String processName =modelData.getName() + ".bpmn20.xml";

            // 部署流程
            Deployment deployment = repositoryService.createDeployment()
                    .name(modelData.getName())
                    .addString(processName, new String(bpmnBytes, "UTF-8"))
                    .deploy();

            // 获取元数据信息
            String metaInfo = modelData.getMetaInfo();
            JSONObject metaInfoMap = JSON.parseObject(metaInfo);
            
            // 获取图片二进制
            byte[] imgBytes = repositoryService.getModelEditorSourceExtra(modelId);

            // 同时应用到正在运行中的流程
            this.updateProcdef(modelData.getKey(), bpmnBytes, imgBytes);

        } catch (IOException e) {
            log.error("部署流程-读取模型数据报错",e);
            return Result.error("读取模型数据失败,请检查流程");
        } catch (XMLException e){
            log.error("部署流程-解析xml",e);
            return Result.error("读取模型数据失败,请检查流程是否正确");
        }

        return Result.ok("部署成功");
    }

    /**
     * 替换BPMN文件和流程图片
     *	@param processKey 流程定义key
     *  @param xml BPMN文件二进制
     *  @param img 流程图文件二进制
     */
    @Override
    public void updateProcdef(String processKey, byte[] xml, byte[] img) {
        // 正在运行中的流程定义信息
        List<ProcessDefinitionEntity> definitions = actCustomService.queryTaskDeployment(processKey);

        // 获取配置
        ProcessEngineConfigurationImpl configuration = (ProcessEngineConfigurationImpl) processEngine.getProcessEngineConfiguration();
        DeploymentManager deploymentManager = configuration.getDeploymentManager();

        for (ProcessDefinitionEntity definition : definitions) {
            // 移除缓存!!!!【重要】
            deploymentManager.getBpmnModelCache().remove(definition.getId());
            deploymentManager.getProcessDefinitionCache().remove(definition.getId());
            // 更新BPMN文件
            ResourceEntity xmlEntity = new ResourceEntity();
            xmlEntity.setDeploymentId(definition.getDeploymentId());
            xmlEntity.setName(definition.getResourceName());
            xmlEntity.setBytes(xml);
            actCustomService.updateProcessDefinitionResource(xmlEntity);

            // 更新流程图片文件
            ResourceEntity imgEntity = new ResourceEntity();
            imgEntity.setDeploymentId(definition.getDeploymentId());
            imgEntity.setName(definition.getDiagramResourceName());
            imgEntity.setBytes(img);
            actCustomService.updateProcessDefinitionResource(imgEntity);
        }
    }

``ActCustomService调用更新二进制文件的的Mapper`接口

public interface ActCustomMapper {
    /**
     * 更新流程定义的xml和流程图片
     * @param entity 信息
     * @return 更新条数
     */
    int updateProcessDefinitionResource(@Param("resource") ResourceEntity entity);
}

SQL

    <!--更新资源-->
    <update id="updateProcessDefinitionResource">
        UPDATE `act_ge_bytearray`
        SET BYTES_ = #{resource.bytes}
        <where>
            DEPLOYMENT_ID_ = #{resource.deploymentId}
            AND NAME_ = #{resource.name}
        </where>
    </update>
1

评论区