Activiti UEL 表達式
UEL表達式到底是什麼呢?
UEL是java EE6規範的一部分,UEL(Unified Expression Language)即統一表達式語言,activiti支援兩個UEL表達式:UEL-value和UEL-method
Activiti使用UEL進行表達式解析(有關詳細資訊,請參閱EE6規範)
Activiti 如何使用UEL表達式擷取Spring 容器中的bean?
答案在activiti-spring.jar中
SpringExpressionManager.java //spring表達式管理類
public class SpringExpressionManager extends ExpressionManager {
//應用上下文
protected ApplicationContext applicationContext;
public SpringExpressionManager(ApplicationContext applicationContext, Map<Object, Object> beans) {
super(beans);//這個beans是流程引擎中的beans
this.applicationContext = applicationContext;
}
@Override
protected ELResolver createElResolver(VariableScope variableScope) {
//複合el表達式
CompositeELResolver compositeElResolver = new CompositeELResolver();
compositeElResolver.add(new VariableScopeElResolver(variableScope));
//判斷beans是否為空
if (beans != null) {
// 在表達式中隻暴露流程引擎中的beans
compositeElResolver.add(new ReadOnlyMapELResolver(beans));
} else {
// 在表達式中暴露整個application-context
compositeElResolver.add(new ApplicationContextElResolver(applicationContext));
}
//添加數組解析器
compositeElResolver.add(new ArrayELResolver());
//添加集合解析器
compositeElResolver.add(new ListELResolver());
//添加map解析器
compositeElResolver.add(new MapELResolver());
//添加json格式的資料解析器 like {key:value,...} or [1,2,3,4,...]
compositeElResolver.add(new JsonNodeELResolver());
//添加bean解析器
compositeElResolver.add(new BeanELResolver());
return compositeElResolver;
}
在ProcessEngineConfigurationImpl.java中調用
public class ProcessEngineFactoryBean implements FactoryBean<ProcessEngine>, DisposableBean, ApplicationContextAware {
...
protected void configureExpressionManager() {
if (processEngineConfiguration.getExpressionManager() == null && applicationContext != null) {
processEngineConfiguration.setExpressionManager(new SpringExpressionManager(applicationContext, processEngineConfiguration.getBeans()));
}
}
...
}
使用表達式
Activiti的Expression 接口
public interface Expression extends Serializable {
// variableScope 為變量作用域
Object getValue(VariableScope variableScope);
void setValue(Object value, VariableScope variableScope);
String getExpressionText();
}
在代碼中的具體使用
//擷取表達式對象
//execution 為 VariableScope 的實作類 用于從不同的變量作用域中取變量
Expression expression = expressionManager.createExpression("${bean.id}");
businessKey = expression.getValue(execution).toString();
為什麼有VariableScope
因為Activiti中有很多流程,每一個流程都有很多變量,使用變量的時候肯定不能去拿其他流程的變量,為了更好的管理在表達式中使用變量,是以這裡就有了一個變量作用域的概念
通過變量作用域獲得EL上下文
public class ExpressionManager {
...
public ELContext getElContext(VariableScope variableScope) {
ELContext elContext = null;
if (variableScope instanceof VariableScopeImpl) {
VariableScopeImpl variableScopeImpl = (VariableScopeImpl) variableScope;
elContext = variableScopeImpl.getCachedElContext();
}
if (elContext == null) {
//如果沒有就建立一個EL上下文
elContext = createElContext(variableScope);
if (variableScope instanceof VariableScopeImpl) {
((VariableScopeImpl) variableScope).setCachedElContext(elContext);
}
}
return elContext;
}
...
}
VariableScope 的實作類
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAzNvwVZ2x2bzNXak9CX90TQNNkRrFlQKBTSvwFbslmZvwFMwQzLcVmepNHdu9mZvwFVywUNMZTY18CX052bm9CX9s2MilGZtJWM5cVZ6xmMMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2LcRHelR3LcJzLctmch1mclRXY39zM0IjMzkDN0EDMzcDM4EDMy8CX0Vmbu4GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
實作類就隻要有三個類
- NoExecutionVariableScope.java
- TaskEntityImpl.java
- ExecutionEntityImpl.java
其中VariableScopeImpl 是個抽象類,這裡使用了模闆模式
需要子類實作的方法
protected abstract Collection<VariableInstanceEntity> loadVariableInstances();
protected abstract VariableScopeImpl getParentVariableScope();
protected abstract void initializeVariableInstanceBackPointer(VariableInstanceEntity variableInstance);
protected abstract VariableInstanceEntity getSpecificVariable(String variableName);
JUEL實作類
public class JuelExpression implements Expression {
protected String expressionText;
protected ValueExpression valueExpression;
public JuelExpression(ValueExpression valueExpression, String expressionText) {
this.valueExpression = valueExpression;
this.expressionText = expressionText;
}
public Object getValue(VariableScope variableScope) {
//擷取值的時候都要通過variableScope擷取上下文
ELContext elContext = Context.getProcessEngineConfiguration().getExpressionManager().getElContext(variableScope);
try {
ExpressionGetInvocation invocation = new ExpressionGetInvocation(valueExpression, elContext);
Context.getProcessEngineConfiguration().getDelegateInterceptor().handleInvocation(invocation);
return invocation.getInvocationResult();
} catch (PropertyNotFoundException pnfe) {
throw new ActivitiException("Unknown property used in expression: " + expressionText, pnfe);
} catch (MethodNotFoundException mnfe) {
throw new ActivitiException("Unknown method used in expression: " + expressionText, mnfe);
} catch (ELException ele) {
throw new ActivitiException("Error while evaluating expression: " + expressionText, ele);
} catch (Exception e) {
throw new ActivitiException("Error while evaluating expression: " + expressionText, e);
}
}
public void setValue(Object value, VariableScope variableScope) {
ELContext elContext = Context.getProcessEngineConfiguration().getExpressionManager().getElContext(variableScope);
try {
ExpressionSetInvocation invocation = new ExpressionSetInvocation(valueExpression, elContext, value);
Context.getProcessEngineConfiguration().getDelegateInterceptor().handleInvocation(invocation);
} catch (Exception e) {
throw new ActivitiException("Error while evaluating expression: " + expressionText, e);
}
}
@Override
public String toString() {
if (valueExpression != null) {
return valueExpression.getExpressionString();
}
return super.toString();
}
public String getExpressionText() {
return expressionText;
}
}