リスナーリスナーには、次の3つのタイプがあります。JavaDelegateTaskListener ExecutionListener
ユーザータスク(UserTask)のリスナーはTaskListenerです
Javaサービスタスク(JavaServiceTask)のリスナーはJavaDelegateです
他のサービスのリスナーはExecutionListenerです
TaskListenerのパラメーター(DelegateTask)はuserTaskに関するものです
JavaDelegateおよびExecutionListenerパラメーター(DelegateExecution)はプロセスに関するものです
リスナーを使用するには、次の3つの方法があります。
1.次のように、クラスのメソッドを直接使用します。
activiti:class = "org.activiti.examples.bpmn.servicetask.ToUpperCaseFieldInjected"
2.式メソッドを使用します(このメソッドはテストされておらず、後で追加されます)
activiti:expression $ {genderBean.getGenderString(gender)} </ activiti:expression>
3.delegateExpressionメソッドを使用します
activiti:delegateExpression = "$ {someJavaDelegateBean}"
このメソッドはBeanを使用してクラスを検索します。SomeJavaDelegateBeanはBeanです。たとえば、プロジェクトはSpringによって管理され、@ Service( "someJavaDelegateBean")をリスナークラスに直接追加できます。
このようにして、スプリングとシームレスに接続でき、カスタムサービスを注入できないという問題も解決できます。最初の方法は、カスタムサービスをサービスに挿入することです; @Autowired
filedNameを使用する3つの方法
最初:
<activiti:field name="text" stringValue="Hello World" />
public class ToUpperCaseFieldInjected implements JavaDelegate {
private Expression text;
public void execute(DelegateExecution execution) {
execution.setVariable("var", ((String)text.getValue(execution)).toUpperCase());
}
}
复制代码
第二种: 普通字符文本
<extensionElements>
<activiti:field name="text">
<activiti:string>
This is a long string with a lot of words and potentially way longer even!
</activiti:string>
</activiti:field>
</extensionElements>
复制代码
第三种: 较长文本,比如邮件;
<serviceTask id="javaService" name="Java service invocation"
activiti:class="org.activiti.examples.bpmn.servicetask.ReverseStringsFieldInjected">
<extensionElements>
<activiti:field name="text1">
<activiti:expression>${genderBean.getGenderString(gender)}</activiti:expression>
</activiti:field>
<activiti:field name="text2">
<activiti:expression>Hello ${gender == 'male' ? 'Mr.' : 'Mrs.'} ${name}</activiti:expression>
</activiti:field>
</ extensionElements>
</ serviceTask>
复制代码
public class ReverseStringsFieldInjected implements JavaDelegate {
private Expression text1;
private Expression text2;
public void execute(DelegateExecution execution) {
String value1 = (String) text1.getValue(execution);
execution.setVariable("var1", new StringBuffer(value1).reverse().toString());
String value2 = (String) text2.getValue(execution);
execution.setVariable("var2", new StringBuffer(value2).reverse().toString());
}
}
复制代码
运行时动态注入的值,可以使用表达式,这种表达式可以使用流程变量,或是spring中定义的bean
上面为bpmn标签
如果监听器使用class的方式,那么需要在监听器中添加 private Expression text; // 名字需要和filedName一致 如果不加,则会抛出异常;
public class ToUpperCaseFieldInjected implements JavaDelegate {
private Expression text;
public void execute(DelegateExecution execution) {
execution.setVariable("var", ((String)text.getValue(execution)).toUpperCase());
}
}
复制代码
但是上面提到class的方式不能@autowired 会为null
activiti:delegateExpression这种方式可以@autowired,但是这种方式不能保证线程安全,那怎么改动呢?
首先我们需要知道:
delegateExpressionFieldInjectionMode参数(取org.activiti.engine.imp.cfg.DelegateExpressionFieldInjectionMode枚举中的值)
这个参数的可以进行设置;(包含以下三种)
DISABLED(禁用):当使用代理表达式时,完全禁用字段注入。不会再尝试进行字段注入。这是最安全的方式,保证线程安全。 COMPATIBILITY(兼容):在这个模式下,行为与5.21版本之前完全一样:可以在代理表达式中使用字段注入,如果代理类中没有定义该字段,会抛出异常。这是最不线程安全的模式,但可以保证历史版本兼容性,也可以在代理表达式只在一个任务中使用的时候(因此不会产生并发竞争条件),安全使用。 MIXED(混合):可以在使用代理表达式时注入,但当代理中没有定义字段时,不会抛出异常。这样可以在部分代理中使用注入(例如不是单例时),而在部分代理中不使用注入。
Activiti 5.x版本的默认模式为COMPATIBILITY(兼容)。 Activiti 6.x版本的默认模式为MIXED(混合)。
@Service("myJavaDelegate")
public class MyJavaDelegate implements JavaDelegate {
// Expression expression;
@Override
public void execute(DelegateExecution execution) {
Expression operationsLocal = DelegateHelper.getFieldExpression(execution, "operationsLocal");
execution.setVariable("operationsLocal",operationsLocal.getExpressionText());
}
}
复制代码
以上只是单例模式,如果是多例(scope=“prototype”)不需要这种方式
其中JavaServiceTask 中有一个activiti:resultVariable的标签
服务执行的返回值(仅对使用表达式的服务任务),可以通过为脚本任务定义的’activiti:resultVariable’属性设置流程变量名,指定为已经存在的,或者新的流程变量。指定的已有值的流程变量,会被服务执行的结果值覆盖。当不指定结果变量名时,服务执行的结果值将被忽略。