• 入门 Activiti 工作流,通俗易懂


     

    概念

    工作流。通过计算机对业务流程自动化执行管理,主要解决的是“使在多个参与者之间按照某种预定义的规则自动进行传递文档、信息或任务的过程,从而实现某个预期的业务目标,或者促使此目标的实现”。

    Activiti7

    介绍

    Activiti是一个工作流引擎,Activiti可以将业务系统中复杂的业务流程抽取出来,使用专门的建模语言BPMN2.0进行定义,业务流程按照预先定义的流程进行执行,实现了系统的流程由Activiti进行管理,减少业务系统由于流程变更进行系统升级改造的工作量,从而提高系统的健壮性,同时也减少了系统开发维护成本。

    在使用activiti之前,首先需要编写activiti.cfg.xml配置文件。并且引入相关依赖。

    1. <dependencies>
    2.     
    3.     <dependency>
    4.         <groupId>org.activitigroupId>
    5.         <artifactId>activiti-engineartifactId>
    6.         <version>6.0.0version>
    7.     dependency>
    8.     <dependency>
    9.         <groupId>org.activitigroupId>
    10.         <artifactId>activiti-springartifactId>
    11.         <version>6.0.0version>
    12.     dependency>
    13.     <dependency>
    14.         <groupId>org.activitigroupId>
    15.         <artifactId>activiti-bpmn-modelartifactId>
    16.         <version>6.0.0version>
    17.     dependency>
    18.     <dependency>
    19.         <groupId>javax.servletgroupId>
    20.         <artifactId>servlet-apiartifactId>
    21.         <version>2.5version>
    22.     dependency>
    23.     <dependency>
    24.         <groupId>org.activitigroupId>
    25.         <artifactId>activiti-bpmn-converterartifactId>
    26.         <version>6.0.0version>
    27.     dependency>
    28.     <dependency>
    29.         <groupId>org.activitigroupId>
    30.         <artifactId>activiti-json-converterartifactId>
    31.         <version>6.0.0version>
    32.     dependency>
    33.     <dependency>
    34.         <groupId>org.activitigroupId>
    35.         <artifactId>activiti-bpmn-layoutartifactId>
    36.         <version>6.0.0version>
    37.     dependency>
    38.     <dependency>
    39.         <groupId>org.activiti.cloudgroupId>
    40.         <artifactId>activiti-cloud-services-apiartifactId>
    41.         <version>7-201710-EAversion>
    42.     dependency>
    43.     <dependency>
    44.         <groupId>aspectjgroupId>
    45.         <artifactId>aspectjweaverartifactId>
    46.         <version>1.5.4version>
    47.     dependency>
    48.     <dependency>
    49.         <groupId>mysqlgroupId>
    50.         <artifactId>mysql-connector-javaartifactId>
    51.         <version>5.1.40version>
    52.     dependency>
    53.     <dependency>
    54.         <groupId>org.springframeworkgroupId>
    55.         <artifactId>spring-testartifactId>
    56.         <version>5.0.7.RELEASEversion>
    57.     dependency>
    58.     <dependency>
    59.         <groupId>org.springframeworkgroupId>
    60.         <artifactId>spring-coreartifactId>
    61.         <version>4.1.6.RELEASEversion>
    62.     dependency>
    63.     <dependency>
    64.         <groupId>org.mybatisgroupId>
    65.         <artifactId>mybatisartifactId>
    66.         <version>3.4.5version>
    67.     dependency>
    68.     <dependency>
    69.         <groupId>commons-dbcpgroupId>
    70.         <artifactId>commons-dbcpartifactId>
    71.         <version>1.4version>
    72.     dependency>
    73.     <dependency>
    74.         <groupId>junitgroupId>
    75.         <artifactId>junitartifactId>
    76.         <version>4.12version>
    77.     dependency>
    78.     <dependency>
    79.         <groupId>log4jgroupId>
    80.         <artifactId>log4jartifactId>
    81.         <version>1.2.17version>
    82.     dependency>
    83.     <dependency>
    84.         <groupId>org.slf4jgroupId>
    85.         <artifactId>slf4j-log4j12artifactId>
    86.         <version>1.7.21version>
    87.     dependency>
    88.     <dependency>
    89.         <groupId>org.slf4jgroupId>
    90.         <artifactId>slf4j-apiartifactId>
    91.         <version>1.7.25version>
    92.     dependency>
    93.     <dependency>
    94.         <groupId>commons-iogroupId>
    95.         <artifactId>commons-ioartifactId>
    96.         <version>2.6version>
    97.     dependency>
    98.     <dependency>
    99.         <groupId>org.projectlombokgroupId>
    100.         <artifactId>lombokartifactId>
    101.         <version>1.16.18version>
    102.         <scope>providedscope>
    103.     dependency>
    104. dependencies>

    activiti.cfg.xml

    activiti的引擎配置文件,包括:ProcessEngineConfiguration的定义、数据源定义、事务管理器等。其实就是一个Spring配置文件。

    1. "1.0" encoding="UTF-8"?>
    2. <beans xmlns="http://www.springframework.org/schema/beans"
    3.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4.        xsi:schemaLocation="http://www.springframework.org/schema/beans
    5.                             http://www.springframework.org/schema/beans/spring-beans.xsd">
    6.     
    7.     <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
    8.         <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
    9.         <property name="url" value="jdbc:mysql://localhost:3306/activiti"/>
    10.         <property name="username" value="root"/>
    11.         <property name="password" value="root"/>
    12.         <property name="maxActive" value="3"/>
    13.         <property name="maxIdle" value="1"/>
    14.     bean>
    15.     
    16.     <bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
    17.         
    18.         <property name="dataSource" ref="dataSource"/>
    19.         
    20.         <property name="databaseSchemaUpdate" value="true"/>
    21.         <property name="asyncExecutorActivate" value="false"/>
    22.         <property name="mailServerHost" value="mail.my-corp.com"/>
    23.         <property name="mailServerPort" value="5025"/>
    24.     bean>
    25. beans>

    Activiti流程框架,在前期主要需要了解的就是数据库表的创建、流程的部署、流程的启动和各个阶段任务的完成。

    流程引擎配置类

    流程引擎配置类(ProcessEngineConfiguration),通过 ProcessEngineConfiguration 可以创建工作流引擎 ProceccEngine。

    工作流引擎的创建

    工作流引擎的创建主要有两种方式:默认创建方式和一般创建方式

    默认创建方式

    1. ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    2. System.out.println(processEngine);

    一般创建方式

    1. //使用自定义方式创建
    2. ProcessEngineConfiguration processEngineConfiguration = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti.cfg.xml");
    3. //获取流程引擎对象:通过 ProcessEngineConfiguration 创建 ProcessEngine,此时会创建数据库
    4. ProcessEngine processEngine = processEngineConfiguration.buildProcessEngine();

    当创建好工作流引擎后,对应的数据库中会自动生成25张数据库表。

        

    图片

    ACT_GE_PROPERTY中会先展示下一次流程的ID(next.dbid),并且在下一次流程部署的时候,对下一次流程的ID进行赋值。

     

     

    图片

    Activiti表说明

    这里以表名的前缀进行说明:

    图片

    Service服务接口

    Activiti中还有许多的Service服务接口。这些Service 是工作流引擎提供用于进行工作流部署、执行、管理的服务接口,我们可以使用这些接口操作服务对应的数据表。

    Service创建方式

    通过ProcessEngine创建Service方式:

    1. Runtimeservice runtimeService = processEngine.getRuntimeService();
    2. RepositoryService repositoryService = processEngine.getRepositoryService();
    3. TaskService taskService = processEngine.getTaskService();

    Service总览

    图片

    • RepositoryService

    Activiti 的资源管理类,提供了管理和控制流程发布包和流程定义的操作。使用工作流建模工具设计的业务流程图需要使用此service将流程定义文件的内容部署到计算机。除了部署流程定义以外,还可以查询引擎中的发布包和流程定义。

    暂停或激活发布包,对应全部和特定流程定义。暂停意味着它们不能再执行任何操作了,激活是对应的反向操作。获得多种资源,像是包含在发布包里的文件,或引擎自动生成的流程图。获得流程定义的pojo版本,可以用来通过java解析流程,而不必通过xml。

    • Runtimeservice

    Activiti的流程运行管理类。可以从这个服务类中获取很多关于流程执行相关的信息

    • Taskservice

    Activiti的任务管理类。可以从这个类中获取任务的信息。

    • Historyservice

    Activiti的历史管理类,可以查询历史信息,执行流程时,引擎会保存很多数据(根据配置),比如流程实例启动时间,任务的参与者,完成任务的时间,每个流程实例的执行路径,等等。这个服务主要通过查询功能来获得这些数据。

    • ManagementService

    Activiti的引擎管理类,提供了对Activiti流程引擎的管理和维护功能,这些功能不在工作流驱动的应用程序中使用,主要用于Activiti 系统的日常维护。

    流程图符号说明

    图片

    BPMN插件

    使用IDEA进行开发,建议下载一个插件。actiBPM插件,直接搜索下载。

    流程符号、画流程图

    流程符号:事件Event,活动Activity,网关Gateway,流向

    使用流程设计器画出流程图

    • 创建bpmn文件,在流程设计器使用流程符号来表达流程,指定流程的key,指定任务负责人

    • 生成png文件

    • 创建的bpmn文件要放在resourse下的bpmn文件夹下。

    图片

     

    图片

    注意: 当前任务流程的ID不能是数字开头。

    图片

    找到本地的文件,选择notepad打开

     

    1. "1.0" encoding="UTF-8" standalone="yes"?>
    2. <definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" 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" xmlns:tns="http://www.activiti.org/test" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" expressionLanguage="http://www.w3.org/1999/XPath" id="m1611283406582" name="" targetNamespace="http://www.activiti.org/test" typeLanguage="http://www.w3.org/2001/XMLSchema">
    3.   <process id="myEvection" isClosed="false" isExecutable="true" name="出差申请" processType="None">
    4.     <startEvent id="_2" name="StartEvent"/>
    5.     <userTask activiti:assignee="zhangsan" activiti:exclusive="true" id="_3" name="创建出差申请"/>
    6.     <userTask activiti:assignee="jerry" activiti:exclusive="true" id="_4" name="经理审批"/>
    7.     <userTask activiti:assignee="jack" activiti:exclusive="true" id="_5" name="总经理审批"/>
    8.     <userTask activiti:assignee="rose" activiti:exclusive="true" id="_6" name="财务审批"/>
    9.     <endEvent id="_7" name="EndEvent"/>
    10.     <sequenceFlow id="_8" sourceRef="_2" targetRef="_3"/>
    11.     <sequenceFlow id="_9" sourceRef="_3" targetRef="_4"/>
    12.     <sequenceFlow id="_10" sourceRef="_4" targetRef="_5"/>
    13.     <sequenceFlow id="_11" sourceRef="_5" targetRef="_6"/>
    14.     <sequenceFlow id="_12" sourceRef="_6" targetRef="_7"/>
    15.   process>
    16.   <bpmndi:BPMNDiagram documentation="background=#FFFFFF;count=1;horizontalcount=1;orientation=0;width=842.4;height=1195.2;imageableWidth=832.4;imageableHeight=1185.2;imageableX=5.0;imageableY=5.0" id="Diagram-_1" name="New Diagram">
    17.     <bpmndi:BPMNPlane bpmnElement="myEvection">
    18.       <bpmndi:BPMNShape bpmnElement="_2" id="Shape-_2">
    19.         <omgdc:Bounds height="32.0" width="32.0" x="185.0" y="0.0"/>
    20.         <bpmndi:BPMNLabel>
    21.           <omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/>
    22.         bpmndi:BPMNLabel>
    23.       bpmndi:BPMNShape>
    24.       <bpmndi:BPMNShape bpmnElement="_3" id="Shape-_3">
    25.         <omgdc:Bounds height="55.0" width="85.0" x="160.0" y="85.0"/>
    26.         <bpmndi:BPMNLabel>
    27.           <omgdc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/>
    28.         bpmndi:BPMNLabel>
    29.       bpmndi:BPMNShape>
    30.       <bpmndi:BPMNShape bpmnElement="_4" id="Shape-_4">
    31.         <omgdc:Bounds height="55.0" width="85.0" x="160.0" y="185.0"/>
    32.         <bpmndi:BPMNLabel>
    33.           <omgdc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/>
    34.         bpmndi:BPMNLabel>
    35.       bpmndi:BPMNShape>
    36.       <bpmndi:BPMNShape bpmnElement="_5" id="Shape-_5">
    37.         <omgdc:Bounds height="55.0" width="85.0" x="160.0" y="285.0"/>
    38.         <bpmndi:BPMNLabel>
    39.           <omgdc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/>
    40.         bpmndi:BPMNLabel>
    41.       bpmndi:BPMNShape>
    42.       <bpmndi:BPMNShape bpmnElement="_6" id="Shape-_6">
    43.         <omgdc:Bounds height="55.0" width="85.0" x="160.0" y="390.0"/>
    44.         <bpmndi:BPMNLabel>
    45.           <omgdc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/>
    46.         bpmndi:BPMNLabel>
    47.       bpmndi:BPMNShape>
    48.       <bpmndi:BPMNShape bpmnElement="_7" id="Shape-_7">
    49.         <omgdc:Bounds height="32.0" width="32.0" x="185.0" y="475.0"/>
    50.         <bpmndi:BPMNLabel>
    51.           <omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/>
    52.         bpmndi:BPMNLabel>
    53.       bpmndi:BPMNShape>
    54.       <bpmndi:BPMNEdge bpmnElement="_12" id="BPMNEdge__12" sourceElement="_6" targetElement="_7">
    55.         <omgdi:waypoint x="201.0" y="445.0"/>
    56.         <omgdi:waypoint x="201.0" y="475.0"/>
    57.         <bpmndi:BPMNLabel>
    58.           <omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
    59.         bpmndi:BPMNLabel>
    60.       bpmndi:BPMNEdge>
    61.       <bpmndi:BPMNEdge bpmnElement="_8" id="BPMNEdge__8" sourceElement="_2" targetElement="_3">
    62.         <omgdi:waypoint x="201.0" y="32.0"/>
    63.         <omgdi:waypoint x="201.0" y="85.0"/>
    64.         <bpmndi:BPMNLabel>
    65.           <omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
    66.         bpmndi:BPMNLabel>
    67.       bpmndi:BPMNEdge>
    68.       <bpmndi:BPMNEdge bpmnElement="_9" id="BPMNEdge__9" sourceElement="_3" targetElement="_4">
    69.         <omgdi:waypoint x="202.5" y="140.0"/>
    70.         <omgdi:waypoint x="202.5" y="185.0"/>
    71.         <bpmndi:BPMNLabel>
    72.           <omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
    73.         bpmndi:BPMNLabel>
    74.       bpmndi:BPMNEdge>
    75.       <bpmndi:BPMNEdge bpmnElement="_11" id="BPMNEdge__11" sourceElement="_5" targetElement="_6">
    76.         <omgdi:waypoint x="202.5" y="340.0"/>
    77.         <omgdi:waypoint x="202.5" y="390.0"/>
    78.         <bpmndi:BPMNLabel>
    79.           <omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
    80.         bpmndi:BPMNLabel>
    81.       bpmndi:BPMNEdge>
    82.       <bpmndi:BPMNEdge bpmnElement="_10" id="BPMNEdge__10" sourceElement="_4" targetElement="_5">
    83.         <omgdi:waypoint x="202.5" y="240.0"/>
    84.         <omgdi:waypoint x="202.5" y="285.0"/>
    85.         <bpmndi:BPMNLabel>
    86.           <omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
    87.         bpmndi:BPMNLabel>
    88.       bpmndi:BPMNEdge>
    89.     bpmndi:BPMNPlane>
    90.   bpmndi:BPMNDiagram>
    91. definitions>

    流程的操作

    部署流程

    使用 Activiti 提供的 API 把流程图的内容写入到数据库中

    属于资源操作类,使用 RepositoryService

    • 单文件部署:把bpmn文件和png文件逐个处理

    • 压缩包部署:把bpmn文件和png文件打成压缩包来处理

    • 部署操作表:act_re_deploymentact_re_procdefact_ge_bytearray

    1. /**
    2.  * 流程部署
    3.  */
    4. public void deployment() {
    5.     // 创建 ProcessEngine
    6.     ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    7.     // 获取 RepositoryService
    8.     RepositoryService repositoryService = processEngine.getRepositoryService();
    9.     // 使用 service 进行流程的部署,定义一个流程的名字,把bpmn和png部署到数据中
    10.     Deployment deployment = repositoryService.createDeployment()
    11.             .name("出差申请流程"//流程图标的名字
    12.             .addClasspathResource("bpmn/evection.bpmn"//bpmn文件
    13.             .addClasspathResource("bpmn/evection.png"//bpmn文件生成的图片
    14.             .deploy();
    15.     // 输出部署信息
    16.     System.out.println("流程部署ID:" + deployment.getId());
    17.     System.out.println("流程部署名字:" + deployment.getName());
    18. }

    有时候我们会有多个流程,需要创建多个bpmn流程文件,这个时候想要同时部署,我们可以对bpmn文件进行打包压缩,使用Zip包进行批量的部署

    1. /**
    2.  * 使用Zip包进行批量的部署
    3.  */
    4. @Test
    5. public void deployProcessByZip() {
    6.     // 获取流程引擎
    7.     ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    8.     // 获取 RepositoryService
    9.     RepositoryService repositoryService = processEngine.getRepositoryService();
    10.     // 流程部署
    11.     // 读取资源包文件,构造成 InputStream
    12.     InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("bpmn/evection.zip");
    13.     // 使用 InputStream 构造 ZipInputStream
    14.     ZipInputStream zipInputStream = new ZipInputStream(inputStream);
    15.     // 使用压缩包的流,进行流程的部署
    16.     Deployment deploy = repositoryService.createDeployment()
    17.             .addZipInputStream(zipInputStream)
    18.             .deploy();
    19.     // 输出
    20.     System.out.println("流程部署的ID:" + deploy.getId());
    21.     System.out.println("流程部署的名称:" + deploy.getName());
    22. }

    操作的数据库表:

    • act_ge_bytearray

    • act_ge_property

    • act_re_deployment

    • act_re_procdef

    启动流程实例

    流程部署完成以后,需要启动流程实例。使用 RuntimeService 根据流程定义的 key进行启动。

    核心代码:

    1. /**
    2.  * 启动流程
    3.  */
    4. public void starProcess() {
    5.     // 创建 ProcessEngine
    6.     ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    7.     // 获取 RunTimeService
    8.     RuntimeService runtimeService = processEngine.getRuntimeService();
    9.     // 根据流程定义的ID启动流程
    10.     ProcessInstance instance = runtimeService.startProcessInstanceByKey("myEvection");
    11.     // 输出内容
    12.     System.out.println("流程定义ID:" + instance.getProcessDefinitionId());
    13.     System.out.println("流程实例的ID:" + instance.getId());
    14.     System.out.println("当前活动的ID:" + instance.getActivityId());
    15. }

    任务查询

    使用 TaskService ,根据流程定义的 key ,任务负责人来进行查询

    核心代码:

    1. /**
    2.  * 查询个人待执行的任务
    3.  */
    4. @Test
    5. public void findPersonalTaskList() {
    6.     // 获取流程引擎
    7.     ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    8.     // 获取TaskService
    9.     TaskService taskService = processEngine.getTaskService();
    10.     // 根据流程的key和任务的负责人去查询任务
    11.     List taskList = taskService.createTaskQuery()
    12.             .processDefinitionKey("myEvection")  // 流程的key
    13.             .includeProcessVariables()
    14.             .taskAssignee("zhangsan")           // 要查询的负责人
    15.             .list();
    16.     // 输出
    17.     for (Task task : taskList) {
    18.         System.out.println("流程实例的ID:" + task.getProcessInstanceId());
    19.         System.out.println("任务的ID:" + task.getId());
    20.         System.out.println("任务的负责人:" + task.getAssignee());
    21.         System.out.println("任务的名称:" + task.getName());
    22.     }
    23. }

    任务完成

    使用 TaskService ,用任务 ID 直接完成任务。

    核心代码:

    1. /**
    2.  * 完成个人任务
    3.  */
    4. @Test
    5. public void completTask() {
    6.     String key = "testCandidiate";
    7.     String assignee = "张三1"//任务的负责人
    8.     ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    9.     TaskService taskService = processEngine.getTaskService();
    10.     Task task = taskService.createTaskQuery()
    11.             .processDefinitionKey(key)
    12.             .taskAssignee(assignee)
    13.             .singleResult();
    14.     if (task != null) {
    15.         taskService.complete(task.getId());
    16.     }
    17. }

    关于流程实例的挂起和激活

    全部流程实例的挂起和激活

    1. /**
    2.  * 全部流程实例的挂起和激活
    3.  */
    4. @Test
    5. public void suspendAllProcessInstance() {
    6.     // 1.获取流程引擎
    7.     ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    8.     // 2.获取 RepositoryService
    9.     RepositoryService repositoryService = processEngine.getRepositoryService();
    10.     // 3.查询流程定义
    11.     ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
    12.             .processDefinitionKey("myEvection")
    13.             .singleResult();
    14.     // 4.获取当前流程定义的实例是否都是挂起状态
    15.     boolean flag = processDefinition.isSuspended();
    16.     // 5.获取流程定义的ID
    17.     String id = processDefinition.getId();
    18.     // 6.判断是否挂起状态。是:改为激活;否:改为挂起
    19.     if (flag) {
    20.         // 改为激活. 参数1:流程定义的ID,参数2:是否激活,参数3:激活时间
    21.         repositoryService.activateProcessDefinitionById(id, truenull);
    22.         System.out.println("流程定义ID:" + id + "已激活");
    23.     } else {
    24.         // 改为挂起. 参数1:流程定义的ID;参数2:是否挂起;参数3:挂起时间
    25.         repositoryService.suspendProcessDefinitionById(id, truenull);
    26.         System.out.println("流程定义ID:" + id + "已挂起");
    27.     }
    28. }

    单个流程实例的挂起和激活

    1. /**
    2.  * 单个流程实例的挂起和激活
    3.  */
    4. @Test
    5. public void suspendSingleProcessInstance() {
    6.     // 1.获取流程引擎
    7.     ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    8.     // 2.获取 RuntimeService
    9.     RuntimeService runtimeService = processEngine.getRuntimeService();
    10.     // 3.通过 RuntimeService 获取流程实例对象
    11.     ProcessInstance instance = runtimeService.createProcessInstanceQuery()
    12.             .processInstanceId("17501")
    13.             .singleResult();
    14.     // 4.得到当前流程实例的暂停状态
    15.     boolean flag = instance.isSuspended();
    16.     // 5.获取流程实例的ID
    17.     String instanceId = instance.getId();
    18.     // 6.判断是否暂停。是:改为激活;否:改为暂停
    19.     if (flag) {
    20.         runtimeService.activateProcessInstanceById(instanceId);
    21.         System.out.println("流程实例ID:" + instanceId + "已激活");
    22.     } else {
    23.         runtimeService.suspendProcessInstanceById(instanceId);
    24.         System.out.println("流程实例ID:" + instanceId + "已暂停");
    25.     }
    26. }

    注意: 流程实例在挂起的状态下是无法进行下一步操作的。

    流程变量

    我们在使用流程变量的时候。如果我们将一个对象存储到一个流程变量中,那么这个对象需要实现Serializable接口。

    1. /**
    2.  * 出差申请中的流程变量对象
    3.  */
    4. @NoArgsConstructor
    5. @AllArgsConstructor
    6. @Data
    7. public class Evection implements Serializable {
    8.     private Long id;                //主键ID
    9.     private Integer days;            //出差天数
    10.     private String evectionName;    //出差单名字
    11.     private Date startTime;         //出差开始时间
    12.     private Date endTime;           //出差结束时间
    13.     private String address;         //目的地
    14.     private String reason;          //出差原因
    15. }

    流程变量的作用域

    • 整个流程实例、任务、执行实例。

    • 默认:整个流程实例。

    使用方法

    在属性上使用UEL表达式 ${assignee}assignee就是一个流程变量的名称。

     

    图片

    在连线上使用UEL表达式 ${days<=3},days就是一个流程变量名称,返回结果为true或者false。

     

    图片

    Activiti有很多种方式设置流程变量,这里简单介绍两种:

    启动流程时设置流程变量

    1. /**
    2.  * 启动流程
    3.  */
    4. @Test
    5. public void startProcess() {
    6.     ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    7.     RuntimeService runtimeService = processEngine.getRuntimeService();
    8.     // 流程变量map
    9.     Map map = new HashMap<>();
    10.     // 设置流程变量
    11.     Evection evection = new Evection();
    12.     evection.setDays(2);
    13.     // 把流程变量的pojo放入map
    14.     map.put("evection", evection);
    15.     map.put("assignee0""张三");
    16.     map.put("assignee1""李经理");
    17.     map.put("assignee2""王财务");
    18.     map.put("assignee3""赵总经理");
    19.     runtimeService.startProcessInstanceByKey("myProcess_1", map);
    20. }

    任务办理时设置

    1. /**
    2.  * 完成任务
    3.  */
    4. @Test
    5. public void completTask() {
    6.     ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    7.     TaskService taskService = processEngine.getTaskService();
    8.     Evection evection = new Evection();
    9.     evection.setDays(2);
    10.     Map map = new HashMap<>();
    11.     map.put("evection", evection);
    12.     Task task = taskService.createTaskQuery()
    13.             .processDefinitionKey("myProcess_2")
    14.             .taskAssignee("王财务0")
    15.             .singleResult();
    16.     if (task != null) {
    17.         String taskId = task.getId();
    18.         // 完成任务
    19.         taskService.complete(taskId, map);
    20.     }
    21. }

    网关

    用来控制流程的走向

    排他网关——ExclusiveGateway

    用来在流程中实现决策,当流程执行到这个网关,所有的分支都会判断条件是否为true,如果为true,则执行该分支。

    注意: 排他网关只会选择一个作为true的分支执行,如果有两个分支都为true,排他网关会选择ID值比较小的一条分支去执行。

    如果从排他网关出去的流程所有的条件都不满足,则会抛出异常。

    并行网关——ParallelGateway

    并行网关,允许流程分成多条分支,也可以把多分支汇聚到一起,并行网关的功能是基于进入和外出顺序流的:

    • fork分支:并行后的所有外出顺序流,为每个顺序流都创建一个并发分支

    • join汇聚:所有到达并行网关,在此等待的分支,直到所有进入顺序流的分支都到达以后,流程就会通过汇聚网关。

    注意: 如果同一个并行网关有多个进入和多个外出顺序流,它就同时具有分支和汇聚功能,这时,网关会先汇聚所有进入的顺序流,然后再切分成多个并行分支。

    与其他网关的主要区别是:并行网关不会解析条件,即使顺序流中定义了条件,也会被忽略。

    并行网关需要所有分支的全部运行完了,才会汇聚,继续向下执行。

    包含网关——InclusiveGateway

    包含网关可以看成是排他网关和并行网关的结合体,和排他网关一样,可以在外出顺序流上定义条件,包含网关会解析它们,但是主要的区别是:包含网关可以选择多于一条顺序流,这和并行网关一样。

    包含网关的功能是基于进入和外出顺序流的。

    • 分支:所有外出顺序流的条件都会被解析,结果为true的顺序流会以并行方式继续执行,会为每一个顺序流创建一个分支。

    • 汇聚:所有并行分支到达包含网关,会进入等待状态,直到每个包含流程token的进入顺序流的分支都到达。这是和并行网关最大的不同。

    事件网关——EventGateway

    Activiti和Spring的整合开发

    配置文件:

    1. "1.0" encoding="UTF-8"?>
    2. <beans xmlns="http://www.springframework.org/schema/beans"
    3.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4.        xmlns:tx="http://www.springframework.org/schema/tx"
    5.        xsi:schemaLocation="http://www.springframework.org/schema/beans
    6.         http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
    7.          http://www.springframework.org/schema/tx
    8.         http://www.springframework.org/schema/tx/spring-tx.xsd">
    9.     
    10.     <bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
    11.         
    12.         <property name="dataSource" ref="dataSource"/>
    13.         
    14.         <property name="transactionManager" ref="transactionManager"/>
    15.         
    16.         <property name="databaseSchemaUpdate" value="true"/>
    17.     bean>
    18.     
    19.     <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
    20.         <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
    21.         <property name="url" value="jdbc:mysql://localhost:3306/actspring"/>
    22.         <property name="username" value="root"/>
    23.         <property name="password" value="root"/>
    24.         <property name="maxActive" value="3"/>
    25.         <property name="maxIdle" value="1"/>
    26.     bean>
    27.     
    28.     <bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">
    29.         <property name="processEngineConfiguration" ref="processEngineConfiguration"/>
    30.     bean>
    31.     
    32.     <bean id="repositoryService" factory-bean="processEngine" factory-method="getRepositoryService"/>
    33.     
    34.     <bean id="runtimeService" factory-bean="processEngine" factory-method="getRuntimeService"/>
    35.     
    36.     <bean id="taskService" factory-bean="processEngine" factory-method="getTaskService"/>
    37.     
    38.     <bean id="historyService" factory-bean="processEngine" factory-method="getHistoryService"/>
    39.     
    40.     <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    41.         <property name="dataSource" ref="dataSource"/>
    42.     bean>
    43.     
    44.     <tx:advice id="txAdvice" transaction-manager="transactionManager">
    45.         <tx:attributes>
    46.             
    47.             <tx:method name="save*" propagation="REQUIRED"/>
    48.             <tx:method name="insert*" propagation="REQUIRED"/>
    49.             <tx:method name="delete*" propagation="REQUIRED"/>
    50.             <tx:method name="update*" propagation="REQUIRED"/>
    51.             <tx:method name="find*" propagation="SUPPORTS" read-only="true"/>
    52.             <tx:method name="get*" propagation="SUPPORTS" read-only="true"/>
    53.         tx:attributes>
    54.     tx:advice>
    55. beans>

    Activiti和SpringBoot的整合开发

    配置文件:

    1. spring:
    2.   application:
    3.     name: actspringboot
    4.   datasource:
    5.     driver-class-name: com.mysql.jdbc.Driver
    6.     url: jdbc:mysql://localhost:3306/actspring?useUnicode=true&characterEncoding=utf-8&useSSL=false&autoReconnect=true&serverTimezone=UTC
    7.     username: root
    8.     password: root
    9.   activiti:
    10.     # false:默认值。activiti在启动时,会对比数据库表中保存的版本。如果没有表或者版本不匹配,将抛出异常
    11.     # true:activiti会对数据库中所有表进行更新操作,如果表不存在,则会自动创建
    12.     # create_drop:在activiti启动时创建表,在关闭时删除表(必须手动关闭引擎,才能删除表)
    13.     # drop-create:在activiti启动时删除原来的旧表,然后再创建新表(不需要手动关闭引擎)
    14.     # 线上一般使用false,开发中使用true
    15.     database-schema-update: true
    16.     # 自动部署验证设置:true-开启(默认)、false-关闭
    17.     check-process-definitions: false
    18.     # 开启历史表
    19.     db-history-used: true
    20.     # 历史记录存储等级
    21.     history-level: full
    22. server:
    23.   port: 8082

     

  • 相关阅读:
    14_自定义ItemDecoration实现qq好友列表分组效果
    手机投屏到笔记本电脑小方法
    【翻译】rocksdb write stall
    Spring Cloud【为什么需要监控系统、Prometheus环境搭建、Grafana环境搭建 、微服务应用接入监控 】(十七)
    OD机考真题搜集:不开心的小朋友
    (四)在docker中安装nginx
    重新认识下JVM级别的本地缓存框架Guava Cache(3)——探寻实现细节与核心机制
    『无为则无心』Python日志 — 69、补充:logging.basicConfig()函数说明
    Selenium 柱状图自动化测试
    开发一个app,需要申请哪些,费用是多少?
  • 原文地址:https://blog.csdn.net/qq_45637260/article/details/127900865