場景:工作流在配置分支的時候,需要配置流條件,而流條件有時候會比較復雜,容易寫錯。本章主要描述 如何從 flowable 源碼中拿到 表達式處理代碼。
環(huán)境:
springboot:2.2.0.RELEASE
flowable:6.4.2

測試流程圖
如上圖,表達式的寫法可以很多用,flowable會基于spring EL 表達式的基礎上,再進行擴展:
到節(jié)點A:(自定義函數)流條件:
${variables:substr(a1,index1,end1)}=='哈哈'}
到節(jié)點B:(數字比較)流條件:
${b==2}
到節(jié)點C:(字符串對象方法)流條件:
${c.contains("BCD")}
所以如果要進行 flowable 表達式 校驗,就需要模擬拿到核心。
從源碼中可以找到類:org.flowable.engine.impl.util.condition.ConditionUtil
Expression expression = CommandContextUtil.getProcessEngineConfiguration().getExpressionManager().createExpression(conditionExpression);
Condition condition = new UelExpressionCondition(expression);
return condition.evaluate(sequenceFlow.getId(), execution);
通過Debug,可以找到實現類:
org.flowable.spring.SpringExpressionManager
org.flowable.engine.impl.el.JuelExpression
org.flowable.engine.impl.el.UelExpressionCondition
org.flowable.engine.impl.el.UelExpressionCondition
public class UelExpressionCondition implements Condition {
protected Expression expression;
public UelExpressionCondition(Expression expression) {
this.expression = expression;
}
@Override
public boolean evaluate(String sequenceFlowId, DelegateExecution execution) {
Object result = expression.getValue(execution);
if (result == null) {
throw new FlowableException("condition expression returns null (sequenceFlowId: " + sequenceFlowId + ")" );
}
if (!(result instanceof Boolean)) {
throw new FlowableException("condition expression returns non-Boolean (sequenceFlowId: " + sequenceFlowId + "): " + result + " (" + result.getClass().getName() + ")");
}
return (Boolean) result;
}
}
由上面就可以基本定位到主要代碼只有
Expression expression = CommandContextUtil.getProcessEngineConfiguration()
.getExpressionManager()
.createExpression(conditionExpression);
Object result = expression.getValue(execution);
PS: 前置條件:CommandContextUtil 這一類Utils在flowable中,會在Command獲取緩存,直接調回導致 空指針
最終代碼為:
package com.example.oldguy.modules.app.plugins;
import org.flowable.common.engine.api.delegate.Expression;
import org.flowable.common.engine.impl.el.ExpressionManager;
import org.flowable.common.engine.impl.interceptor.Command;
import org.flowable.common.engine.impl.interceptor.CommandContext;
import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.impl.persistence.entity.ExecutionEntityImpl;
import org.flowable.engine.impl.util.CommandContextUtil;
import java.util.Map;
/**
* @ClassName: ExpressTestCmd
* @Author: hrh
* @Description:
* @Version:
**/
public class ExpressTestCmd implements Command<Object> {
private String conditionExpression;
private Map<String, Object> data;
public ExpressTestCmd(String conditionExpression, Map<String, Object> data) {
this.conditionExpression = conditionExpression;
this.data = data;
}
@Override
public Object execute(CommandContext commandContext) {
ExpressionManager expressionManager = CommandContextUtil.getProcessEngineConfiguration().getExpressionManager();
Expression expression = expressionManager.createExpression(conditionExpression);
DelegateExecution delegateExecution = new ExecutionEntityImpl();
delegateExecution.setTransientVariables(data);
return expression.getValue(delegateExecution);
}
}
測試調用:
@SpringBootTest
public class ExpressTests0924 {
@Autowired
private ManagementService managementService;
@Test
public void test() {
// String expression = "${a==1}";
String expression = "${variables:substr(a1,index1,end1)}${variables:substr(a2,index2)}";
// String expression = "${substr(a1,index1,end1)}";
Map<String, Object> data = new HashMap<>();
data.put("a1", "東方");
data.put("a", "1");
data.put("index1", 0);
data.put("end1", 2);
data.put("a2", "方不敗");
data.put("index2", 1);
Object result = managementService.executeCommand(new ExpressTestCmd(expression, data));
System.out.println(result);
}
}
返回結果:

image.png
最后在調用異常的時候,需要對異常進行處理(下面只示例參數傳輸不完整)
org.flowable.common.engine.impl.javax.el.PropertyNotFoundException 傳值不完整時候。

image.png