精华内容
下载资源
问答
  • activiti中task监听器

    2017-08-29 10:09:41
    activiti中task监听器activiti:delegateExpression使用的spring初始化的bean 会报couldn't serializ,然后我将我全部引用的类序列化,但是最后报到spring内部的类没有序列化,这我就没辙了,我猜我做法应该是错的...
  • ----------------------接口   1级 事件 异常事件   2级 事件的子接口(活动事件 取消事件 序列流事件 变量事件 实体事件 会员事件) ...3级 活动事件的子接口 (消息活动事件 信号活动事件 取消活动事件 错误活动...

    ----------------------接口

     

    1级  事件   异常事件  

     

    2级  事件的子接口(活动事件  取消事件  序列流事件  变量事件  实体事件  会员事件)

     

     

    3级  活动事件的子接口 (消息活动事件  信号活动事件 取消活动事件 错误活动事件)

     

    3级  取消事件的子接口(取消活动事件)

     

     

    3级  实体事件的子接口(与变量相关的实体事件)

     

     

    ------------实现类

     

    1级   事件

     

    2级   事件的子类(活动事件 实体事件  实体异常事件 会员事件  流程取消事件 序列流事件 变量事件)

     

     

    3级   活动事件的子类(取消活动事件 错误活动事件 消息活动事件  信号活动事件)

     

     

    3级  实体事件的子类(与变量相关的实体事件)

     

     

     

     

    ------------------事件创建者ActivitiEventBuilder

     

    ------------------事件调度者ActivitiEventDispatcherImpl

     

    ------------------事件支持者ActivitiEventSupport

    展开全文
  • Activiti中的事件监听

    千次阅读 2019-08-14 14:47:12
    其默认的事件监听接口:org.activiti.engine.delegate.event.ActivitiEventListener 事件类型:org.activiti.engine.delegate.event.ActivitiEventType,事件类型是一个枚举类型,其中包含了42种类型 public enum...

    工作流程事件监听可用于任务提醒、超时提醒等的模块的设计。

    其默认的事件监听接口:org.activiti.engine.delegate.event.ActivitiEventListener

    事件类型:org.activiti.engine.delegate.event.ActivitiEventType,事件类型是一个枚举类型,其中包含了42种类型

    public enum ActivitiEventType {
        ENTITY_CREATED,                            //创建了一个新实体。实体包含在事件中。
        ENTITY_INITIALIZED,                        //创建了一个新实体,初始化也完成了。如果这个实体的创建会包含子实体的创建,这个事件会在子实体都创建/初始化完成后被触发,这是与ENTITY_CREATED的区别。
        ENTITY_UPDATED,                            //更新了已存在的实体。实体包含在事件中。
        ENTITY_DELETED,                            //删除了已存在的实体。实体包含在事件中。
        ENTITY_SUSPENDED,                          //暂停了已存在的实体。实体包含在事件中。会被ProcessDefinitions, ProcessInstances 和 Tasks抛出。
        ENTITY_ACTIVATED,                          //激活了已存在的实体,实体包含在事件中。会被ProcessDefinitions, ProcessInstances 和 Tasks抛出。
        TIMER_SCHEDULED,
        TIMER_FIRED,                               //触发了定时器。job包含在事件中。
        JOB_CANCELED,                              //取消了一个作业。事件包含取消的作业。作业可以通过API调用取消,   任务完成后对应的边界定时器也会取消,在新流程定义发布时也会取消。
        JOB_EXECUTION_SUCCESS,                     //作业执行成功。job包含在事件中。
        JOB_EXECUTION_FAILURE,                     //作业执行失败。作业和异常信息包含在事件中。
        JOB_RETRIES_DECREMENTED,                   //因为作业执行失败,导致重试次数减少。作业包含在事件中。
        CUSTOM,
        ENGINE_CREATED,                            //监听器监听的流程引擎已经创建完毕,并准备好接受API调用。
        ENGINE_CLOSED,                             //监听器监听的流程引擎已经关闭,不再接受API调用。
        ACTIVITY_STARTED,                          //一个节点开始执行
        ACTIVITY_COMPLETED,                        //一个节点成功结束
        ACTIVITY_CANCELLED,
        ACTIVITY_SIGNALED,                         //一个节点收到了一个信号
        ACTIVITY_COMPENSATE,                       //一个节点将要被补偿。事件包含了将要执行补偿的节点id。
        ACTIVITY_MESSAGE_WAITING,
        ACTIVITY_MESSAGE_RECEIVED,                 //一个节点收到了一个消息。在节点收到消息之前触发。收到后,会触发ACTIVITY_SIGNAL或ACTIVITY_STARTED,这会根据节点的类型(边界事件,事件子流程开始事件)
        ACTIVITY_ERROR_RECEIVED,                   //一个节点收到了一个错误事件。在节点实际处理错误之前触发。   事件的activityId对应着处理错误的节点。 这个事件后续会是ACTIVITY_SIGNALLED或ACTIVITY_COMPLETE, 如果错误发送成功的话。
        HISTORIC_ACTIVITY_INSTANCE_CREATED,
        HISTORIC_ACTIVITY_INSTANCE_ENDED,
        SEQUENCEFLOW_TAKEN,
        UNCAUGHT_BPMN_ERROR,                       //抛出了未捕获的BPMN错误。流程没有提供针对这个错误的处理器。   事件的activityId为空。
        VARIABLE_CREATED,                          //创建了一个变量。事件包含变量名,变量值和对应的分支或任务(如果存在)。
        VARIABLE_UPDATED,                          //更新了一个变量。事件包含变量名,变量值和对应的分支或任务(如果存在)。
        VARIABLE_DELETED,                          //删除了一个变量。事件包含变量名,变量值和对应的分支或任务(如果存在)。
        TASK_CREATED,                              //创建了新任务。它位于ENTITY_CREATE事件之后。当任务是由流程创建时,     这个事件会在TaskListener执行之前被执行。
        TASK_ASSIGNED,                             //任务被分配给了一个人员。事件包含任务。
        TASK_COMPLETED,                            //任务被完成了。它会在ENTITY_DELETE事件之前触发。当任务是流程一部分时,事件会在流程继续运行之前,   后续事件将是ACTIVITY_COMPLETE,对应着完成任务的节点。
        PROCESS_STARTED,                           //流程启动
        PROCESS_COMPLETED,                         //流程已结束。在最后一个节点的ACTIVITY_COMPLETED事件之后触发。 当流程到达的状态,没有任何后续连线时, 流程就会结束。
        PROCESS_COMPLETED_WITH_ERROR_END_EVENT,
        PROCESS_CANCELLED,
        HISTORIC_PROCESS_INSTANCE_CREATED,
        HISTORIC_PROCESS_INSTANCE_ENDED,
        MEMBERSHIP_CREATED,                        //用户被添加到一个组里。事件包含了用户和组的id。
        MEMBERSHIP_DELETED,                        //用户被从一个组中删除。事件包含了用户和组的id。
        MEMBERSHIPS_DELETED;                       //所有成员被从一个组中删除。在成员删除之前触发这个事件,所以他们都是可以访问的。   因为性能方面的考虑,不会为每个成员触发单独的MEMBERSHIP_DELETED事件。
    
        ...
        ...
    }

     

    展开全文
  • Activiti用户指南详细介绍了启用和使用此功能的方法 。 在这篇文章,我将向您展示我们如何实现其最终实现以及它在幕后所做的事情。 当然,因为这是我通常的签名风格,所以我们还将对性能进行一些了解。 问题 ...

    activiti脚本任务

    最近的Activiti 5.21.0版本的突出特点之一是“安全脚本”。 Activiti用户指南中详细介绍了启用和使用此功能的方法 。 在这篇文章中,我将向您展示我们如何实现其最终实现以及它在幕后所做的事情。 当然,因为这是我通常的签名风格,所以我们还将对性能进行一些了解。

    问题

    长期以来,Activiti引擎一直支持脚本任务(和任务/执行侦听器)的脚本编写。 所使用的脚本在流程定义中定义,并且可以在部署流程定义后直接执行。 这是很多人喜欢的东西。 这与Java委托类或委托表达式有很大的不同,因为它们通常需要将实际的逻辑放在类路径上。 它本身已经引入了某种“保护”,因为高级用户通常只能这样做。

    但是,使用脚本不需要这种“额外步骤”。 如果您将脚本任务的功能提供给最终用户(并且我们从某些用户那里知道某些公司确实拥有此用例),那么所有的赌注都将大打折扣。 您可以通过执行流程实例来关闭JVM或执行恶意操作。

    第二个问题是编写一个无限循环且永无止境的脚本非常容易。 第三个问题是,脚本在执行时可以轻松使用大量内存,并占用大量系统资源。

    让我们来看入门的第一个问题。 首先,让我们添加最新和最大的Activiti引擎依赖性以及内存数据库库中的H2:

    <dependencies>
      <dependency>
        <groupId>org.activiti</groupId>
        <artifactId>activiti-engine</artifactId>
        <version>5.21.0</version>
      </dependency>
      <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
        <version>1.3.176</version>
      </dependency>
    </dependencies>

    我们将在这里使用的过程非常简单:只是一个开始事件,脚本任务和结束。 此处的过程并不是真正的重点,而是脚本执行。

    屏幕截图-自2016-06-13-201621

    我们将尝试的第一个脚本有两件事:它将获取并显示我的机器的当前网络配置(但显然有此想法的更危险的应用程序), 然后关闭整个JVM 。 当然,在适当的设置中,可以通过确保运行逻辑的用户在计算机上没有任何重要权限(但不能解决占用资源的问题)来缓解其中的某些问题。 但是我认为这很好地说明了为什么向几乎任何人提供脚本的功能在安全性方面确实很糟糕。

    <scriptTask id="myScriptTask" scriptFormat="javascript">
      <script>
        var s = new java.util.Scanner(java.lang.Runtime.getRuntime().exec("ifconfig").getInputStream()).useDelimiter("\\A");
        var output = s.hasNext() ? s.next() : "";
        java.lang.System.out.println("--- output = " + output);
        java.lang.System.exit(1);
      </script>
    </scriptTask>

    让我们部署流程定义并执行流程实例:

    public class Demo1 {
    
        public static void main (String[] args) {
    
            // Build engine and deploy
            ProcessEngine processEngine = new StandaloneInMemProcessEngineConfiguration().buildProcessEngine();
            RepositoryService repositoryService = processEngine.getRepositoryService();
            repositoryService.createDeployment().addClasspathResource("process.bpmn20.xml").deploy();
    
            // Start process instance
            RuntimeService runtimeService = processEngine.getRuntimeService();
            runtimeService.startProcessInstanceByKey("myProcess");
        }
    }

    给出以下输出(此处缩短):

    —输出= eth0链接encap:以太网
    inet地址:192.168.0.114广播:192.168.0.255掩码:255.255.255.0
    … 流程以退出代码1完成

    它输出有关我所有网络接口的信息,然后关闭整个JVM。 是的。 太恐怖了

    尝试纳斯霍恩

    第一个问题的解决方案是,我们需要将要在脚本中公开的内容列入白名单,并且默认情况下将所有内容都列入黑名单。 这样,用户将无法运行任何可以做恶意事情的类或方法。

    在Activiti中,当javascript脚本任务是流程定义的一部分时,我们使用JDK中的ScriptEngine类将此脚本提供给JDK中嵌入的javascript引擎。 在JDK 6/7中是Rhino,在JDK 8中是Nashorn。 我首先进行了认真的搜索,以找到Nashorn的解决方案(因为这将更加适用于未来)。 Nashorn确实具有“类过滤器”概念,可以有效地实施白名单。 但是,ScriptEngine抽象没有任何工具可以实际调整或配置Nashorn引擎。 我们必须做一些底层的魔术才能使其正常工作。

    代替使用默认的Nashorn脚本引擎,我们自己在“ SecureScriptTask”(这是常规的JavaDelegate)中实例化Nashorn脚本引擎。 注意使用jdk.nashorn。*包的用法–不太好。 我们遵循https://docs.oracle.com/javase/8/docs/technotes/guides/scripting/nashorn/api.html中的文档,通过在Nashorn引擎中添加“ ClassFilter”来使脚本执行更加安全。 这实际上是可以在脚本中使用的已批准类的白名单。

    public class SafeScriptTaskDemo2 implements JavaDelegate {
    
        private Expression script;
    
        public void execute(DelegateExecution execution) throws Exception {
            NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
            ScriptEngine scriptEngine = factory.getScriptEngine(new SafeClassFilter());
    
            ScriptingEngines scriptingEngines = Context
                    .getProcessEngineConfiguration()
                    .getScriptingEngines();
    
            Bindings bindings = scriptingEngines.getScriptBindingsFactory().createBindings(execution, false);
            scriptEngine.eval((String) script.getValue(execution), bindings);
    
            System.out.println("Java delegate done");
        }
    
        public static class SafeClassFilter implements ClassFilter {
    
            public boolean exposeToScripts(String s) {
                return false;
            }
    
        }
    
    }

    当执行时,上面的脚本将不会执行,将引发一个异常,指出“主线程”中的异常java.lang.RuntimeException:java.lang.ClassNotFoundException:java.lang.System.out.println”。

    请注意,ClassFilter仅可从JDK 1.8.0_40获得(相当近期!)。

    但是,这不能解决无限循环的第二个问题。 让我们执行一个简单的脚本:

    while (true) {
      print("Hello");
    }

    您可以猜测会做什么。 这将永远运行。 如果幸运的话,在脚本任务在事务中执行时,事务超时将发生。 但这远不是一个体面的解决方案,因为它浪费了CPU资源一段时间。

    使用大量内存的第三个问题也很容易证明:

    var array = []
    for(var i = 0; i < 2147483647; ++i) {
      array.push(i);
      java.lang.System.out.println(array.length);
    }

    启动流程实例时,内存将快速填满(仅以几个MB开头):

    屏幕截图-自2016-06-13-204745

    并最终以OutOfMemoryException: 线程“ main” java.lang.OutOfMemoryError:超出GC开销限制结束

    切换到犀牛

    在以下示例与上一个示例之间,花费了大量时间使Nashorn以某种方式拦截或应对无限循环/内存使用情况。 但是,经过大量搜索和试验后,似乎这些功能在Nashorn中还不是(还?)。 快速搜索将告诉您,我们不是唯一寻求解决方案的人。 通常,人们提到Rhino确实具有解决此问题的功能。

    例如,在JDK <8中,Rhino javascript引擎具有'instructionCount'回调机制,Nashorn中不存在。 它基本上为您提供了一种在回叫中执行逻辑的方法,该回叫被每x条指令( 字节码指令!)自动调用。 我首先尝试(并且浪费了很多时间)用Nashorn模仿指令计数的想法,例如,首先美化脚本(因为人们可以将整个脚本写在一行上),然后在脚本中注入一行代码来触发回调。 但是,那是1)做起来不是很简单2)一个人仍然可以在无限运行/使用大量内存的一行上写一条指令。

    搜索被困在那里,导致我们找到了Mozilla的Rhino引擎 。 自从很久以前就将其包含在JDK中以来,它实际上已经进一步发展了,而JDK中的版本并未进行这些更改! 阅读了(相当稀疏的)Rhino文档后,很明显Rhino在我们的用例方面似乎具有更丰富的功能。

    Nashorn的ClassFilter与Rhino中的“ ClassShutter”概念匹配。 使用Rhino的回调机制解决了cpu和内存问题:您可以定义一个称为x指令的回调。 这意味着一行可能是数百个字节代码指令,并且每x条指令我们都会得到一个回调……。 在执行脚本时,它非常适合监视我们的cpu和内存使用情况。

    如果您对我们在代码中实现这些想法感兴趣, 请在此处查看

    这确实意味着无论您使用什么JDK版本,都不会使用嵌入式javascript引擎,而会一直使用Rhino。

    尝试一下

    要使用新的安全脚本功能,请添加以下依赖关系:

    <dependency>
      <groupId>org.activiti</groupId>
      <artifactId>activiti-secure-javascript</artifactId>
      <version>5.21.0</version>
    </dependency>

    这将暂时包括Rhino引擎。 这还将启用SecureJavascriptConfigurator ,在创建流程引擎之前需要对其进行配置:

    SecureJavascriptConfigurator configurator = new SecureJavascriptConfigurator()
      .setWhiteListedClasses(new HashSet<String>(Arrays.asList("java.util.ArrayList")))
      .setMaxStackDepth(10)
      .setMaxScriptExecutionTime(3000L)
      .setMaxMemoryUsed(3145728L)
      .setNrOfInstructionsBeforeStateCheckCallback(10);
    
    ProcessEngine processEngine = new StandaloneInMemProcessEngineConfiguration()
      .addConfigurator(configurator)
      .buildProcessEngine();

    这会将安全脚本配置为

    • 每10条指令,检查一次CPU执行时间和内存使用情况
    • 给脚本3秒3MB的执行时间
    • 将堆栈深度限制为10(以避免递归)
    • 将数组列表公开为可以在脚本中安全使用的类

    从上方运行试图读取ifconfig并关闭JVM的脚本会导致:

    TypeError:无法在对象[JavaPackage java.lang.Runtime]中调用属性getRuntime。 它不是功能,而是“对象”。

    从上面运行无限循环脚本可以得到

    线程“主” java.lang.Error中的异常:最大variableScope时间超过了3000 ms

    从上面运行内存使用脚本可以

    线程“主” java.lang.Error中的异常:内存限制达到3145728字节

    和欢呼! 解决了上面定义的问题

    性能

    我做了一个非常不科学的快速检查……我几乎不敢分享它,因为结果违背了我的设想。

    我创建了一个快速主程序,该主程序运行带有脚本任务的流程实例10000次:

    public class PerformanceUnsecure {
    
        public static void main (String[] args) {
    
            ProcessEngine processEngine = new StandaloneInMemProcessEngineConfiguration().buildProcessEngine();
    
            RepositoryService repositoryService = processEngine.getRepositoryService();
            repositoryService.createDeployment().addClasspathResource("performance.bpmn20.xml").deploy();
    
            Random random = new Random();
    
            RuntimeService runtimeService = processEngine.getRuntimeService();
    
            int nrOfRuns = 10000;
            long total = 0;
    
            for (int i=0; i<nrOfRuns; i++) {
                Map<String, Object> variables = new HashMap<String, Object>();
                variables.put("a", random.nextInt());
                variables.put("b", random.nextInt());
                long start = System.currentTimeMillis();
                runtimeService.startProcessInstanceByKey("myProcess", variables);
                long end = System.currentTimeMillis();
                total += (end - start);
            }
            System.out.println("Finished process instances : " + processEngine.getHistoryService().createHistoricProcessInstanceQuery().count());
            System.out.println("Total time = " + total + " ms");
            System.out.println("Avg time/process instance = " + ((double)total/(double)nrOfRuns) + " ms");
        }
    
    }

    流程定义只是一个开始->脚本任务->结束。 脚本任务只是将变量添加到变量中,然后将结果保存在第三个变量中。

    <scriptTask id="myScriptTask" scriptFormat="javascript">
      <script>
        var c = a + b;
        execution.setVariable('c', c);
      </script>
    </scriptTask>

    我运行了五次,平均每个进程实例为2.57毫秒。 这是在最近的JDK 8(所以是Nashorn)上。

    然后,我切换了上面的前两行以使用新的安全脚本,从而切换到Rhino并启用了安全功能:

    SecureJavascriptConfigurator configurator = new SecureJavascriptConfigurator()
      .addWhiteListedClass("org.activiti.engine.impl.persistence.entity.ExecutionEntity")
      .setMaxStackDepth(10)
      .setMaxScriptExecutionTime(3000L)
      .setMaxMemoryUsed(3145728L)
      .setNrOfInstructionsBeforeStateCheckCallback(1);
    
    ProcessEngine processEngine = new StandaloneInMemProcessEngineConfiguration()
      .addConfigurator(configurator)
      .buildProcessEngine();

    再次进行了五次运行……并获得了1.07毫秒/流程实例。 这是同一件事的两倍以上

    当然,这不是一个真正的考验。 我以类白名单检查和回调为前提,假设Rhino的执行速度会变慢,但是没有这种事情。 也许这种特殊情况更适合Rhino……如果有人可以解释,请发表评论。 但这仍然是一个有趣的结果。

    结论

    如果您在流程定义中使用脚本,请仔细阅读引擎中的此新安全脚本功能。 由于这是一项新功能,非常欢迎反馈和改进!

    翻译自: https://www.javacodegeeks.com/2016/06/secure-scripting-activiti-works.html

    activiti脚本任务

    展开全文
  • Activiti中TaskListener接口的使用

    ##TaskListener可以用来分配个人任务,使用方式如下

    1、定义一个实现TaskListener的类,并实现notify()方法,指定下一任务处理人
    示例:
    public class TaskListenerImpl implements TaskListener {

    /** 用来指定任务的办理人 */
    @Override
    public void notify(DelegateTask delegateTask) {
    	System.out.println("参数:" + delegateTask.getVariables().get("v1"));
    	// 下一任务的处理人,可以从流程变量中获取,delegateTask封装了流程变量和当前任务的信息
    	delegateTask.setAssignee("A");
    }
    

    }
    2、创建流程图的时候,设置如下:
    在这里插入图片描述
    3

    展开全文
  • activiti中的bug列表

    万次阅读 2016-11-21 17:30:42
    Improvements to the Activiti Modeler with terminate end events, cancel event and transaction support, and more intermediate catch and throw event support. Also, improvements to interrupting and non-...
  • activiti

    2020-08-04 20:56:50
    Activiti5是在2010年5月17日发布的业务流程管理(BPM)框架,它是覆盖了业务流程管理、工作流、服务协作等领域的一个开源的、灵活的、易扩展的可执行流程语言框架。Activiti基于Apache许可的开源BPM平台,它特色是...
  • Activiti用户指南详细介绍了启用和使用此功能的方法 。 在这篇文章,我将向您展示我们如何实现其最终实现以及它在幕后所做的事情。 当然,由于这是我通常的签名风格,因此我们还将对性能进行一些了解。 问题 ...
  • Activiti中ServiceTask的java服务任务

    千次阅读 2019-02-18 16:00:47
    activiti.cfg.xml内容: &lt;?xml version="1.0"?&gt; &lt;beans default-lazy-init="false" xsi:schemaLocation=" http://www.springframework.o...
  • activiti 涉及的内容

    2018-09-29 09:56:00
    1 JAVA 委派模式(Delegate) ... 2 Activiti中activiti:expression和activiti:delegateExpression有什么区别? 答:以serviceTask为例,delegateExpression是引用一个JavaDelegat...
  • 比较Activiti中三种不同的表单及其应用

    万次阅读 多人点赞 2014-09-17 08:36:07
    http://www.kafeitu.me/activiti/2012/08/05/diff-activiti-workflow-forms.html
  • activiti 的一些信息

    2015-02-15 13:57:00
    activiti 的service  1. script task 执行脚本任务(java自身脚本不在此列 如需关注看 javaservice) scriptFormat  : 1. javascript(JDK 自带的脚步解析特性) 虽然早就知道 但是还未去看过 2. ...
  • Activiti

    千次阅读 2017-05-01 21:58:37
    关于学习Activiti的过程:直接使用官方文档进行学习,希望会有好...了解一个大概,在这其中可以看看随意别人博客写的对Activiti的理解。 二.进入学习: 介绍ProcessEngineConfiguration的初始化,首先可以将其写为...
  • Activiti中三种不同的表单及其应用

    千次阅读 2016-03-11 13:48:49
    这个恐怕是初次接触工作流最多的话题之一了,当然这个不是针对Activiti来说的,每个工作流引擎都会支持多种方式的表单。目前大家讨论到的大概有三种。 动态表单外置表单普通表单 具体选择哪种方式只能读者根据...
  • activiti java service task 服务任务

    千次阅读 2018-08-20 10:06:27
    java 服务任务 有三种实现...2. activiti:delegateExpression 也要实现上面两个类 3. activiti:expression 直接调用javaBean 第一种方式在前面博客已经实现过了,这里实现一下2和3这两个方式 activiti:delegat...
  • activiti中的设计器汉化问题

    千次阅读 2016-09-01 14:17:36
    "http://www.activiti.org/processdef" ,    "description"  :  "工作流目标命名空间" ,    "popular"  :  false    } ]   }, {    "name"  :  "usertaskbase" ,    "properties"  : [ {  ...
  • 今天在利用activiti进行接口开发的时候发现底层代码抛出的错误被activiti进行了进一步的封装成了runtimeException,而主动抛出的错误信息整体被作为runtimeException的detailMessage信息进行保存。经过研究发现实际...
  • (该类需实现org.activiti.engine.delegate.ExecutionListener 接口) 列子代码: public class MyTaskListener implements TaskListener {     private static final long ...
  • Activiti 监听器的配置使用

    万次阅读 2014-08-24 00:30:15
    (BC内部开发文档资料)一)流程监听器的配置 此监听器的作用是记录流程的... 用Activiti Designer打开流程图,点击空白处,在Properties的Listeners如下配置流程的start和end两个事件: 二)任务监听器的配置 此

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,054
精华内容 421
关键字:

activiti中delegate