Flowable常用方法

Flowable笔记

1. Flowable介绍

  • Flowable是一个使用Java编写的轻量级业务流程引擎。Flowable流程引擎可用于部署BPMN 2.0流程定义(用于定义流程的行业XML标准), 创建这些流程定义的流程实例,进行查询,访问运行中或历史的流程实例与相关数据,等等。这个章节将用一个可以在你自己的开发环境中使用的例子,逐步介绍各种概念与API。
  • Flowable可以十分灵活地加入你的应用/服务/构架。可以将JAR形式发布的Flowable库加入应用或服务,来嵌入引擎。 以JAR形式发布使Flowable可以轻易加入任何Java环境:Java SE;Tomcat、Jetty或Spring之类的servlet容器;JBoss或WebSphere之类的Java EE服务器,等等。 另外,也可以使用Flowable REST API进行HTTP调用。也有许多Flowable应用(Flowable Modeler, Flowable Admin, Flowable IDM 与 Flowable Task),提供了直接可用的UI示例,可以使用流程与任务。

2. 模块介绍

项目结构

  • flowable-idm:用户管理模块【用户的创建、访问权限的管理】
  • flowable-modeler:流程设计器【创建流程、新建应用程序和发布】
  • flowable-task:启动应用程序、查询代办任务

表结构

  • ACT_RE_*: RE表示repository(存储) RepositoryService接口操作的表。带此前缀的表包含的是静态信息,如,流程定义,流程的资源(图片,规则等)。
  • ACT_RU_*: RU表示runtime(15张表) 这是运行时的表存储着流程变量,用户任务,变量,职责(job)等运行时的数据。flowable只存储实例执行期间的运行时数据,当流程实例结束时,将删除这些记录。这就保证了这些运行时的表小且快。
  • ACT_ID_*: ID表示identity(组织机构-9张表)这些表包含标识的信息,如用户,用户组,等等。
  • ACT_HI_*: HI表示history(10张表) 就是这些表包含着历史的相关数据,如结束的流程实例,变量,任务,等等。
  • ACT_GE_*: 普通数据(2张表)各种情况都使用的数据。
  • *_ DATABASECHANGELOG liuquibase的log表(4张表)
  • * _DATABASECHANGELOGLOCK liuquibase的log表(4张表)

2.1 人员组织

2.1.1 表结构

ID MODEL TABLE_NAME REAMARKS
7 ACT_ID_BYTEARRAY 二进制数据
10 IdentityInfoEntityImpl ACT_ID_INFO 人员信息详情
19 GroupEntityImpl ACT_ID_GROUP 分组
13 MemberShipEntityImpl ACT_ID_MEMBERSHIP 用户和分组中间信息表
25 ACT_ID_PRIV 权限
28 ACT_ID_PRIV_MAPPING 用户或者分组的权限信息中间表
4 ACT_ID_PROPERTY 属性
22 ACT_ID_TOKEN 系统登录日志
16 UserEntityImpl ACT_ID_USER 用户

2.1.2 构建IDM

  1. maven配置文件

      <properties>
            <java.version>1.8java.version>
            <maven.compiler.source>8maven.compiler.source>
            <maven.compiler.target>8maven.compiler.target>
            <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
            <project.reporting.outputEncoding>UTF-8project.reporting.outputEncoding>
            <slf4j.version>1.7.25slf4j.version>
            <flowable.version>6.4.1flowable.version>
            <druid.version>1.2.4druid.version>
            <mysql.version>5.1.47mysql.version>
        properties>
    
        <dependencies>
            
            <dependency>
                <groupId>org.slf4jgroupId>
                <artifactId>slf4j-apiartifactId>
                <version>${slf4j.version}version>
            dependency>
            <dependency>
                <groupId>org.slf4jgroupId>
                <artifactId>slf4j-log4j12artifactId>
                <version>${slf4j.version}version>
            dependency>
            
            <dependency>
                <groupId>org.flowablegroupId>
                <artifactId>flowable-springartifactId>
                <version>${flowable.version}version>
            dependency>
            <dependency>
                <groupId>org.flowablegroupId>
                <artifactId>flowable-engineartifactId>
                <version>${flowable.version}version>
            dependency>
            
            <dependency>
                <groupId>com.alibabagroupId>
                <artifactId>druidartifactId>
                <version>${druid.version}version>
            dependency>
            
            <dependency>
                <groupId>mysqlgroupId>
                <artifactId>mysql-connector-javaartifactId>
                <version>${mysql.version}version>
            dependency>
            
            <dependency>
                <groupId>junitgroupId>
                <artifactId>junitartifactId>
                <version>4.13.2version>
                <scope>testscope>
            dependency>
        dependencies>
    
  2. IDM引擎配置

    
    
    <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans   http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        
        <bean id="idmEngineConfiguration" class="org.flowable.idm.engine.IdmEngineConfiguration">
            <property name="dataSource" ref="dataSource">property>
            <property name="databaseSchemaUpdate" value="true">property>
        bean>
    
        
        <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
            <property name="driverClassName" value="com.mysql.jdbc.Driver">property>
            <property name="url" value="jdbc:mysql://127.0.0.1:3306/flowable?characterEncoding=UTF-8">property>
            <property name="username" value="root">property>
            <property name="password" value="root">property>
        bean>
    beans>
    
  3. 常用API

    package com.flowable;
    
    import org.flowable.common.engine.api.management.TableMetaData;
    import org.flowable.idm.api.*;
    import org.flowable.idm.engine.IdmEngine;
    import org.flowable.idm.engine.IdmEngineConfiguration;
    import org.flowable.idm.engine.impl.persistence.entity.GroupEntityImpl;
    import org.flowable.idm.engine.impl.persistence.entity.UserEntityImpl;
    import org.junit.Before;
    import org.junit.Test;
    
    import java.io.InputStream;
    import java.util.List;
    import java.util.Map;
    
    
    /**
     * @author Laisheng
     * @version 1.0
     * @date 2021-07-21
     * @className FlowAbleIdmTest
     * @description flowable-idm-api-test
     **/
    public class FlowAbleIdmTest {
    
        private IdmEngine idmEngine;
        private IdmIdentityService idmIdentityService;
        private IdmEngineConfiguration configuration;
        private IdmManagementService managementService;
        private String idmName;
    
        /**
         * 初始化IDM引擎配置
         */
        @Before
        public void initFlowAbleIdm(){
            InputStream stream = FlowAbleIdmTest.class.getClassLoader().getResourceAsStream("flowable.idm.cfg.xml");
            idmEngine = IdmEngineConfiguration.createIdmEngineConfigurationFromInputStream(stream).buildIdmEngine();
            idmIdentityService = idmEngine.getIdmIdentityService();
            configuration = idmEngine.getIdmEngineConfiguration();
            managementService = idmEngine.getIdmManagementService();
            idmName = idmEngine.getName();
            System.out.println("引擎名称:"+ idmName);
        }
    
        /**
         * 添加用户
         */
        @Test
        public void addUserTest(){
            UserEntityImpl userEntity = new UserEntityImpl();
            userEntity.setEmail("[email protected]");
            userEntity.setId("test0006");
            userEntity.setPassword("test");
            userEntity.setRevision(0);
            idmIdentityService.saveUser(userEntity);
        }
    
        /**
         * 添加分组
         */
        @Test
        public void addGroupTest(){
            GroupEntityImpl groupEntity = new GroupEntityImpl();
            groupEntity.setId("yanfabu");
            groupEntity.setName("研发部");
            groupEntity.setRevision(0);
            idmIdentityService.saveGroup(groupEntity);
        }
    
        /**
         * 用户分配组
         */
        @Test
        public void addUserForGroup(){
            String userId ="test0006",groupId="yanfabu";
            idmIdentityService.createMembership(userId,groupId);
        }
    
        /**
         * 用户和分组分配权限
         */
        @Test
        public void addPriVile(){
            String privilegeName = "测试权限",priVileId = "8e5de021-e934-11eb-9f6e-f8e4e3d3dff7",userId = "test0006",groupId = "yanfabu";
            idmIdentityService.createPrivilege(privilegeName);
            idmIdentityService.addUserPrivilegeMapping(priVileId,userId);
            idmIdentityService.addGroupPrivilegeMapping(priVileId,groupId);
        }
    
        /**
         * 查询用户
         */
        @Test
        public void findUser(){
            UserQuery userQuery = idmIdentityService.createUserQuery();
            List<User> users = userQuery.list();
            users.forEach(user -> System.out.println(user.getId()));
        }
    
        /**
         * 查询分组
         */
        @Test
        public void findGroup(){
            GroupQuery groupQuery = idmIdentityService.createGroupQuery();
            List<Group> groups = groupQuery.list();
            groups.forEach(Group -> System.out.println(Group.getId()));
        }
    
        /**
         * 查询权限
         */
        @Test
        public void findPriVile(){
            PrivilegeQuery privilegeQuery = idmIdentityService.createPrivilegeQuery();
            List<Privilege> privileges = privilegeQuery.list();
            privileges.forEach(privilege -> System.out.println(privilege.getId()+":"+privilege.getName()));
            String priVileId = "8e5de021-e934-11eb-9f6e-f8e4e3d3dff7";
            // 根据权限查询用户
            List<User> usersWithPrivilege = idmIdentityService.getUsersWithPrivilege(priVileId);
            usersWithPrivilege.forEach(user -> System.out.println(user.getId()));
            // 根据权限查询分组
            List<Group> groupsWithPrivilege = idmIdentityService.getGroupsWithPrivilege(priVileId);
            groupsWithPrivilege.forEach(group -> System.out.println(group.getId()));
        }
    
        /**
         * 获取table相关数据
         */
        @Test
        public void findManagementTable(){
            // 获取表名和数据条数
            Map<String, Long> tableCount = managementService.getTableCount();
            tableCount.forEach((k,v)-> System.out.println(k+" : "+v));
            // 根据class获取表面
            String tableName = managementService.getTableName(User.class);
            System.out.println(tableName);
            // 获取配置信息
            Map<String, String> properties = managementService.getProperties();
            properties.forEach((k,v)-> System.out.println(k+" : "+v));
            // 获取数据库表的元数据信息
            TableMetaData tableMetaData = managementService.getTableMetaData("ACT_ID_USER");
            System.out.println(tableMetaData.getColumnNames());
            System.out.println(tableMetaData.getColumnTypes());
        }
    }
    

2.2 引擎

2.2.1 引擎服务类信息

  • AbstractEngineConfiguration:引擎顶级父类
    • CmmnEngineConfiguration
    • IdmEngineConfiguration
    • AppEngineConfiguration
    • ProcessEngineConfiguration
  • ProcessEngines:流程引擎管理类
  • ProcessEngine:流程引擎类
  • ProcessEngineImpl:流程引擎实现类
  • ProcessEngineConfiguration:流程引擎配置类
  • ProcessEngineConfigurationImpl:流程引擎配置实现类
  • EngineInfo:流程引擎信息类

2.2.2 常用服务类信息

beanName remarks
ProcessEngine 流程引擎类
RepositoryService 流程定义
DynamicBpmnService 动态bpmn服务
HistoryService 历史
FormService 表单
TaskService 任务
IdentityService 用户
ManagementService 执行cmd以及job
RuntimeService 流程实例
ProcessEngineConfiguration 流程引擎配置

2.2.3 引擎初始化步骤和常用API

初始化流程引擎实例化以下服务对象

// 初始化流程引擎
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

通过flowable **flowable.cfg.xml **配置文件初始化引擎


<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans   http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver">property>
        <property name="url" value="jdbc:mysql://127.0.0.1:3306/flowable?characterEncoding=UTF-8">property>
        <property name="username" value="root">property>
        <property name="password" value="root">property>
    bean>
	
    <bean id="processEngineConfiguration" class="org.flowable.engine.impl.cfg.StandaloneProcessEngineConfiguration">
        <property name="databaseType" value="mysql">property>
        <property name="databaseSchemaUpdate" value="true"/>
        <property name="dataSource" ref="dataSource">property>
        
        <property name="processEngineLifecycleListener">
            <bean class="com.flowable.listener.FlowAbleProcessEngineLifecycleListener">bean>
        property>
    bean>
beans>

初始化引擎步骤

/**
 * 初始化引擎步骤
 **/
private static ProcessEngine buildProcessEngine(URL resource) {
        InputStream inputStream = null;
        try {
            inputStream = resource.openStream();
            // 根据flowable.cfg.xml配置文件实例化流程引擎配置类
            ProcessEngineConfiguration processEngineConfiguration = ProcessEngineConfiguration.createProcessEngineConfigurationFromInputStream(inputStream);
            // 实例化引擎类
            return processEngineConfiguration.buildProcessEngine();
        } catch (IOException e) {
            throw new FlowableIllegalArgumentException("couldn't open resource stream: " + e.getMessage(), e);
        } finally {
            IoUtil.closeSilently(inputStream);
        }
}

@Override
public ProcessEngine buildProcessEngine() {
    // 初始化引擎配置类中的属性
    init();
    // 实例化流程引擎实现类
    ProcessEngineImpl processEngine = new ProcessEngineImpl(this);
    // 《Flowable 5》引擎的触发构建
    if (flowable5CompatibilityEnabled && flowable5CompatibilityHandler != null) {
        commandExecutor.execute(new Command<Void>() {
            @Override
            public Void execute(CommandContext commandContext) {
                flowable5CompatibilityHandler.getRawProcessEngine();
                return null;
            }
        });
    }
    // 校验flowable流程实例数量
    postProcessEngineInitialisation();
    return processEngine;
}

创建引擎的五种方式

public static ProcessEngineConfiguration createProcessEngineConfigurationFromResourceDefault() {
        return createProcessEngineConfigurationFromResource("flowable.cfg.xml", "processEngineConfiguration");
    }

    public static ProcessEngineConfiguration createProcessEngineConfigurationFromResource(String resource) {
        return createProcessEngineConfigurationFromResource(resource, "processEngineConfiguration");
    }

    public static ProcessEngineConfiguration createProcessEngineConfigurationFromResource(String resource, String beanName) {
        return (ProcessEngineConfiguration) BeansConfigurationHelper.parseEngineConfigurationFromResource(resource, beanName);
    }

    public static ProcessEngineConfiguration createProcessEngineConfigurationFromInputStream(InputStream inputStream) {
        return createProcessEngineConfigurationFromInputStream(inputStream, "processEngineConfiguration");
    }

    public static ProcessEngineConfiguration createProcessEngineConfigurationFromInputStream(InputStream inputStream, String beanName) {
        return (ProcessEngineConfiguration) BeansConfigurationHelper.parseEngineConfigurationFromInputStream(inputStream, beanName);
    }

    public static ProcessEngineConfiguration createStandaloneProcessEngineConfiguration() {
        return new StandaloneProcessEngineConfiguration();
    }

    public static ProcessEngineConfiguration createStandaloneInMemProcessEngineConfiguration() {
        return new StandaloneInMemProcessEngineConfiguration();
    }

spring风格初始化引擎


<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans   http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="dataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource">
        <property name="driverClass" value="org.h2.Driver"/>
        <property name="url" value="jdbc:h2:mem:flowable;DB_CLOSE_DELAY=1000"/>
        <property name="username" value="sa"/>
        <property name="password" value=""/>
    bean>

    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    bean>

    <bean id="processEngineConfiguration" class="org.flowable.spring.SpringProcessEngineConfiguration">
        <property name="dataSource" ref="dataSource"/>
        <property name="transactionManager" ref="transactionManager"/>
        <property name="databaseSchemaUpdate" value="true"/>
        <property name="mailServerHost" value="localhost"/>
        <property name="mailServerPort" value="5025"/>
        <property name="asyncExecutorActivate" value="false" />
    bean>
	
    <bean id="processEngine" class="org.flowable.spring.ProcessEngineFactoryBean">
        <property name="processEngineConfiguration" ref="processEngineConfiguration"/>
    bean>
	
    <bean id="repositoryService" factory-bean="processEngine" factory-method="getRepositoryService"/>
    
    <bean id="runtimeService" factory-bean="processEngine" factory-method="getRuntimeService"/>
    
    <bean id="taskService" factory-bean="processEngine" factory-method="getTaskService"/>
   	
    <bean id="historyService" factory-bean="processEngine" factory-method="getHistoryService"/>
    
    <bean id="formService" factory-bean="processEngine" factory-method="getFormService"/>
   	
    <bean id="managementService" factory-bean="processEngine" factory-method="getManagementService"/>

beans>
 /**
     * Initializes all process engines that can be found on the classpath for resources flowable.cfg.xml (plain Flowable style configuration) and for resources
     * flowable-context.xml (Spring style configuration).
     */
public static synchronized void init() {
    if (!isInitialized()) {
        if (processEngines == null) {
            // Create new map to store process-engines if current map is null
            processEngines = new HashMap<>();
        }
        ClassLoader classLoader = ReflectUtil.getClassLoader();
        Enumeration<URL> resources = null;
        try {
            resources = classLoader.getResources("flowable.cfg.xml");
        } catch (IOException e) {
            throw new FlowableIllegalArgumentException("problem retrieving flowable.cfg.xml resources on the classpath: " + System.getProperty("java.class.path"), e);
        }

        // Remove duplicated configuration URL's using set. Some
        // classloaders may return identical URL's twice, causing duplicate
        // startups
        Set<URL> configUrls = new HashSet<>();
        while (resources.hasMoreElements()) {
            configUrls.add(resources.nextElement());
        }
        for (Iterator<URL> iterator = configUrls.iterator(); iterator.hasNext();) {
            URL resource = iterator.next();
            LOGGER.info("Initializing process engine using configuration '{}'", resource.toString());
            initProcessEngineFromResource(resource);
        }

        try {
            resources = classLoader.getResources("flowable-context.xml");
        } catch (IOException e) {
            throw new FlowableIllegalArgumentException("problem retrieving flowable-context.xml resources on the classpath: " + System.getProperty("java.class.path"), e);
        }
        while (resources.hasMoreElements()) {
            URL resource = resources.nextElement();
            LOGGER.info("Initializing process engine using Spring configuration '{}'", resource.toString());
            initProcessEngineFromSpringResource(resource);
        }

        setInitialized(true);
    } else {
        LOGGER.info("Process engines already initialized");
    }
}

/**
 * 初始化
 **/
protected static void initProcessEngineFromSpringResource(URL resource) {
    try {
        Class<?> springConfigurationHelperClass = ReflectUtil.loadClass("org.flowable.spring.SpringConfigurationHelper");
        Method method = springConfigurationHelperClass.getDeclaredMethod("buildProcessEngine", new Class<?>[] { URL.class });
        ProcessEngine processEngine = (ProcessEngine) method.invoke(null, new Object[] { resource });

        String processEngineName = processEngine.getName();
        EngineInfo processEngineInfo = new EngineInfo(processEngineName, resource.toString(), null);
        processEngineInfosByName.put(processEngineName, processEngineInfo);
        processEngineInfosByResourceUrl.put(resource.toString(), processEngineInfo);

    } catch (Exception e) {
        throw new FlowableException("couldn't initialize process engine from spring configuration resource " + resource.toString() + ": " + e.getMessage(), e);
    }
}

/**
 * 通过spring方式加载ProcessEngineFactoryBean 
 */
public class SpringConfigurationHelper {
    private static final Logger LOGGER = LoggerFactory.getLogger(SpringConfigurationHelper.class);
    public static ProcessEngine buildProcessEngine(URL resource) {
        LOGGER.debug("==== BUILDING SPRING APPLICATION CONTEXT AND PROCESS ENGINE =========================================");
        try (GenericXmlApplicationContext applicationContext = new GenericXmlApplicationContext(new UrlResource(resource))) {
            Map<String, ProcessEngine> beansOfType = applicationContext.getBeansOfType(ProcessEngine.class);
            if ((beansOfType == null) || beansOfType.isEmpty()) {
                throw new FlowableException("no " + ProcessEngine.class.getName() + " defined in the application context " + resource.toString());
            }
            ProcessEngine processEngine = beansOfType.values().iterator().next();
            LOGGER.debug("==== SPRING PROCESS ENGINE CREATED ==================================================================");
            return processEngine;
        }
    }
}

2.3 流程定义

2.3.1 流程定义相关服务类

  • **RepositoryServiceImpl:**流程定义服务类
    • DeploymentBuilder:用来定义流程部署的相关参数

    • ProcessDefinitionQuery:用来构造查询流程定义相关参数

    • NativeProcessDefinitionQuery:用来构造本地SQL查询流程定义相关参数

    • DeploymentQuery:用来构造查询部署对象相关参数

2.3.2 表结构

MODEL TABLE_NAME REMARKS
DeploymentEntityImpl act_re_deployment 部署对象表
ProcessDefinitionEntityImpl act_re_procdef 流程定义表,key是相同的情况下,默认版本升级
ByteArrayEntityImpl act_ge_bytearray 资源文件表
PropertyEntityImpl act_ge_property 主键生成策略表/属性表
ModelEntityImpl act_re_model 模型信息表
ProcessDefinitionInfoEntityImpl act_procdef_info 流程定义动态改变信息表

2.3.3 常用API

package com.flowable.service;

import org.flowable.bpmn.model.BpmnModel;
import org.flowable.common.engine.impl.util.IoUtil;
import org.flowable.engine.ProcessEngine;
import org.flowable.engine.ProcessEngines;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.repository.*;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.InputStream;

/**
 * @author Laisheng
 * @version 1.0
 * @date 2021-07-22
 * @className RepositoryServiceTest
 * @description 流程定义
 **/
public class RepositoryServiceTest {

    private ProcessEngine processEngine;

    private RepositoryService repositoryService;

    /**
     * 引擎相关配置
     */
    @Before
    public void processEngineTest() {
        processEngine = ProcessEngines.getDefaultProcessEngine();
        repositoryService = processEngine.getRepositoryService();
    }

    /**
     * 关闭
     */
    @After
    public void closeFlowEngine() {
        processEngine.close();
    }

    /**
     * 开始创建新部署
     */
    @Test
    public void createDeployment() {
        String deployString = IoUtil.readFileAsString("oneTaskProcess.bpmn20.xml");
        InputStream inputStream = RepositoryServiceTest.class.getClassLoader().getResourceAsStream("oneTaskProcess.bpmn20.xml");
        DeploymentBuilder deployment = repositoryService.createDeployment()
                .category("test category")
                .name("test name")
                //.addInputStream("oneTaskProcess.bpmn20.xml",inputStream);
                .addString("oneTaskProcess.bpmn20.xml",deployString);

        Deployment deploy = deployment.deploy();
        System.out.println(deploy);
    }

    /**
     * 流程定义查询
     */
    @Test
    public void findProcessDefinitionQuery(){
        // 流程定义
        ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery().latestVersion();
        processDefinitionQuery.list().forEach(processDefinition -> System.out.println(processDefinition.toString()));
        // 流程部署查询
        DeploymentQuery deploymentQuery = repositoryService.createDeploymentQuery();
        deploymentQuery.list().forEach(deployment -> System.out.print(deployment.getId()+"\t"));
        // 流程部署本地SQL查询
        NativeProcessDefinitionQuery nativeProcessDefinitionQuery = repositoryService.createNativeProcessDefinitionQuery();
        NativeProcessDefinitionQuery sql = nativeProcessDefinitionQuery.sql("select * from act_re_procdef");
        sql.list().forEach(processDefinition -> System.err.println(processDefinition.getId()));
        // 根据部署ID删除流程定义
        repositoryService.deleteDeployment("20001",true);
    }
}

2.4 流程实例

2.4.1 RuntimeService 流程执行服务类接口

RuntimeService核心功能:启动实例【定义部署好流程,启动该流程】、查询实例相关信息

ProcessInstanceBuilder:定义启动流程实例相关参数【RuntimeService的派生类】

启动实例的方式:

  • processDefinitionKey:流程定义的key
  • processDefinitionKey + 租户ID:流程定义的key和租户的ID
  • processDefinitionID:流程定义的ID
  • messageName:消息名称
  • messageName + 租户ID:消息的名称和租户的ID

2.4.2 概念:

  • 流程定义
    • 提前定义好流程相关信息,类似在java中定义的类,提前确定参数属性
  • 执行实例
    • 流程在运转过程中执行的任务环节和节点,就是对于的执行实例
    • 启动流程会先创建流程实例,然后在创建执行实例
    • 一个流程中,执行对象可以有多个,但是流程实例只能有一个
  • 流程实例
    • 流程定义的执行实例;好比请假审批,想请假就必须向所属领导进行申请
    • 流程实例中包含所有的环节和节点信息
  • 特别注意:流程实例本质上也是一个执行实例【是当前定义的流程中最大的执行实例】

2.4.3 流程执行的大致过程

  • 启动实例 -> 创建流程实例 -> 执行实例 -> 更新实例 -> 流程环节结束 -> 实例结束

2.4.4 表结构

  • 运行时流程数据表
MODEL TABLE_NAME REMARKS
ExecutionEntityImpl act_ru_execution 流程实例与分支执行表
TaskEntityImpl act_ru_task 用户任务表
IdentityLinkEntityImpl act_ru_identitylink 参与者相关信息表
JobEntityImpl act_ru_job 作业表
act_ru_history_job 历史作业表
TimerJobEntityImpl act_ru_timer_job 定时器表
SuspendedJobEntityImpl act_ru_suspended_job 暂停作业表
DeadLetterJobEntityImpl act_ru_deadletter_job 死信表
VariableInstanceEntityImpl act_ru_variable 变量信息
EventSubscriptionEntityImpl act_ru_event_subscr 事件订阅表
  • 历史流程数据表
MODEL TABLE_NAME REMARKS
HistoricProcessInstanceEntityImpl act_hi_procinst 历史流程实例表
HistoricActivityInstanceEntityImpl act_hi_actinst 历史节点信息表
HistoricTaskInstanceEntityImpl act_hi_taskinst 历史任务表
HistoricVariableInstanceEntityImpl act_hi_varinst 历史变量
HistoricIdentityLinkEntityImpl act_hi_identitylink 历史参与者表
HistoricDetailEntityImpl act_hi_detail 历史的流程运行中的细节信息
AttachmentEntityImpl act_hi_attachment 附件表
CommentEntityImpl act_hi_comment 评论表
EventLogEntryEntityImpl act_evt_log 事件日志表

2.4.5 常用API

package com.flowable.service;

import org.flowable.engine.*;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.repository.DeploymentQuery;
import org.flowable.engine.runtime.Execution;
import org.flowable.engine.runtime.ExecutionQuery;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.engine.runtime.ProcessInstanceQuery;
import org.flowable.task.api.Task;
import org.flowable.task.api.TaskQuery;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Consumer;

/**
 * @author Laisheng
 * @version 1.0
 * @date 2021-07-27
 * @className RuntimeServiceTest
 * @description 流程实例单元测试
 **/
public class RuntimeServiceTest {

    private ProcessEngine processEngine;

    private RepositoryService repositoryService;

    private RuntimeService runtimeService;

    private TaskService taskService;

    /**
     * 引擎相关配置
     */
    @Before
    public void processEngineTest() {
        processEngine = ProcessEngines.getDefaultProcessEngine();
        repositoryService = processEngine.getRepositoryService();
        runtimeService = processEngine.getRuntimeService();
        taskService = processEngine.getTaskService();
    }

    /**
     * 关闭
     */
    @After
    public void closeFlowEngine() {
        processEngine.close();
    }

    /**
     * 获取定义的流程
     */
    @Test
    public void findDeployment() {
        DeploymentQuery deploymentQuery = repositoryService.createDeploymentQuery();
        List<Deployment> deployments = deploymentQuery.list();
        deployments.forEach(deployment -> System.out.println(deployment.toString()));
    }

    /**
     * 启动流程实例
     * 定义测试流程:DeploymentEntity[id=30001, name=请假流程, key=Expense]
     */
    @Test
    public void startDeployment() {
        String businessKey = "dataObject";
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(businessKey);
        System.out.println("流程实例的流程定义id:" + processInstance.getProcessDefinitionId());
        System.out.println("流程实例的流程定义键:" + processInstance.getProcessDefinitionKey());
        System.out.println("实例ID:" + processInstance.getId());
        System.out.println("返回当前执行所在的活动的id:" + processInstance.getActivityId());
    }

    /**
     * 个人任务查询
     */
    @Test
    public void findRuntimeService() {
        TaskQuery taskQuery = taskService.createTaskQuery();
        List<Task> list = taskQuery.taskAssignee("张三")
                .processDefinitionKey("Expense")
                .list();
        list.forEach(task -> System.out.println(task.getId() + ":" + task.getName() + ":" + task.getTaskDefinitionKey()));

    }

    /**
     * 执行任务
     */
    @Test
    public void handlerTask() {
        // 当任务成功执行时调用
        taskService.complete("22501");
    }

    /**
     * 查看流程状态,判断流程正在执行还是结束,有数据的情况正在执行,没有数据表示已经结束
     */
    @Test
    public void queryProcessInstance() {
        ProcessInstanceQuery processInstanceQuery = runtimeService.createProcessInstanceQuery();
        ProcessInstance processInstance = processInstanceQuery.processInstanceId("2501").singleResult();
        System.out.println(Objects.nonNull(processInstance) ? "执行" : "结束");
    }

    /**
     * 查询执行实例
     */
    @Test
    public void queryExecuteInstance() {
        ExecutionQuery executionQuery = runtimeService.createExecutionQuery();
        List<Execution> list = executionQuery.list();
        list.forEach(execution -> System.out.println(execution.getId()+": "+execution.getActivityId()));
    }


    /**
     * 判断当前定义的流程是否被挂起
     */
    @Test
    public void isProcessDefinitionSuspended(){
        boolean processDefinitionSuspended = repositoryService.isProcessDefinitionSuspended("dataObject:2:17504");
        System.out.println(processDefinitionSuspended);
    }


    /**
     * 挂起定义的流程
     * 流程定义表状态为2时,表示流程被挂起
     */
    @Test
    public void suspendProcessDefinitionById(){
        repositoryService.suspendProcessDefinitionById("dataObject:2:17504");
    }

    @Test
    public void startProcessDefinitionById(){
        ProcessInstance processInstance = runtimeService.startProcessInstanceById("dataObject:2:17504");
    }

    /**
     * 激活定义的流程
     */
    @Test
    public void activateProcessDefinitionById(){
        repositoryService.activateProcessDefinitionById("dataObject:2:17504");
    }

    /**
     * 挂起流程实例
     */
    @Test
    public void suspendProcessInstanceById(){
        runtimeService.suspendProcessInstanceById("22501");
    }
    
    /**
     * 激活流程实例
     */
    @Test
    public void activateProcessInstanceById(){
        runtimeService.activateProcessInstanceById("22501");
    }
}

2.5 流程节点

2.6 流程变量

2.7 历史数据

2.8 定时任务

2.9 表单

2.10 流程图

flowable操作手册

flowable-version: 6.4.2

1. idm模块

Flowable常用方法_第1张图片

1.1 创建用户

Flowable常用方法_第2张图片

1.2 创建分组

Flowable常用方法_第3张图片

1.3 分配权限

Flowable常用方法_第4张图片

2. modeler模块

Flowable常用方法_第5张图片

2.1 绘制流程图


Flowable常用方法_第6张图片
Flowable常用方法_第7张图片

2.2 绘制表单


Flowable常用方法_第8张图片
Flowable常用方法_第9张图片
Flowable常用方法_第10张图片

2.3 配置条件

Flowable常用方法_第11张图片


2.4 分配节点用户

Flowable常用方法_第12张图片

2.5 配置应用程序



Flowable常用方法_第13张图片
Flowable常用方法_第14张图片

2.6 发布应用程序

Flowable常用方法_第15张图片

3. task模块

3.1 查询任务

Flowable常用方法_第16张图片

3.2 启动流程

Flowable常用方法_第17张图片

3.3 完成任务

Flowable常用方法_第18张图片

4. admin模块

4.1 查看引擎相关配置

Flowable常用方法_第19张图片

你可能感兴趣的:(flowable流程设计,workflow)