如何实现Activiti的分支条件的自定义配置

2024-11-19 09:24:32
推荐回答(1个)
回答1:

、Activiti流程支条件局限
Activiti流程支条件目前采用脚本判断式并且需要流程定义进行支条件设定图所示:

${input == 1}

${input == 2}

${input == 3}

面定义看流程支条件存两致命局限性:
1.支条件需要流程定义(XML)设定要求流程定义必须由发员设计及编写
2.支条件比较简单般boolean表达式表达式单变量判断处理
两局限性限制流程支判断处理必须由发员设定内部流程应用都要求普通业务员即处理或者由定计算机基础员设置处理要求我流程条件设置提更高要求节我通修改Activiti流程定义XML支条件表达式同刷新流程定义引擎缓存代码基于种式:
JsonNode jsonObject=objectMapper.readTree(configJson);
JsonNode configsNode=jsonObject.get("configs");
BpmSolution bpmSolution=bpmSolutionManager.get(solId);
BpmDef bpmDef=bpmDefManager.getLatestBpmByKey(bpmSolution.getDefKey(), ContextUtil.getCurrentTenantId());
ActProcessDef processDef=actRepService.getProcessDef(bpmDef.getActDefId());
String processDefXml=actRepService.getBpmnXmlByDeployId(bpmDef.getActDepId());
System.out.println("xml:"+processDefXml);
ActNodeDef sourceNode=processDef.getNodesMap().get(nodeId);
ByteArrayInputStream is=new ByteArrayInputStream(processDefXml.getBytes());
Map map = new HashMap();
map.put("bpm","");
map.put("xsi","");
SAXReader saxReader = new SAXReader();
saxReader.getDocumentFactory().setXPathNamespaceURIs(map);
Document doc = saxReader.read(is);
//Document doc=Dom4jUtil.load(is, "UTF-8");
Element rootEl=doc.getRootElement();
if(configsNode!=null){
//取支条件列表
JsonNode configs=configsNode.get("conditions");
if(configs!=null){
Iterator it=configs.elements();
while(it.hasNext()){
ObjectNode config=(ObjectNode)it.next();
String tmpNodeId=config.get("nodeId").textValue();
String tmpCondition=config.get("condition").textValue();
Element seqFlow=(Element)rootEl.selectSingleNode("/bpm:definitions/bpm:process/bpm:sequenceFlow[@sourceRef='"
+sourceNode.getNodeId()+"' and @targetRef='"+tmpNodeId+"']");
if(seqFlow==null) continue;
Element conditionExpress=(Element)seqFlow.selectSingleNode("bpm:conditionExpression");
if(conditionExpress==null){
conditionExpress=seqFlow.addElement("conditionExpression");
conditionExpress.addAttribute("xsi:type", "tFormalExpression");
}else{
conditionExpress.clearContent();
}
conditionExpress.addCDATA(tmpCondition);
}
}
}
//修改流程定义XML并且清空该流程定义缓存
actRepService.doModifyXmlAndClearCache(bpmDef.getActDefId(),bpmDef.getActDepId(), doc.asXML());

【说明】
1.基于种式容易错流程支条件写流程定义XML比较容易问题同清楚员填写条件XML文件
2.于Jsaas流程定义用于流程解决案使用配置同条件太适合流程定义能支条件设置
基于要求我Activiti进行扩展使我允许流程引擎支判断处理执行我条件设置其原理:

流程引擎跳至支条件判断处理让执行我脚本设置条件条件满足则跳至我设置目标节点实现干预流程引擎本身执行式影响Activiti原运行机制我保留其旧执行判断式
二、Activiti扩展点
Activiti流程扩展比较灵我通改写ExclusiveGateway节点行即其实现:
package com.redxun.bpm.activiti.ext;
import java.util.Iterator;
import javax.annotation.Resource;
import org.activiti.engine.impl.bpmn.behavior.ExclusiveGatewayActivityBehavior;
import org.activiti.engine.impl.pvm.PvmTransition;
import org.activiti.engine.impl.pvm.delegate.ActivityExecution;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.redxun.bpm.core.entity.config.ExclusiveGatewayConfig;
import com.redxun.bpm.core.entity.config.NodeExecuteScript;
import com.redxun.bpm.core.manager.BpmNodeSetManager;
import com.redxun.core.script.GroovyEngine;
import com.sun.star.uno.RuntimeException;
/**
* 网关条件判断优先使用扩展配置
* @author keitch
*
*/
@SuppressWarnings("serial")
public class ExclusiveGatewayActivityBehaviorExt extends ExclusiveGatewayActivityBehavior{

protected static Logger log = LoggerFactory.getLogger(ExclusiveGatewayActivityBehaviorExt.class);

//节点设置管理器
@Resource
BpmNodeSetManager bpmNodeSetManager;
//脚本引擎
@Resource GroovyEngine groovyEngine;

@Override
protected void leave(ActivityExecution execution) {
log.debug("enter ExclusiveGatewayActivityBehaviorExt=======================");
if (log.isDebugEnabled()) {
log.debug("Leaving activity '{}'", execution.getActivity().getId());
}
String solId=(String)execution.getVariable("solId");
String nodeId=execution.getActivity().getId();
log.debug("solid is {} and nodeId is {}",solId,nodeId);

if(StringUtils.isNotEmpty(solId)&& StringUtils.isNotBlank(nodeId)){
ExclusiveGatewayConfig configs=bpmNodeSetManager.getExclusiveGatewayConfig(solId, nodeId);
for(NodeExecuteScript script:configs.getConditions()){
String destNodeId=script.getNodeId();
String condition=script.getCondition();
log.debug("dest node:{}, condition is {}",destNodeId,condition);
//执行脚本引擎
Object boolVal=groovyEngine.executeScripts(condition, execution.getVariables());
if(boolVal instanceof Boolean){
Boolean returnVal=(Boolean)boolVal;//符合条件
if(returnVal==true){
//找符合条件目标节点并且进行跳转
Iterator transitionIterator = execution.getActivity().getOutgoingTransitions().iterator();
while (transitionIterator.hasNext()) {
PvmTransition seqFlow = transitionIterator.next();
if(destNodeId.equals(seqFlow.getDestination().getId())){
execution.take(seqFlow);
return;
}
}
}
}else{
throw new RuntimeException("表达式:\n "+condition+"\n返值布尔值(true or false)");
}
}
}
//执行父类写使其支持旧式跳线写条件做
super.leave(execution);

}
}

我通继续改写支节点跳机制并且通脚本引擎执行其条件支判断处理流程引擎并解我扩展类我需要配置Activiti流程引擎行作工厂类所示:
package com.redxun.bpm.activiti.ext;

import org.activiti.bpmn.model.ExclusiveGateway;
import org.activiti.engine.impl.bpmn.behavior.ExclusiveGatewayActivityBehavior;
import org.activiti.engine.impl.bpmn.parser.factory.DefaultActivityBehaviorFactory;

/**
* 扩展缺省流程节点默认工厂类实现Activiti节点执行默认行更改
* @author keitch
*
*/
public class ActivityBehaviorFactoryExt extends DefaultActivityBehaviorFactory {

private ExclusiveGatewayActivityBehaviorExt exclusiveGatewayActivityBehaviorExt;

/**
* 通Spring容器注入新支条件行执行类
* @param exclusiveGatewayActivityBehaviorExt
*/
public void setExclusiveGatewayActivityBehaviorExt(ExclusiveGatewayActivityBehaviorExt exclusiveGatewayActivityBehaviorExt) {
this.exclusiveGatewayActivityBehaviorExt = exclusiveGatewayActivityBehaviorExt;
}

//重写父类支条件行执行类
@Override
public ExclusiveGatewayActivityBehavior createExclusiveGatewayActivityBehavior(ExclusiveGateway exclusiveGateway) {
return exclusiveGatewayActivityBehaviorExt;
}