Activiti手动执行的应用(UserTask)

工作流模拟某公司请假流程情景如下:
   1.开发人员请假流程,如果开发人员请假,如果请假天数小于3天,组长批准,人事批准即可请假。
   2.如果请假大约三天,需要项目经理或者产品经理批准,并且项目总监批准

流程图:

流程配置:

<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.activiti.org/test">
  <process id="UserExecuteTask" name="UserExecuteTask">
    <startEvent id="startevent1" name="Start"></startEvent>
    <parallelGateway id="parallelgateway1" name="多种请假方式"></parallelGateway>
    <userTask id="servicetask1" name="项目经理同意" >
       <extensionElements>
          <activiti:taskListener event="complete" class="com.easyway.workflow.activiti.gateway.DeveloperManagerUserTaskListener"/>
       </extensionElements>
    </userTask>
    <userTask id="servicetask2" name="产品经理同意">
       <extensionElements>
          <activiti:taskListener event="complete" class="com.easyway.workflow.activiti.gateway.ProductManagerUserTaskListener"/>
       </extensionElements>
    </userTask>
    <userTask id="servicetask3" name="项目组长同意" >
          <extensionElements>
          <activiti:taskListener event="complete" class="com.easyway.workflow.activiti.gateway.TeamLeaderUserTaskListener"/>
       </extensionElements>
    </userTask>
    <parallelGateway id="parallelgateway2" name="First Join"></parallelGateway>
    <userTask id="servicetask4" name="项目总监同意" >
       <extensionElements>
          <activiti:taskListener event="complete" class="com.easyway.workflow.activiti.gateway.ProductBossUserTaskListener"/>
       </extensionElements>
    </userTask>
    <parallelGateway id="parallelgateway3" name="人事判断"></parallelGateway>
    <userTask id="servicetask5" name="人事部门同意" >
        <extensionElements>
           <activiti:taskListener event="complete"  class="com.easyway.workflow.activiti.gateway.HumanResouceUserTaskListener"/>
        </extensionElements>
    </userTask>
    <endEvent id="endevent1" name="End"></endEvent>
    <sequenceFlow id="flow1" name="" sourceRef="startevent1" targetRef="parallelgateway1"></sequenceFlow>
    <sequenceFlow id="flow2" name="" sourceRef="parallelgateway1" targetRef="servicetask1"></sequenceFlow>
    <sequenceFlow id="flow3" name="" sourceRef="parallelgateway1" targetRef="servicetask2"></sequenceFlow>
    <sequenceFlow id="flow4" name="" sourceRef="parallelgateway1" targetRef="servicetask3"></sequenceFlow>
    <sequenceFlow id="flow5" name="" sourceRef="servicetask1" targetRef="parallelgateway2"></sequenceFlow>
    <sequenceFlow id="flow6" name="" sourceRef="servicetask2" targetRef="parallelgateway2"></sequenceFlow>
    <sequenceFlow id="flow7" name="" sourceRef="servicetask3" targetRef="parallelgateway3"></sequenceFlow>
    <sequenceFlow id="flow8" name="" sourceRef="parallelgateway2" targetRef="servicetask4"></sequenceFlow>
    <sequenceFlow id="flow9" name="" sourceRef="servicetask4" targetRef="parallelgateway3"></sequenceFlow>
    <sequenceFlow id="flow10" name="" sourceRef="parallelgateway3" targetRef="servicetask5"></sequenceFlow>
    <sequenceFlow id="flow11" name="" sourceRef="servicetask5" targetRef="endevent1"></sequenceFlow>
  </process>
</definitions>  

流程实现:

package com.easyway.workflow.activiti.gateway;  

import java.util.logging.Logger;
/**
 * execute方法的参数DelegateExecution execution可以在流程中各个结点之间传递流程变量。
 * <activiti:taskListener>元素的event属性,它一共包含三种事件:"create"、"assignment"、"complete",分别表示结点执行处理逻辑的时机为:在处理类实例化时、在结点处理逻辑被指派时、在结点处理逻辑执行完成时,可以根据自己的需要进行指定。
  *上述流程定义中,4个任务结点对应的处理类
  *
  *<activiti:taskListener>元素的event属性,它一共包含三种事件:"create"、"assignment"、"complete",分别表示结点执行处理逻辑的时机为:在处理类实例化时、在结点处理逻辑被指派时、在结点处理逻辑执行完成时,可以根据自己的需要进行指定。
  *
 *<userTask id="servicetask2" name="产品经理同意">
       <extensionElements>
          <activiti:taskListener event="complete" class="com.easyway.workflow.activiti.gateway.ProductManagerUserTaskListener"/>
       </extensionElements>
    </userTask>
 *
 *
 * 项目经理审批过程
 * @author longgangbai
 *
 *
 * 2011-12-17  下午07:45:47
 */
public class DeveloperManagerUserTaskListener implements TaskListener
{  

    private final Logger log = Logger.getLogger(DeveloperManagerUserTaskListener.class.getName());  

    /* (non-Javadoc)
     * @see org.activiti.engine.delegate.TaskListener#notify(org.activiti.engine.delegate.DelegateTask)
     */
    @Override
    public void notify(DelegateTask delegateTask) {
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        log.info("variavles=" + delegateTask.getVariables());
        delegateTask.setVariable("项目经理", "请假天数大约3天,同意请假。");
        log.info("项目经理,请假天数大约3天,同意请假。.");  

    }
}  
package com.easyway.workflow.activiti.gateway;  

import java.util.logging.Logger;
/**
  * execute方法的参数DelegateExecution execution可以在流程中各个结点之间传递流程变量。
 *
 *<activiti:taskListener>元素的event属性,它一共包含三种事件:"create"、"assignment"、"complete",分别表示结点执行处理逻辑的时机为:在处理类实例化时、在结点处理逻辑被指派时、在结点处理逻辑执行完成时,可以根据自己的需要进行指定。  

 *    <userTask id="servicetask5" name="人事部门同意" >
        <extensionElements>
           <activiti:taskListener event="complete"  class="com.easyway.workflow.activiti.gateway.HumanResouceUserTaskListener"/>
        </extensionElements>
    </userTask> 

 * 人事部门审批过程
 * @author longgangbai
 *
 * 2011-12-17  下午07:45:47
 */
public class HumanResouceUserTaskListener implements TaskListener {  

    private final Logger log = Logger.getLogger(HumanResouceUserTaskListener.class.getName());  

    /* (non-Javadoc)
     * @see org.activiti.engine.delegate.TaskListener#notify(org.activiti.engine.delegate.DelegateTask)
     */
    @Override
    public void notify(DelegateTask delegateTask) {
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        log.info("variavles=" + delegateTask.getVariables());
        delegateTask.setVariable("人事部门", "请假天数大约3天,同意请假。");
        log.info("人事部门 ,请假天数大约3天,同意请假。");  

    }
}  
package com.easyway.workflow.activiti.gateway;  

import java.util.logging.Logger;
/**
 *  execute方法的参数DelegateExecution execution可以在流程中各个结点之间传递流程变量。
 *
 *  <activiti:taskListener>元素的event属性,它一共包含三种事件:"create"、"assignment"、"complete",分别表示结点执行处理逻辑的时机为:在处理类实例化时、在结点处理逻辑被指派时、在结点处理逻辑执行完成时,可以根据自己的需要进行指定。  

 *  配置如下
 *    <userTask id="servicetask4" name="项目总监同意" >
       <extensionElements>
          <activiti:taskListener event="complete" class="com.easyway.workflow.activiti.gateway.ProductBossUserTaskListener"/>
       </extensionElements>
    </userTask>
 *
 *
 * 项目总监审批过程
 * @author longgangbai
 *
 * 2011-12-17  下午07:45:47
 */
public class ProductBossUserTaskListener implements TaskListener {  

    private final Logger log = Logger.getLogger(ProductBossUserTaskListener.class.getName());  

    /* (non-Javadoc)
     * @see org.activiti.engine.delegate.TaskListener#notify(org.activiti.engine.delegate.DelegateTask)
     */
    @Override
    public void notify(DelegateTask execution) {
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        log.info("variavles=" + execution.getVariables());
        execution.setVariable("项目总监", "请假天数大约3天,同意请假。");
        log.info("项目总监,请假天数大约3天,同意请假。");          

    }
}  
package com.easyway.workflow.activiti.gateway;  

import java.util.logging.Logger;
/**
  * execute方法的参数DelegateExecution execution可以在流程中各个结点之间传递流程变量。
  *
  * <activiti:taskListener>元素的event属性,它一共包含三种事件:"create"、"assignment"、"complete",分别表示结点执行处理逻辑的时机为:在处理类实例化时、在结点处理逻辑被指派时、在结点处理逻辑执行完成时,可以根据自己的需要进行指定。  

  *
  * 配置如下
 *    <userTask id="servicetask1" name="项目经理同意" >
       <extensionElements>
          <activiti:taskListener event="complete" class="com.easyway.workflow.activiti.gateway.DeveloperManagerUserTaskListener"/>
       </extensionElements>
    </userTask>
 * 产品经理审批过程
 * @author longgangbai
 *
 * 2011-12-17  下午07:45:47
 */
public class ProductManagerUserTaskListener implements TaskListener {  

    private final Logger log = Logger.getLogger(ProductManagerUserTaskListener.class.getName());  

    /* (non-Javadoc)
     * @see org.activiti.engine.delegate.TaskListener#notify(org.activiti.engine.delegate.DelegateTask)
     */
    @Override
    public void notify(DelegateTask execution) {
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        log.info("variavles=" + execution.getVariables());
        execution.setVariable("产品经理", "请假天数大约3天,同意请假。");
        log.info("产品经理,请假天数大约3天,同意请假。");      

    }
}  
package com.easyway.workflow.activiti.gateway;  

import java.util.logging.Logger;
/**
 *
 *
 * <activiti:taskListener>元素的event属性,它一共包含三种事件:"create"、"assignment"、"complete",分别表示结点执行处理逻辑的时机为:在处理类实例化时、在结点处理逻辑被指派时、在结点处理逻辑执行完成时,可以根据自己的需要进行指定。
 *
 *
 * 配置如下:
 *     <userTask id="servicetask3" name="项目组长同意" >
          <extensionElements>
          <activiti:taskListener event="complete" class="com.easyway.workflow.activiti.gateway.TeamLeaderUserTaskListener"/>
       </extensionElements>
    </userTask> 

 * 项目组长批准请假
 *    模拟当开发人员请假小于3天,组长比准
 * @author longgangbai
 *
 * 2011-12-17  上午09:07:37
 */
public class TeamLeaderUserTaskListener implements TaskListener {  

    private final Logger log = Logger.getLogger(TeamLeaderUserTaskListener.class.getName());  

    /* (non-Javadoc)
     * @see org.activiti.engine.delegate.TaskListener#notify(org.activiti.engine.delegate.DelegateTask)
     */
    @Override
    public void notify(DelegateTask execution) {
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        log.info("variavles=" + execution.getVariables());
        execution.setVariable("项目组长", "请假天数小于3天,同意请假。");
        log.info("项目组长,请假天数小于3天,同意请假。");
    }
}  
package com.easyway.workflow.activiti.gateway;  

import junit.framework.TestCase;
/**
 * 主要是在测试之前做一些初始化工作,主要包括流程引擎实例
 * 的构建,及其流程提供的基本服务。
 * 目的:让开发者熟悉工作流使用过程使用的几个步骤
 * 1.加载相关的工作流全局配置文件activiti.cfg.xml配置文件信息
 * 2.获取工作流相关的服务(RepositoryService,RuntimeService,
 *    TaskService,HistoryService,FormService,ManagementService,
 *    IdentityService等)
 * 2.加载工作流文件*.bpmn20.xml信息
 *
 * 3.部署工作流
 *    部署工作流由多种方式,在以后会相继讲解
 *
 * @author longgangbai
 *
 * 2011-12-17  下午07:48:59
 */
public abstract class AbstractTest extends TestCase {  

    private ProcessEngine processEngine;
    protected String deploymentId;
    protected RepositoryService repositoryService;
    protected RuntimeService runtimeService;
    protected TaskService taskService;
    protected FormService formService;
    protected HistoryService historyService;
    protected IdentityService identityService;
    protected ManagementService managementService;  

    /**
     * 测试用例开始初始化工作
     * 1.创建相关的工作流程对象ProcessEngine
     * 2.创建相关的服务
     * 3.
     */
    @Override
    protected void setUp() throws Exception {
        super.setUp();
        //由于ProcessEngine为线程安全性对象,整个项目可以共用一个
        if(processEngine==null) {
            //此处使用此种方法调用的activiti的配置文件为 classpath路径下的activiti.cfg.xml
            //采用的H2的数据库
            processEngine = ProcessEngines.getDefaultProcessEngine();
        }
        //获取工作流的各种服务信息
        repositoryService = processEngine.getRepositoryService();
        runtimeService = processEngine.getRuntimeService();
        taskService = processEngine.getTaskService();
        formService = processEngine.getFormService();
        historyService = processEngine.getHistoryService();
        identityService = processEngine.getIdentityService();
        managementService = processEngine.getManagementService();
        //调用扩展的初始化工作
        initialize();  

    }  

    /**
     * test销毁方法
     */
    @Override
    protected void tearDown() throws Exception {
        super.tearDown();
        destroy();
    }  

    /**
     * 便于子类的工作的初始化的扩展工作
     *
     *
     * @throws Exception
     */
    protected abstract void initialize() throws Exception;
    /**
     * 便于子类的工作的销毁的扩展工作
     *
     * @throws Exception
     */
    protected abstract void destroy() throws Exception;
}  
/**
package com.easyway.workflow.activiti.gateway;
import java.util.Date;
/**
 * 测试实例如下
 *
 * @author longgangbai
 *
 * 2011-12-18  上午12:00:03
 */
public class ParallelGatewayTest extends AbstractTest {
    private String deploymentId;
    private Date start = null;
    private Date end = null;   

    @Override
    protected void initialize() throws Exception {
        deploymentId = repositoryService.createDeployment()
        .addClasspathResource("diagrams/UserExecuteTask.bpmn20.xml")
        .deploy().getId();
    }   

    @Override
    protected void destroy() throws Exception {
            repositoryService.deleteDeployment(deploymentId, true);
    }   

    @Deployment
    public void testUnbalancedForkJoin() {
        //获取流程实例对象
        ProcessInstance pi = runtimeService.startProcessInstanceByKey("UserExecuteTask");
        //获取任务服务对象的查询
        TaskQuery query = taskService.createTaskQuery().processInstanceId(pi.getId()).orderByTaskName().asc();
       //获取所有的任务
        List<Task> tasks = query.list();
        assertEquals(3, tasks.size());
        start = new Date();   

        for(Task task : tasks) {
            //执行任务
            taskService.complete(task.getId());
            System.out.println("name =+"+task.getName());
            end = new Date();
            System.out.println("" + (end.getTime()-start.getTime()) + "ms.");
        }
        //查询任务
        tasks = query.list();
        assertEquals(1, tasks.size());
        for(Task task : tasks) {
            taskService.complete(task.getId());
            System.out.println("name =+"+task.getName());
            end = new Date();
            System.out.println("" + (end.getTime()-start.getTime()) + "ms.");
        }
        end = new Date();
        System.out.println("" + (end.getTime()-start.getTime()) + "ms.");
    }
}  

运行结果:

2011-12-18 13:15:29 org.activiti.engine.ProcessEngines initProcessEnginFromResource
信息: initializing process engine for resource jar:file:/C:/activiti-rest/activiti-cfg.jar!/activiti.cfg.xml
2011-12-18 13:15:32 org.activiti.engine.impl.ProcessEngineImpl <init>
信息: ProcessEngine default created
2011-12-18 13:15:32 org.activiti.engine.ProcessEngines initProcessEnginFromResource
信息: initialised process engine default
2011-12-18 13:15:32 org.activiti.engine.impl.jobexecutor.JobAcquisitionThread run
信息: JobAcquisitionThread starting to acquire jobs
2011-12-18 13:15:32 org.activiti.engine.impl.bpmn.deployer.BpmnDeployer deploy
信息: Processing resource diagrams/UserExecuteTask.bpmn20.xml
2011-12-18 13:15:33 org.activiti.engine.impl.bpmn.parser.BpmnParse parseDefinitionsAttributes
信息: XMLSchema currently not supported as typeLanguage
2011-12-18 13:15:33 org.activiti.engine.impl.bpmn.parser.BpmnParse parseDefinitionsAttributes
信息: XPath currently not supported as expressionLanguage
2011-12-18 13:15:43 com.easyway.workflow.activiti.gateway.ProductManagerUserTaskListener notify
信息: variavles={}
2011-12-18 13:15:43 com.easyway.workflow.activiti.gateway.ProductManagerUserTaskListener notify
信息: 产品经理,请假天数大约3天,同意请假。
name =+产品经理同意
10094ms.
2011-12-18 13:15:53 com.easyway.workflow.activiti.gateway.TeamLeaderUserTaskListener notify
信息: variavles={产品经理=请假天数大约3天,同意请假。}
2011-12-18 13:15:53 com.easyway.workflow.activiti.gateway.TeamLeaderUserTaskListener notify
信息: 项目组长,请假天数小于3天,同意请假。
name =+项目组长同意
20172ms.
2011-12-18 13:16:03 com.easyway.workflow.activiti.gateway.DeveloperManagerUserTaskListener notify
信息: variavles={项目组长=请假天数小于3天,同意请假。, 产品经理=请假天数大约3天,同意请假。}
2011-12-18 13:16:03 com.easyway.workflow.activiti.gateway.DeveloperManagerUserTaskListener notify
信息: 项目经理,请假天数大约3天,同意请假。.
name =+项目经理同意
30313ms.
2011-12-18 13:16:13 com.easyway.workflow.activiti.gateway.ProductBossUserTaskListener notify
信息: variavles={项目组长=请假天数小于3天,同意请假。, 项目经理=请假天数大约3天,同意请假。, 产品经理=请假天数大约3天,同意请假。}
2011-12-18 13:16:13 com.easyway.workflow.activiti.gateway.ProductBossUserTaskListener notify
信息: 项目总监,请假天数大约3天,同意请假。
name =+项目总监同意
40485ms.
40485ms.  

原文地址:https://www.cnblogs.com/liaojie970/p/8976051.html

时间: 2024-10-11 17:45:56

Activiti手动执行的应用(UserTask)的相关文章

crontab执行脚本中文乱码,手动执行没有问题

crontab执行脚本中文乱码,手动执行没有问题 产生原因:       这是因为Unix/Linux下使用crontab时的运行环境已经不是用户环境了,因此原本用户下的一些环境变量的设置就失效了.例如原来用户环境变量设置的是GB2312,但是使用crontab运行时的环境变量就可能是ISO8859-1.   解决方法:       首先执行命令echo $LANG,假设输出是en_US.UTF-8       然后在脚本中增加一行export LANG=en_US.UTF-8

关于 yii2 cron执行 console的脚本不执行,但是手动执行成功的原因

在yii2中执行脚本出现了一个问题 手动执行没有问题.在cron中不执行,最后找出来了原因 打开yii文件(在根目录下面) #!/usr/bin/env php <?php /** * Yii console bootstrap file. * 改成: #!/usr/bin/env /usr/local/php/bin/php <?php /** * Yii console bootstrap file. * 当然这个得看你的php的安装路径 我的不是yum安装,上面是我的路径 关于这个,ph

是否需要手动执行DataContext的Dispose方法?

我们知道DataContext实现了IDisposable接口.在C#中,凡是实现了IDisposable接口的类,都推荐的使用using语句.如下: using (DataContext db = new DataContext(fileOrServerOrConnection)) { //... } 使用using语句可以确保以正确的方式调用Dispose方法,即使在语句块中出现异常,Dispose方法也将被执行. 但当我们使用如下代码时,将不可避免地得到“System.ObjectDisp

模块手动执行和模块导入执行

本章内容: 1.手动执行模块中的if __name__=="__main__" 2.将文件整体导入到另一个模块中使用 1.手动执行 新建一个文件叫process_Pool.py,然后手动执行 1 #手动执行时,__name__ 等于__main__的,所以会执行测试代码 2 3 import multiprocessing 4 import time,threading 5 6 def thread_run(): 7 print(threading.get_ident()) 8 9 d

解决 MAC 终端上每次打开新窗口手动执行source ~/.bash_profile导出环境变量

MAC OSX上,使用终端(我用的是iTerm2),在个人主目录(~/.bash_profile)中配置了环境变量,但是每次在终端打开一个新标签页或窗口,都要手动执行一下source ~/.bash_profile,很麻烦,解决方法就是: 编辑个人主目录下的.zshrc 这个文件 vim ~/.zshrc 在最后一行少添加一句:(按i进入编辑模式) source ~/.bash_profile 保存退出, :wq 这样每次打开新窗口或标签页就自动执行了source ~/.bash_profile

开发中遇到的问题---【使用mybatis时 有一个sql查询不到结果 日志也显示查询为o 但是从日志中取出执行的sql到数据库客户端手动执行,可以查到数据】

问题:使用mybatis时 有一个sql查询不到结果 日志也显示查询为o 但是从日志中取出执行的sql到数据库客户端手动执行,可以查到数据: 原因:MyBatis看到 #{}会认为你在给sql中的变量赋值,就像JDBC编程中给问号赋值一样(自动在前后加单引号)也就是说,他把你传入的字符串并没有当做多个值,而是当做一个大的字符串,所以查询不到值 而MyBatis看到${}的时候会直接将之替换成变量的值而不做任何处理: 解决方案:将查询条件中的“#”替换成“$”. <select id="fi

&lt;转载&gt;如何立即手动执行BW周期性处理链

在项目测试阶段或者正常企业月结阶段,用户需要看到即使数据,这时候客户会提出当前立刻执行BW处理链的需求.但是一般的业务处理链都是安排在晚上由系统周期性处理.如需要手动立刻执行,就需要对处理链的开始节点更改立即.这样的操作每次都需要将请求传输到测试机或生产机上,效率很低,而且事后需要再次改回原来状态.十分麻烦. 其实,SAP提供了一个标准的function,可以在不改变处理链开始节点的前提下,随时随地的触发处理链.该function的名称是:RSPC_API_CHAIN_START,下面简单介绍一

自动挡换手动挡:在 ASP.NET Core 3.0 Middleware 中手动执行 Controller Action

由于遭遇 System.Data.SqlClient 的性能问题(详见之前的博文),向 .NET Core 3.0 的升级工作被迫提前了.在升级过程中遇到了一个问题,我们在 Razor Class Library 中实现的自定义错误页面无法在 ASP.NET Core 3.0 Preview 5 中正常工作,问题原因详见博问 Razor Class Library 中的属性路由在 ASP.NET Core 3.0 中不起作用 . 由于属性路由不起作用的问题没找到解决方法,于是被迫采用了另外一种解

脚本手动执行正常,放cron中执行有问题的原因

问题原因: 1. crond服务没启动 2. 环境变量如 PATH LANG SHELL 等设置不对 3. 脚本中引用的文件地址是相对路径,而非绝对路径. 排查步骤:  以 check.sh 为例 先检查cron日志中是否有脚本的执行记录:  grep check.sh /var/log/cron* --> 没有执行的记录,则crond服务没启动. 检查crond服务状态: service crond status --> 有执行记录,则crond服务运行正常. 脚本至少是执行过了. 清理掉/