监听器listener
监听器分为三种:JavaDelegate TaskListener ExecutionListener
用户任务(UserTask)的监听器为TaskListener
Java服务任务(JavaServiceTask)的监听器为JavaDelegate
其他的服务的监听器为ExecutionListener
TaskListener中参数(DelegateTask)是有关于userTask的
JavaDelegate和ExecutionListener参数(DelegateExecution)是有关于流程的
使用监听器的方式有三种:
1.直接是用class的方式,如下标签
activiti:class=”org.activiti.examples.bpmn.servicetask.ToUpperCaseFieldInjected”
2.用expression的方式(这种方式还没有试验过,之后补充)
activiti:expression${genderBean.getGenderString(gender)}</activiti:expression>
3.用delegateExpression的方式
activiti:delegateExpression=”${someJavaDelegateBean}”
这种方式是利用bean进行查找类的,someJavaDelegateBean是bean,比如现在项目都是由spring管理的,可以在监听器的类上直接加上@Service(“someJavaDelegateBean”);
利用这种方式可以和spring进行无缝对接,也解决自定义的service无法注入的问题。第一种方式是服务自定注入自定义service的;@Autowired
filedName的用法三种方式
第一种:
<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’属性设置流程变量名,指定为已经存在的,或者新的流程变量。指定的已有值的流程变量,会被服务执行的结果值覆盖。当不指定结果变量名时,服务执行的结果值将被忽略。