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
-
maven配置文件
<properties> <java.version>1.8</java.version> <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> <slf4j.version>1.7.25</slf4j.version> <flowable.version>6.4.1</flowable.version> <druid.version>1.2.4</druid.version> <mysql.version>5.1.47</mysql.version> </properties> <dependencies> <!-- logging --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${slf4j.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>${slf4j.version}</version> </dependency> <!--flowAble--> <dependency> <groupId>org.flowable</groupId> <artifactId>flowable-spring</artifactId> <version>${flowable.version}</version> </dependency> <dependency> <groupId>org.flowable</groupId> <artifactId>flowable-engine</artifactId> <version>${flowable.version}</version> </dependency> <!--druid--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>${druid.version}</version> </dependency> <!-- mysql --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql.version}</version> </dependency> <!--junit--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13.2</version> <scope>test</scope> </dependency> </dependencies>
-
IDM引擎配置
<?xml version="1.0" encoding="UTF-8"?> <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"> <!-- idm引擎配置 --> <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>
-
常用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("test0006@qq.com"); 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 **配置文件初始化引擎
<?xml version="1.0" encoding="UTF-8"?>
<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风格初始化引擎
<?xml version="1.0" encoding="UTF-8"?>
<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>
<!--SpringProcessEngineConfiguration引擎配置-->
<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"/>
<!--执行cmd以及job-->
<bean id="managementService" factory-bean="processEngine" factory-method="getManagementService"/>
</beans>
/**
* Initializes all process engines that can be found on the classpath for resources <code>flowable.cfg.xml</code> (plain Flowable style configuration) and for resources
* <code>flowable-context.xml</code> (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模块
1.1 创建用户
1.2 创建分组
1.3 分配权限
2. modeler模块
2.1 绘制流程图
2.2 绘制表单
2.3 配置条件
2.4 分配节点用户
2.5 配置应用程序