需求
-
支持在线动态修改流程图
-
修改流程图发布后对正在运行的流程也要生效
修改后同样一个未审批完成的任务的
实时流程图
实现思路
- 从流程模型表
act_re_model
中加载流程模型,使用流程设计器修改修改流程。 - 调用
activiti
的API部署新的流程。 - 根据流程定义Key查找正在运行的流程定义。
- 根据流程定义文件替换BPMN文件
原理分析
流程引擎中是根据act_ge_bytearray
中存储的BPMN二进制信息知道流程的走向的,所以,实现思路就是拿新的BPMN二进制文件替换旧的BPMN文件
即可实现新的流程应用到新的流程中。
代码
注意!!:需要清除BpmnModelCache
和ProcessDefinitionCache
否则不生效
// 相关的包
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>
评论区