監聽器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’屬性設置流程變量名,指定爲已經存在的,或者新的流程變量。指定的已有值的流程變量,會被服務執行的結果值覆蓋。當不指定結果變量名時,服務執行的結果值將被忽略。