activiti监听器的使用总结

1,461 阅读3分钟

监听器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’属性设置流程变量名,指定为已经存在的,或者新的流程变量。指定的已有值的流程变量,会被服务执行的结果值覆盖。当不指定结果变量名时,服务执行的结果值将被忽略。