Activiti 7学习_1

Activiti7

一、Activiti介绍

​ Alfresco软件在2010年5月17日宣布Activiti业务流程管理(BPM)开源项目的正式启动,其首席架构师由业务流程管理BPM的专家 Tom Baeyens担任,Tom Baeyens就是原来jbpm的架构师,而jbpm是一个非常有名的工作流引擎,当然activiti也是一个工作流引擎。

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

Activiti官方网站:https://www.activiti.org/

在这里插入图片描述

二、Activiti 7 Demo快速搭建

1、使用IDEA快速搭建一个Maven项目

在这里插入图片描述

2、pom.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.dashu</groupId>
    <artifactId>activiti-demo</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <activiti.version>7.0.0.Beta1</activiti.version>
    </properties>


    <dependencies>

        <!--activiti 引擎-->
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-engine</artifactId>
            <version>${activiti.version}</version>
        </dependency>

        <!--activiti json数据转换 -->
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-json-converter</artifactId>
            <version>${activiti.version}</version>
        </dependency>

        <!--activiti 云支持 -->
        <dependency>
            <groupId>org.activiti.cloud</groupId>
            <artifactId>activiti-cloud-services-api</artifactId>
            <version>${activiti.version}</version>
        </dependency>

        <!--bpmn 模型处理-->
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-bpmn-converter</artifactId>
            <version>${activiti.version}</version>
        </dependency>

        <!--bpmn 布局 -->
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-bpmn-layout</artifactId>
            <version>${activiti.version}</version>
        </dependency>

        <!--mysql-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.15</version>
        </dependency>

        <!--日志-->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.12</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.30</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.30</version>
        </dependency>

        <!--测试-->
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
            <version>RELEASE</version>
            <scope>compile</scope>
        </dependency>


    </dependencies>

</project>
3、log4j.properties
log4j.rootLogger=debug,stdout,info,debug,warn,error 

#console
log4j.appender.stdout=org.apache.log4j.ConsoleAppender 
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout 
log4j.appender.stdout.layout.ConversionPattern= [%d{yyyy-MM-dd HH:mm:ss a}]:%p %l%m%n

#info log
log4j.logger.info=info
log4j.appender.info=org.apache.log4j.DailyRollingFileAppender 
log4j.appender.info.DatePattern='_'yyyy-MM-dd'.log'
log4j.appender.info.File=./log/info/info.log
log4j.appender.info.Append=true
log4j.appender.info.Threshold=INFO
log4j.appender.info.layout=org.apache.log4j.PatternLayout 
log4j.appender.info.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss a} [Thread: %t][ Class:%c >> Method: %l ]%n%p:%m%n

#debug log
log4j.logger.debug=debug
log4j.appender.debug=org.apache.log4j.DailyRollingFileAppender 
log4j.appender.debug.DatePattern='_'yyyy-MM-dd'.log'
log4j.appender.debug.File=./log/debug/debug.log
log4j.appender.debug.Append=true
log4j.appender.debug.Threshold=DEBUG
log4j.appender.debug.layout=org.apache.log4j.PatternLayout 
log4j.appender.debug.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss a} [Thread: %t][ Class:%c >> Method: %l ]%n%p:%m%n

#warn log
log4j.logger.warn=warn
log4j.appender.warn=org.apache.log4j.DailyRollingFileAppender 
log4j.appender.warn.DatePattern='_'yyyy-MM-dd'.log'
log4j.appender.warn.File=./log/warn/warn.log
log4j.appender.warn.Append=true
log4j.appender.warn.Threshold=WARN
log4j.appender.warn.layout=org.apache.log4j.PatternLayout 
log4j.appender.warn.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss a} [Thread: %t][ Class:%c >> Method: %l ]%n%p:%m%n

#error
log4j.logger.error=error
log4j.appender.error = org.apache.log4j.DailyRollingFileAppender
log4j.appender.error.DatePattern='_'yyyy-MM-dd'.log'
log4j.appender.error.File = ./log/error/error.log
log4j.appender.error.Append = true
log4j.appender.error.Threshold = ERROR 
log4j.appender.error.layout = org.apache.log4j.PatternLayout
log4j.appender.error.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss a} [Thread: %t][ Class:%c >> Method: %l ]%n%p:%m%n
4、activiti.cfg.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                        http://www.springframework.org/schema/beans/spring-beans.xsd
						http://www.springframework.org/schema/contex
						http://www.springframework.org/schema/context/spring-context.xsd
						http://www.springframework.org/schema/tx
						http://www.springframework.org/schema/tx/spring-tx.xsd">


    <bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
        <!--配置数据库相关信息-->
        <!--数据库驱动-->
        <property name="jdbcDriver" value="com.mysql.cj.jdbc.Driver"/>
        <!--数据库连接地址-->
        <property name="jdbcUrl" value="jdbc:mysql:///activiti?serverTimezone=CTT&amp;useUnicode=true&amp;characterEncoding=utf-8&amp;allowMultiQueries=true"/>
        <!--用户名-->
        <property name="jdbcUsername" value="root"/>
        <!--密码-->
        <property name="jdbcPassword" value="123456"/>
        <!--
        数据库表生成时的策略:
        flase:       默认值。activiti在启动时,会对比数据库表中保存的版本,如果没有表或者版本不匹配,将抛出异常。(生产环境常用)
        true:        activiti会对数据库中所有表进行更新操作。如果表不存在,则自动创建。(开发时常用)
        create_drop: 在activiti启动时创建表,在关闭时删除表(必须手动关闭引擎,才能删除表)。(单元测试常用)
        drop-create: 在activiti启动时删除原来的旧表,然后在创建新表(不需要手动关闭引擎)。
        -->
        <property name="databaseSchemaUpdate" value="true"/>
    </bean>
</beans>
5、创建数据库

在这里插入图片描述

6、创建Activiti的数据库表
(1) 项目结构

在这里插入图片描述

(2)ActivitiTest.java测试类
package com.dahu.test;

import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.apache.log4j.Logger;
import org.junit.jupiter.api.Test;

public class ActivitiTest {


    private static Logger logger = Logger.getLogger(ActivitiTest.class);

   /**
     * 获取Activiti引擎来创建Activiti的数据库表
     */
    @Test
    public void createActivitiTable() {
        ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
        logger.info(defaultProcessEngine);
        logger.info("创建成功");
    }

}
(3)运行结果

在这里插入图片描述

在这里插入图片描述

三、BPMN文件创建

这里将会使用工具Activiti BPMN visualizer创建BPMN文件

1、Activiti BPMN visualizer插件安装

在这里插入图片描述

2、新建BPMN文件
(1)新建一个BPMN文件并打开

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

(2)画evection工作流

出差申请工作流:

在这里插入图片描述

开始事件

在这里插入图片描述

用户活动:出差申请创建

受理人:张三

在这里插入图片描述

用户活动:组长审核

受理人:李四

在这里插入图片描述

用户活动:经理审批

受理人:王五

在这里插入图片描述

结束事件

在这里插入图片描述

3、BPMN文件

BPMN文件本质上就是一个xml文件,当我们在"Activiti BPMN visualizer"画布上话工作流是,BPMN文件内容也会随之改变。

在这里插入图片描述

4、evection.bpmn20.xml
<?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:xsd="http://www.w3.org/2001/XMLSchema" 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/processdef">
  <process id="evection" name="出差申请工作流" isExecutable="true">
    <startEvent id="sid-b294b070-29a3-4b22-9ef6-5583d3230bdf" name="开始"/>
    <userTask id="sid-a0b2302c-00ad-4f19-b00e-b6f767bf40d2" name="出差申请创建" activiti:assignee="张三"/>
    <userTask id="sid-a665c8ff-8061-4c40-95ab-1329449c97af" name="组长审核" activiti:assignee="李四"/>
    <userTask id="sid-d16dd1ab-afb3-4de4-b5ed-c78331cfa615" name="经理审批" activiti:assignee="王五"/>
    <endEvent id="sid-fc7d1832-5c28-450f-a9bd-da27f3c0584c" name="结束"/>
    <sequenceFlow id="sid-74d23b90-0531-4246-bbe1-c233447fb2c0" sourceRef="sid-b294b070-29a3-4b22-9ef6-5583d3230bdf" targetRef="sid-a0b2302c-00ad-4f19-b00e-b6f767bf40d2"/>
    <sequenceFlow id="sid-59b77e24-64e1-4a4a-bcfc-924833e2eddd" sourceRef="sid-a0b2302c-00ad-4f19-b00e-b6f767bf40d2" targetRef="sid-a665c8ff-8061-4c40-95ab-1329449c97af"/>
    <sequenceFlow id="sid-8aad1f61-88c9-49b8-bdc2-c3197ca30057" sourceRef="sid-a665c8ff-8061-4c40-95ab-1329449c97af" targetRef="sid-d16dd1ab-afb3-4de4-b5ed-c78331cfa615"/>
    <sequenceFlow id="sid-9128fd96-ee22-4fc0-aadd-8738a8d2845f" sourceRef="sid-d16dd1ab-afb3-4de4-b5ed-c78331cfa615" targetRef="sid-fc7d1832-5c28-450f-a9bd-da27f3c0584c"/>
  </process>
  <bpmndi:BPMNDiagram id="BPMNDiagram_evection">
    <bpmndi:BPMNPlane bpmnElement="evection" id="BPMNPlane_evection">
      <bpmndi:BPMNShape id="shape-e164da98-9f11-4606-a083-0e25fad30c73" bpmnElement="sid-b294b070-29a3-4b22-9ef6-5583d3230bdf">
        <omgdc:Bounds x="20.0" y="-105.0" width="30.0" height="30.0"/>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="shape-d4d2d39a-596e-491d-9ffc-556a37bace8b" bpmnElement="sid-a0b2302c-00ad-4f19-b00e-b6f767bf40d2">
        <omgdc:Bounds x="-15.0" y="-40.0" width="100.0" height="80.0"/>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="sid-cb3b86cd-dadb-451a-8e37-424d5eedfaff" bpmnElement="sid-a665c8ff-8061-4c40-95ab-1329449c97af">
        <omgdc:Bounds x="-15.0" y="68.75" width="100.0" height="80.0"/>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="sid-ab42d20c-2c8e-47c5-978b-d4611b5c1989" bpmnElement="sid-d16dd1ab-afb3-4de4-b5ed-c78331cfa615">
        <omgdc:Bounds x="-15.0" y="181.25" width="100.0" height="80.0"/>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="shape-10c8537c-2bef-4528-afdd-9e7ba03f00c7" bpmnElement="sid-fc7d1832-5c28-450f-a9bd-da27f3c0584c">
        <omgdc:Bounds x="20.0" y="300.0" width="30.0" height="30.0"/>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge id="edge-ae8594f3-5672-47f9-a967-5079c81ca222" bpmnElement="sid-74d23b90-0531-4246-bbe1-c233447fb2c0">
        <omgdi:waypoint x="35.0" y="-75.0"/>
        <omgdi:waypoint x="35.0" y="-40.0"/>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="edge-89a56d29-17e9-4c74-9c6c-1c325b72272c" bpmnElement="sid-59b77e24-64e1-4a4a-bcfc-924833e2eddd">
        <omgdi:waypoint x="35.0" y="40.0"/>
        <omgdi:waypoint x="35.0" y="68.75"/>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="edge-6f3cf344-6694-4f8e-ab47-b55876071838" bpmnElement="sid-8aad1f61-88c9-49b8-bdc2-c3197ca30057">
        <omgdi:waypoint x="35.0" y="148.75"/>
        <omgdi:waypoint x="35.0" y="181.25"/>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="edge-0735540b-e25f-48cb-bbf3-b274f50480a3" bpmnElement="sid-9128fd96-ee22-4fc0-aadd-8738a8d2845f">
        <omgdi:waypoint x="35.0" y="261.25"/>
        <omgdi:waypoint x="35.0" y="300.0"/>
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</definitions>

四、工作流部署

1、修改ActivitiTest.java测试类
package com.dahu.test;

import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.DeploymentBuilder;
import org.apache.log4j.Logger;
import org.junit.jupiter.api.Test;

public class ActivitiTest {


    private static Logger logger = Logger.getLogger(ActivitiTest.class);

    /**
     * 获取Activiti引擎来创建Activiti的数据库表
     */
    @Test
    public void createActivitiTable() {
        ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
        logger.info(defaultProcessEngine);
        logger.info("创建成功");
    }



    /**
     * 工作流部署
     */
    @Test
    public void workflowDeployment() {

        /**
         * 获取Activiti流程引擎
         */
        ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();

        /**
         * 获取Activiti资源服务
         */
        RepositoryService repositoryService = defaultProcessEngine.getRepositoryService();

        /**
         * 资源服务创建一个部署对象
         */
        DeploymentBuilder deployment = repositoryService.createDeployment();

        /**
         * 设置工作流名称
         */
        deployment.name("出差申请工作流");
        /**
         * 添加bpmn资源文件
         */
        deployment.addClasspathResource("bpmn/evection.bpmn20.xml");
        /**
         * 开始部署
         */
        deployment.deploy();


//        链式编程
//        deployment.name("出差申请工作流")
//                .addClasspathResource("bpmn/evection.bpmn20.xml")
//                .deploy();


        logger.info("工作流部署成功");
    }


}
2、运行结果

在这里插入图片描述

act_re_deployment表:

在这里插入图片描述

act_ge_bytearray表:
在这里插入图片描述

五、启动一个工作流实例

1、修改ActivitiTest.java测试类
package com.dahu.test;

import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.repository.DeploymentBuilder;
import org.activiti.engine.runtime.ProcessInstance;
import org.apache.log4j.Logger;
import org.junit.jupiter.api.Test;

public class ActivitiTest {


    private static Logger logger = Logger.getLogger(ActivitiTest.class);

    /**
     * 获取Activiti引擎来创建Activiti的数据库表
     */
    @Test
    public void createActivitiTable() {
        ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
        logger.info(defaultProcessEngine);
        logger.info("创建成功");
    }


    /**
     * 工作流部署
     */
    @Test
    public void workflowDeployment() {

        /**
         * 获取Activiti流程引擎
         */
        ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();

        /**
         * 获取Activiti资源服务
         */
        RepositoryService repositoryService = defaultProcessEngine.getRepositoryService();

        /**
         * 资源服务创建一个部署对象
         */
        DeploymentBuilder deployment = repositoryService.createDeployment();

        /**
         * 设置工作流名称
         */
        deployment.name("出差申请工作流");
        /**
         * 添加bpmn资源文件
         */
        deployment.addClasspathResource("bpmn/evection.bpmn20.xml");
        /**
         * 开始部署
         */
        deployment.deploy();


//        链式编程
//        deployment.name("出差申请工作流")
//                .addClasspathResource("bpmn/evection.bpmn20.xml")
//                .deploy();


        logger.info("工作流部署成功");
    }


    /**
     * 流程启动
     */
    @Test
    public void startProcessInstance() {

        /**
         * 工作流key
         */
        String key = "evection";

        /**
         * 获取Activiti流程引擎
         */
        ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();

        /**
         * 获取Activiti运行服务
         */
        RuntimeService runtimeService = defaultProcessEngine.getRuntimeService();

        /**
         * 根据工作流key启动一个流程实例
         */
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(key);

        logger.info("流程定义id = " + processInstance.getProcessDefinitionId());
        logger.info("流程实例id = " + processInstance.getId());
        logger.info("当前活动id = " + processInstance.getActivityId());
        logger.info("流程启动成功....");

    }


}

工作流key的来源:

在这里插入图片描述

2、运行结果

在这里插入图片描述

act_ru_task表:
在这里插入图片描述

流程已启动…