表达式语言
Camunda平台支持统一表达式语言(EL),它是JSP 2.1标准的一部分(JSR-245)。使用了开源的JUEL实现。要获得更多关于表达式语言使用的一般信息,请阅读官方文档。
特别是提供了很好的实例,可以方便的学习表达式语法。
在Camunda平台内,EL可以在许多情况下用于评估小型的脚本式表达。下面的例子是一个使用了EL的BPMN元素:
BPMN element | EL support |
---|---|
Service Task, Business Rule Task, Send Task, Message Intermediate Throwing Event, Message End Event, Execution Listener and Task Listener | Expression language as delegation code |
Sequence Flows, Conditional Events | Expression language as condition expression |
All Tasks, All Events, Transaction, Subprocess and Connector | Expression language inside an inputOutput parameter mapping |
Different Elements | Expression language as the value of an attribute or element |
All Flow Nodes, Process Definition | Expression language to determine the priority of a job |
表达式语言的用法
委托代码
除了Java代码,Camunda平台还支持将表达式作为委托代码进行计算。关于委托代码的信息,请参见相应的章节.
目前表达式支持两种类型:camunda:expression
和camunda:delegateExpression
。
通过camunda:expression
,可以计算一个值表达式或调用一个方法表达式。你可以使用在表达式或Spring和CDI Bean中可用的特殊变量。关于变量、Spring,以及CDIbean的更多信息,请参见相应章节。
<process id="process">
<extensionElements>
<!-- execution listener which uses an expression to set a process variable -->
<camunda:executionListener event="start" expression="${execution.setVariable('test', 'foo')}" />
</extensionElements>
<!-- ... -->
<userTask id="userTask">
<extensionElements>
<!-- task listener which calls a method of a bean with current task as parameter -->
<camunda:taskListener event="complete" expression="${myBean.taskDone(task)}" />
</extensionElements>
</userTask>
<!-- ... -->
<!-- service task which evaluates an expression and saves it in a result variable -->
<serviceTask id="serviceTask"
camunda:expression="${myBean.ready}" camunda:resultVariable="myVar" />
<!-- ... -->
</process>
属性camunda:delegateExpression
用于表达式,该表达式可以调用一个委托对象。这个委托对象必须实现了JavaDelegate
或ActivityBehavior
接口。
<!-- 服务任务调用一个实现JavaDelegate接口的Bean -->
<serviceTask id="task1" camunda:delegateExpression="${myBean}" />
<!-- 服务任务调用一个返回委托对象的方法 -->
<serviceTask id="task2" camunda:delegateExpression="${myBean.createDelegate()}" />
作为条件
为了使用条件序列流(译者注:就是带条件的分支线,一般用在网关后面)或条件事件,通常使用表达式语言。对于条件序列流,必须使用序列流的 conditionExpression
元素。对于条件性事件,必须使用条件性事件的 condition
元素。两者都是 tFormalExpression
的类型。该元素的文本内容是要被计算的表达式。
在表达式中,一些特殊的变量是可用的,这些变量可以访问当前的上下文。要找到关于可用变量的更多信息,请参见变量章节。
关于表达式语言作为序列流条件的用法,请看下面的例子:
<sequenceFlow>
<conditionExpression xsi:type="tFormalExpression">
${test == 'foo'}
</conditionExpression>
</sequenceFlow>
关于表达式语言在条件事件上的用法,请看下面的例子:
<conditionalEventDefinition>
<condition type="tFormalExpression">${var1 == 1}</condition>
</conditionalEventDefinition>
输入输出参数
通过Camunda inputOutput
扩展,你可以用表达式语言映射 inputParameter
或 outputParameter
。
在表达式中,一些特殊的变量是可用的,这些变量可以访问当前的上下文。要找到关于可用变量的更多信息,请参见变量章节。
下面的例子显示了一个输入参数 “inputParameter”,它使用表达式语言来调用一个bean的方法。
<serviceTask id="task" camunda:class="org.camunda.bpm.example.SumDelegate">
<extensionElements>
<camunda:inputOutput>
<camunda:inputParameter name="x">
${myBean.calculateX()}
</camunda:inputParameter>
</camunda:inputOutput>
</extensionElements>
</serviceTask>
外部任务错误处理
外部任务可以定义 camunda:errorEventDefinition元素,可以用JUEL表达式提供。该表达式在ExternalTaskService#complete
和ExternalTaskService#handleFailure
时被计算。如果表达式结果为 “true”,就会抛出一个BPMN错误,这个错误可以被错误边界事件捕获。
在外部任务的范围内,表达式可以通过key externalTask
对象访问ExternalTaskEntity
,它为 “errorMessage”、”errorDetails”、”workerId”、”retries” 等提供getter方法。
案例:
下面的例子展示了如何访问外部任务对象:
<bpmn:serviceTask id="myExternalTaskId" name="myExternalTask" camunda:type="external" camunda:topic="myTopic">
<bpmn:extensionElements>
<camunda:errorEventDefinition id="myErrorEventDefinition" errorRef="myError" expression="${externalTask.getWorkerId() == 'myWorkerId'}" />
</bpmn:extensionElements>
</bpmn:serviceTask>
如何匹配一个错误信息:
<bpmn:serviceTask id="myExternalTaskId" name="myExternalTask" camunda:type="external" camunda:topic="myTopic">
<bpmn:extensionElements>
<camunda:errorEventDefinition id="myErrorEventDefinition" errorRef="myError" expression="${externalTask.getErrorDetails().contains('myErrorMessage')}" />
</bpmn:extensionElements>
</bpmn:serviceTask>
关于外部任务背景下错误事件定义功能的进一步细节,请查阅外部任务指南.
Value
很多的BPMN和CMMN元素允许通过表达式指定其内容或属性值。请参阅参考文献中BPMN和CMMN的相应章节,以了解更详细的例子。
表达式语言内变量与函数
流程变量
当前范围内的所有流程变量在表达式中都可以直接使用。所以条件序列流可以直接检查一个变量的值:
<sequenceFlow>
<conditionExpression xsi:type="tFormalExpression">
${test == 'start'}
</conditionExpression>
</sequenceFlow>
内置环境变量
根据当前的执行环境,在计算表达式时,可以使用特殊的内置环境变量:
Variable | Java Type | Context |
---|---|---|
execution |
DelegateExecution
|
Available in a BPMN execution context like a service task, execution listener or sequence flow. |
task |
DelegateTask
|
Available in a task context like a task listener. |
externalTask |
ExternalTask
|
Available during an external task context activity (e.g. in camunda:errorEventDefinition expressions). |
caseExecution |
DelegateCaseExecution
|
Available in a CMMN execution context. |
authenticatedUserId |
String |
The id of the currently authenticated user. Only returns a value if the id of the currently
authenticated user has been set through the corresponding methods of the
IdentityService . Otherwise it returns null .
|
以下示例展示了,将变量test
设置为执行侦听器的当前事件名称的表达式;
<camunda:executionListener event="start"
expression="${execution.setVariable('test', execution.eventName)}" />
从 Spring 和 CDI 的外部上下文中获取外部变量
如果流程引擎与 Spring 或 CDI 集成,则可以在表达式中访问 Spring 和 CDI Bean。请参阅 Spring 和 CDI 的相应章节以了解更多信息。下面的例子显示了一个实现了 “JavaDelegate “接口的Bean作为委托表达式的用法。
<serviceTask id="task1" camunda:delegateExpression="${myBean}" />
With the expression attribute any method of a bean can be called.
<serviceTask id="task2" camunda:expression="${myBean.myMethod(execution)}" />
内置上下文
在对表达式进行评估时,可以使用以下内置上下文函数:
Function | Return Type | Description |
---|---|---|
currentUser() |
String |
Returns the user id of the currently authenticated user or null no user is authenticated at the moment.
|
currentUserGroups() |
List of Strings |
Returns a list of the group ids of the currently authenticated user or null if no user is authorized at the moment.
|
now() |
Date |
Returns the current date as a Java Date object. |
dateTime() |
DateTime |
Returns a Joda-Time DateTime object of the current date. Please see the Joda-Time documentation for all available functions. |
下面的例子将一个用户任务的到期日设置为任务创建3天后:
<userTask id="theTask" name="Important task" camunda:dueDate="${dateTime().plusDays(3).toDate()}"/>
Camunda Spin 内置的方法
如果激活了Camunda Spin流程引擎插件,Spin函数S
、XML
和JSON
在表达式中也可用。参见数据格式部分了解详情。
<serviceTask id="task" camunda:expression="${XML(xml).attr('test').value()}" resultVariable="test" />