经过部署流程前后对比,发现每次部署流程activiti会在ACT_RE_DEPLOYMENT添加一条部署记录、在ACT_RE_PROCDEF表添加一条流程记录、在ACT_GE_BYTEARRAY表中添加流程的定义信息。
ACT_RE_DEPLOYMENT表结构如下:
ACT_RE_PROCDEF表结构如下:
ACT_GE_BYTEARRAY表结构如下:
经过观察发现,其实activiti查询流程定义信息就是根据ACT_RE_PROCDEF表中DEPLOYMENT_ID_(流程的部署id)去查找ACT_GE_BYTEARRAY表中对应DEPLOYMENT_ID_的定义信息,至此大致思路已经有了,想动态修改已部署的流程的流程图,只需要将修改之后的流程图进行部署,然后将ACT_GE_BYTEARRAY表中新生成的(修改后的)流程图定义信息的DEPLOYMENT_ID_改为原来要修改流程的DEPLOYMENT_ID_,然后再删除ACT_RE_DEPLOYMENT表中新流程的部署记录、ACT_GE_BYTEARRAY表中原流程的定义信息即可。
@Transactional @Override public int updateProcess(ModelBo model, String processId) throws XMLStreamException { // 获取模型流程图 byte[] bpmnBytes = model.getBpmn().getBytes(); // 获取模型流程图svg byte[] svgBytes = model.getSvg().getBytes(); DeploymentBuilder deploymentBuilder = repositoryService.createDeployment(); deploymentBuilder.addInputStream("diagram.bpmn", new ByteArrayInputStream(bpmnBytes)); deploymentBuilder.addInputStream("diagram.png",new ByteArrayInputStream(svgBytes)); // 流程分类 deploymentBuilder.category(model.getCategory()); // 流程名 (model.getName()); // 部署修改后的流程 Deployment deployment = deploymentBuilder.deploy(); // 修改activiti中流程图 // 查询原流程定义信息 ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processId).singleResult(); // 删除新流程的部署记录 String deleteNewProcessSQL = "DELETE FROM ACT_RE_PROCDEF WHERE DEPLOYMENT_ID_ = '" + deployment.getId() + "'"; commonMapper.executeDeleteSql(deleteNewProcessSQL); // 删除原流程图信息 String deleteOldProcessDataSQL = "DELETE FROM ACT_GE_BYTEARRAY WHERE DEPLOYMENT_ID_ = '" + processDefinition.getDeploymentId() + "'"; commonMapper.executeDeleteSql(deleteOldProcessDataSQL); // 修改新部署的流程图文件的部署id为原流程的部署id String updateNewProcessDataToOldProcessSQL = "UPDATE ACT_GE_BYTEARRAY SET DEPLOYMENT_ID_ = '" + processDefinition.getDeploymentId() + "' " + "WHERE DEPLOYMENT_ID_ = '" + deployment.getId() + "'"; commonMapper.executeUpdateSql(updateNewProcessDataToOldProcessSQL); String deleteDeploymentSQL = "DELETE FROM ACT_RE_DEPLOYMENT WHERE ID_ = '" + deployment.getId() + "'"; // 删除部署表记录 commonMapper.executeDeleteSql(deleteDeploymentSQL); return 1; }
上面代码中的ModelBo为作者自己定义用于传参的实体,主要参数为流程名、流程图定义xml、流程图svg、要修改流程的processId(流程id),可以根据自己需求进行参数的修改。
3 Activiti7中流程定义信息的缓存问题到此运行上面代码的updateProcess方法进行修改流程,修改完成之后发现产生了一个问题,被修改之后的流程图只有在重新启动项目的时候才会生效,也就是调用修改流程图方法之后并没有立刻生效,这是因为activiti7的流程定义信息缓存机制,在流程引擎启动的时候默认会将流程的定义信息加载到内存中进行存储(其实也就是存在一个Map中)以防止后面每次进行流程相关操作的时候都要重新查询数据库获取流程图信息,在经过研究和阅读源码之后发现ProcessEngineConfigurationImpl就是实现缓存流程定义信息的,里面的getProcessDefinitionCache就是获取缓存的流程定义信息的方法,而流程定义信息则被存在类的processDefinitionCache这个成员变量中,所以我们可以想到一个清空缓存迫使activiti重新加载流程图定义信息到缓存中的方法。
这个操作可以分为三步
在流程引擎启动的时候存储流程引擎的配置对象springProcessEngineConfiguration
然后在修改流程图之后,获取配置对象,然后获取流程定义信息缓存对象
然后根据key,也就流程id删除缓存对象中对应的键值
存储流程引擎配置对象如下:
package com.hui.workflow.config; import org.activiti.spring.SpringProcessEngineConfiguration; import org.activiti.spring.boot.ProcessEngineConfigurationConfigurer; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import java.util.ArrayList; import java.util.List; /** * @author DengYingHui */ @Configuration public class ActivitiConfig implements ProcessEngineConfigurationConfigurer { @Autowired private GlobalEventListener activitiEventListener; // 存储引擎配置,以供后面使用 private static SpringProcessEngineConfiguration springProcessEngineConfiguration; @Override public void configure(SpringProcessEngineConfiguration springProcessEngineConfiguration) { ActivitiConfig.springProcessEngineConfiguration = springProcessEngineConfiguration; } /** * 获取流程引擎配置 * @return */ public static SpringProcessEngineConfiguration getSpringProcessEngineConfiguration() { return springProcessEngineConfiguration; } }
删除缓存中对应的流程配置信息
/** * 根据流程id清除activiti引擎中流程缓存 * @param processId */ public static void clearProcessDefinitionCacheByProcessId(String processId) { ActivitiConfig.getSpringProcessEngineConfiguration().getProcessDefinitionCache().remove(processId); }
只需要在动态修改流程图的方法之后调用一次clearProcessDefinitionCacheByProcessId方法即可。
至此,已完成对activiti7中已部署的流程图进行动态修改。