表达式语言
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" />