flowable 實現 流程表達式 校驗

場景:工作流在配置分支的時候,需要配置流條件,而流條件有時候會比較復雜,容易寫錯。本章主要描述 如何從 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
?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內容