跳至主要內容

Flowable-4.服务接口文档说明

holic-x...大约 29 分钟框架BPMFlowable

Flowable框架学习笔记-04-服务接口文档说明

参考学习链接:

Flowable官网地址:https://flowable.org

Flowable社区地址:https://forum.flowable.org

Flowable GitHub地址:https://github.com/flowable-engine

Flowable API

image-20200614121231714

1.Flowable常用数据表说明

参考链接:https://blog.csdn.net/zhongzk69/article/details/90944593

1>通用数据表(2个)
act_ge_bytearray:二进制数据表,如流程定义、流程模板、流程图的字节流文件;
act_ge_property:属性数据表(不常用);
2>历史表(8个,HistoryService接口操作的表)
act_hi_actinst:历史节点表,存放流程实例运转的各个节点信息(包含开始、结束等非任务节点);
act_hi_attachment:历史附件表,存放历史节点上传的附件信息(不常用);
act_hi_comment:历史意见表;
act_hi_detail:历史详情表,存储节点运转的一些信息(不常用);
act_hi_identitylink:历史流程人员表,存储流程各节点候选、办理人员信息,常用于查询某人或部门的已办任务;
act_hi_procinst:历史流程实例表,存储流程实例历史数据(包含正在运行的流程实例);
act_hi_taskinst:历史流程任务表,存储历史任务节点;
act_hi_varinst:流程历史变量表,存储流程历史节点的变量信息;
3>用户相关表(4个,IdentityService接口操作的表)
act_id_group:用户组信息表,对应节点选定候选组信息;
act_id_info:用户扩展信息表,存储用户扩展信息;
act_id_membership:用户与用户组关系表;
act_id_user:用户信息表,对应节点选定办理人或候选人信息;
4>流程定义、流程模板相关表(3个,RepositoryService接口操作的表)
act_re_deployment:部属信息表,存储流程定义、模板部署信息;
act_re_procdef:流程定义信息表,存储流程定义相关描述信息,但其真正内容存储在act_ge_bytearray表中,以字节形式存储;
act_re_model:流程模板信息表,存储流程模板相关描述信息,但其真正内容存储在act_ge_bytearray表中,以字节形式存储;
5>流程运行时表(6个,RuntimeService接口操作的表)
act_ru_task:运行时流程任务节点表,存储运行中流程的任务节点信息,重要,常用于查询人员或部门的待办任务时使用;
act_ru_event_subscr:监听信息表,不常用;
act_ru_execution:运行时流程执行实例表,记录运行中流程运行的各个分支信息(当没有子流程时,其数据与act_ru_task表数据是一一对应的);
act_ru_identitylink:运行时流程人员表,重要,常用于查询人员或部门的待办任务时使用;
act_ru_job:运行时定时任务数据表,存储流程的定时任务信息;
act_ru_variable:运行时流程变量数据表,存储运行中的流程各节点的变量信息;

(1)一般数据

表名表说明
ACT_GE_BYTEARRAY通用的流程定义和流程资源
ACT_GE_PROPERTY系统相关属性

(2)流程历史记录

表名表说明
ACT_HI_ACTINST历史的流程实例
ACT_HI_ATTACHMENT历史的流程附件
ACT_HI_COMMENT历史的说明性信息
ACT_HI_DETAIL历史的流程运行中的细节信息
ACT_HI_IDENTITYLINK历史的流程运行过程中用户关系
ACT_HI_PROCINST历史的流程实例
ACT_HI_TASKINST历史的任务实例
ACT_HI_VARINST历史的流程运行中的变量信息

(3)用户用户组表

表名表说明
ACT_ID_BYTEARRAY二进制数据表
ACT_ID_GROUP用户组信息表
ACT_ID_INFO用户信息详情表
ACT_ID_MEMBERSHIP人与组关系表
ACT_ID_PRIV权限表
ACT_ID_PRIV_MAPPING用户或组权限关系表
ACT_ID_PROPERTY属性表
ACT_ID_TOKEN系统登录日志表
ACT_ID_USER用户表

(4)流程定义表

表名表说明
ACT_RE_DEPLOYMENT部署单元信息
ACT_RE_MODEL模型信息
ACT_RE_PROCDEF已部署的流程定义

(5)运行实例表

表名表说明
ACT_RU_DEADLETTER_JOB正在运行的任务表
ACT_RU_EVENT_SUBSCR运行时事件
ACT_RU_EXECUTION运行时流程执行实例
ACT_RU_HISTORY_JOB历史作业表
ACT_RU_IDENTITYLINK运行时用户关系信息
ACT_RU_JOB运行时作业表
ACT_RU_SUSPENDED_JOB暂停作业表
ACT_RU_TASK运行时任务表
ACT_RU_TIMER_JOB定时作业表
ACT_RU_VARIABLE运行时变量表

(6)其他表

表名表说明
ACT_EVT_LOG事件日志表
ACT_PROCDEF_INFO流程定义信息

总结说明:

  • ACT_RE_*: 'RE’代表repository。带有这个前缀的表包含“静态”信息,例如流程定义与流程资源(图片、规则等)。
  • ACT_RU_*: 'RU’代表runtime。这些表存储运行时信息,例如流程实例(process instance)、用户任务(user task)、变量(variable)、作业(job)等。Flowable只在流程实例运行中保存运行时数据,并在流程实例结束时删除记录。这样保证运行时表小和快。
  • ACT_HI_*: 'HI’代表history。这些表存储历史数据,例如已完成的流程实例、变量、任务等。
  • ACT_GE_*: 通用数据。在多处使用

按照步骤说明:

> 流程设计
- ACT_DE_MODEL 保存的是流程设计的json格式文件
- ACT_DE_MODEL_HISTORY 保存的是流程设计的历史文件

> 流程部署
- ACT_GE_BYTEARRAY 保存流程设计的xml文件和流程图片(两条记录)
- ACT_RE_DEPLOYMENT 保存流程部署信息,名称,部署时间,分类
- ACT_RE_PROCDEF 保存流程定义信息,key,名称(多次部署同一个流程文件,会生成多个部署记录和流程定义记录,流程定义的ID由key+版本+id组成)

> 启动流程
- ACT_RU_VARIABLE 保存启动流程的参数信息
- ACT_RU_TASK 保存任务节点信息,用于查询待办任务
- ACT_RU_IDENTITYLINK 保存运行时流程的人员信息,用于查询待办任务
- ACT_RU_EXECUTION 记录流程分支信息

- ACT_HI_VARINST 流程历史节点的参数信息
- ACT_HI_TASKINST 存储历史任务节点
- ACT_HI_PROCINST 存储流程实例历史数据
- ACT_HI_IDENTITYLINK 存储流程历史节点人员信息,用于查询已办任务
- ACT_HI_ACTINST 存储流程历史节点信息

2.流程引擎API与服务

引擎API是与Flowable交互的最常用手段。总入口点是ProcessEngine,ProcessEngine可以使用多种方式创建。使用ProcessEngine,可以获得各种提供工作流/BPM方法的服务。ProcessEngine与服务对象都是线程安全的,因此可以在服务器中保存并共用同一个引用

image-20200613100708945

// 通过ProcessEngine创建服务实例
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
RuntimeService runtimeService = processEngine.getRuntimeService();
RepositoryService repositoryService = processEngine.getRepositoryService();
TaskService taskService = processEngine.getTaskService();
ManagementService managementService = processEngine.getManagementService();
IdentityService identityService = processEngine.getIdentityService();
HistoryService historyService = processEngine.getHistoryService();
FormService formService = processEngine.getFormService();
DynamicBpmnService dynamicBpmnService = processEngine.getDynamicBpmnService();

ProcessEngine常用的几个服务

  • RepositoryService: 定义流程和部署流程
  • RuntimeService: 开始新流程实例和查询
  • IdentityService:用户相关
  • TaskService: 任务查询与操作
  • HistoryService: 流程实例历史记录

ProcessEngineServicesAutoConfiguration里已经把这些类注册到Spring里,使用的时候通过注解即可

@Autowired
private RepositoryService repositoryService;

【1】RepositoryService

  • 查询引擎现有的部署与流程定义
  • 暂停或激活部署中的某些流程,或整个部署。暂停意味着不能再对它进行操作,激活刚好相反,重新使它可以操作。
  • 获取各种资源,比如部署中保存的文件,或者引擎自动生成的流程图。
  • 获取POJO版本的流程定义。它可以用Java而不是XML的方式查看流程。
a.流程部署
流程部署方式

RepositoryService服务提供了管理与控制部署(deployments)流程定义(process definitions)的操作

// 获取流程定义和部署对象相关的Service(如果整合Spring框架,则可通过注解进行Bean注入)
RepositoryService repositoryService = processEngine.getRepositoryService() ;
// 部署流程资源包括classpath、InputStream、字符串、zip格式压缩包等方式

/** 方式1:通过classpath方式部署(addClasspathResource指定参数为资源文件名称) **/
Deployment deployment = repositoryService.createDeployment()//创建部署对象  
                        .name("测试流程")//声明流程的名称  
                        .addClasspathResource("diagrams/xxx.bpmn")// 加载资源文件
                        .addClasspathResource("diagrams/xxx.png")// 一次只能加载一个文件  
                        .deploy();// 完成流程部署  

/** 方式2:使用InputStream方式部署流程资源(需要传入一个输入流及资源的名称) **/
// 输入流的来源不限,可以从classpath读取,也可以从一个绝对路径文件读取,也可以是从网络上读取
// a.获取资源相对路径  
String bpmnPath = "diagrams/helloworld.bpmn";  
String pngPath = "diagrams/helloworld.png";  
// b.读取资源作为一个输入流  
FileInputStream bpmnfileInputStream = new FileInputStream(bpmnPath);  
FileInputStream pngfileInputStream = new FileInputStream(pngPath);  
Deployment deployment = repositoryService.createDeployment()// 创建部署对象  
                    .addInputStream("helloworld.bpmn",bpmnfileInputStream)  
                    .addInputStream("helloworld.png", pngfileInputStream)  
                    .deploy();// 完成部署  
   
 /** 方式3:使用字符串方式部署 **/
 // 定义字符串(XML配置,需进行转义处理)  
String text = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><definitions>...</definitions>"; 
// String text= IoUtil.readFileAsString("ceshi.bpmn20.xml");
Deployment deployment = repositoryService.createDeployment()// 创建部署对象  
                    .addString("xxx.bpmn",text)                    
                    .deploy();// 完成部署  

/** 方式3:使用zip方式部署(可针对多流程模型定义文件,将多个资源文件打包成zip/bar) **/
// 从classpath路径下读取资源文件(将资源文件打包成zip)
InputStream in = this.getClass().getClassLoader()
     				.getResourceAsStream("diagrams/helloworld.zip");  
ZipInputStream zipInputStream = new ZipInputStream(in);  
Deployment deployment = repositoryService.createDeployment()//创建部署对象                 
                    .addZipInputStream(zipInputStream)// 加载zip资源
                    .deploy();//完成部署  

/** 方式4:Model方式进行发布(参考设计器中的发布,需手动设计流程) **/
Model modelData =modelService.getModel(modelId);
byte[] bytes = modelService.getBpmnXML(modelData);
if(bytes==null){
    res.put("error","模型数据为空,请先设计流程并成功保存,再进行发布。");
    return res;
}
BpmnModel model = modelService.getBpmnModel(modelData);
if(model.getProcesses().size()==0){
    res.put("error","数据模型不符要求,请至少设计一条主线流程。");
    return res;
}
byte[] bpmnBytes = new BpmnXMLConverter().convertToXML(model);
String processName = modelData.getName()+".bpmn20.xml";
Deployment deployment = repositoryService.createDeployment()
        .name(modelData.getName())
        .addBytes(processName,bpmnBytes)
        .deploy();
// 或者用代码创建bpmnModel模型,然后用以下代码进行部署
repositoryService.createDeployment().addBpmnModel("bpmnModel", bpmnModel).deploy();  


 // 部署完成后则可通过Deployment对象获取相应部署的信息
deployment.getId(); // 部署ID
deployment.getDeploymentTime(); // 部署时间
流程部署数据表分析

ACT_RE_DEPLOYMENT(部署对象表)

存放流程定义的显示名和部署时间,每部署一次增加一条记录,它的id主键将会被act_re_procdef和act_ge_bytearray作为外键

image-20200613114548882

ACT_RE_PROCDEF(流程定义表)

一次部署可能包含多个流程,因此用ACT_RE_PROCDEF用于存储每次部署的时候关联的流程定义(DEPLOYMENT_ID_用于关联ACT_RE_DEPLOYMENT)

存放流程定义的属性信息,部署每个新的流程定义都会在这张表中增加一条记录。当流程定义的key相同的情况下,使用的是版本升级(虽然程序中并没有限制其一定不同,但是一般只用于同一个流程,版本更新才会使用同一个key,不然按照程序逻辑,使用相同key值得流程,按key值查找,只会找最近一个设置为这个值的流程定义,因此需要在业务逻辑层面上控制操作)

image-20200613115114636

流程定义在部署时,是根据流程定义的key来区分是否是同一种流程,因此key相同的流程定义相继部署时,会生成该key对应的新版本的流程定义。key指的是流程定义中的id属性

<process id="multiInstance" name="multiInstance" isExecutable="true" >

ACT_GE_BYTEARRAY(资源文件表)

流程模型资源文件的真正存放地方,它每部署一次就会产生2条记录,一条是关于bpmn规范的文件内容存放在BYTES字段中,另一条是图片信息,采用二进制格式存储。可以部署后解析bpmn文件的内容自动生成流程图,实现流程图的跟踪线路

image-20200613120625502

ACT_RE_MODEL:ACT_RE_MODEL表在xml进行部署时没有内容(flowable放弃了此表改用ACT_DE_MODEL保存流程模型信息)

image-20200613121303336

ACT_GE_PROPERTY(主键生成表)

主键表将生成下次流程部署的主键ID

image-20200613120936753

部署说明

Springboot自动部署流程:

​ 如果是使用Springboot整合flowable,项目启动会自动加载resources/processes文件夹下的bpmn文件并自动操作相应数据库,从而实现部署操作

​ 默认设定ACT_RE_DEPLOYMENT字段NAME_:SpringBootAutoDeployment

​ 默认设定ACT_RE_PROCDEF字段RESOURCE_NAME_DGMN_RESOURCE_NAME_:以当前资源目录路径和信息作为参考录入

​ Springboot会自动检测当前resources/processes文件夹下的bpmn文件与上一次项目自动加载的流程定义作比较,下述简单阐述不同情况的部署:

文件新增:重新部署所有的bpmn文件,如果需要指定部署的bpmn文件key已经存在,则在此基础上进行版本迭代

文件删除:不影响原有已经部署的文件

文件内容变动(任意文件内容更新):重新发布当前resources/processes文件夹下的所有bpmn文件,如果需要指定部署的bpmn文件key已经存在,则在此基础上进行版本迭代

手动部署(通过提供接口实现业务操作部署):

后台根据现有业务逻辑提供流程定义的操作接口,通过前台手动对业务流程进行部署

b.流程定义的暂停(挂起)/激活
流程定义为挂起状态该流程定义将不允许启动新的流程实例,同时该流程定义下所有的流程实例将全部挂起暂停执行
流程实例可以理解为流程定义这个class下的无数个Java对象
流程定义被挂起:此流程定义下的所有流程实例不允许继续往后流转了,所有的流程实例都被停止了
流程定义被激活:此流程定义下的所有流程实例允许继续往后流转
流程定义被挂起的场景:可能当前指定的流程发现了一些不合理的地方,然后就把此流程定义挂起。解决办法就是可以先挂起流程定义,然后更新流程定义后再激活流程定义。或者挂起了就不激活了,重新创建一个新的流程定义
区分流程实例的挂起/激活:流程实例针对的是流程定义下的某个实例
流程定义控制操作参数
suspendProcessDefinitionById挂起流程定义ID
suspendProcessDefinitionByKey挂起流程定义KEY
activateProcessDefinitionById激活流程定义ID
activateProcessDefinitionByKey激活流程定义KEY

image-20200613150245117

流程定义挂起、激活api参数说明:

processDefinitionId(processDefinitionKey):流程定义的id(key)

suspendProcessInstances:是否级联挂起/激活该流程定义下的流程实例(true-级联、false-非级联)

suspensionDate:设置操作这个流程定义的时间,如果不填写,则立即执行操作(挂起、激活)

其中‘级联’概念可以理解为:当挂起流程定义的同时指定‘级联为true’时,已经发起流程的业务不能继续执行,且不允许重新发起新的流程实例;而当挂起流程定义的同时指定‘级联为false’时,已经发起流程的业务还能继续执行,但不允许重新发起新的流程实例;以此类推激活操作也可按照这种思路分析

操作数据表ACT_RE_PROCDEF的SUSPENSION_STATE_字段:1激活 2挂起
如果是根据id激活或挂起流程定义,则可借助isProcessDefinitionSuspended判断当前流程定义的挂起状态从而执行相应的操作;如果是根据key值操作,则可能出现一个key指定有多个流程定义,如果直接执行激活或者挂起操作,则可能出现其中部分流程定义已经是要指定的状态而导致状态变更失败,因此在结合自身项目的基础上要结合实际flowable数据表操作的一些特性和关联性去嵌入到自身的项目,避免因为业务操作导致数据关联出现问题或者是存在大的漏洞
常见异常处理:
# 指定的流程定义id不存在导致异常
Cannot find process definition for id 'companyApply:1:57262a70-ad1c-11ea-8d5d-3cf01168'
org.flowable.common.engine.api.FlowableObjectNotFoundException: Cannot find process definition for id 'companyApply:1:57262a70-ad1c-11ea-8d5d-3cf01168'
    
# 指定的流程定义已经是激活或者是挂起状态,不能反复执行操作
There was an unexpected error (type=Internal Server Error, status=500).
Cannot set suspension state 'active' for ProcessDefinitionEntity[companyApply:1:57262a70-ad1c-11ea-8d5d-3cf01168e588]': already in state 'active'.
org.flowable.common.engine.api.FlowableException: Cannot set suspension state 'active' for ProcessDefinitionEntity[companyApply:1:57262a70-ad1c-11ea-8d5d-3cf01168e588]': already in state 'active'.
    
There was an unexpected error (type=Internal Server Error, status=500).
Cannot set suspension state 'suspended' for ProcessDefinitionEntity[companyApply:1:57262a70-ad1c-11ea-8d5d-3cf01168e588]': already in state 'suspended'.
org.flowable.common.engine.api.FlowableException: Cannot set suspension state 'suspended' for ProcessDefinitionEntity[companyApply:1:57262a70-ad1c-11ea-8d5d-3cf01168e588]': already in state 'suspended'.
    
c.资源管理
# 流程与用户、用户组的关联关系管理
// 为定义的流程授权用户或用户组
addCandidateStarterGroup(processDefinitionId, groupId)
addCandidateStarterUser(processDefinitionId, userId)
// 删除指定流程流程关联的用户或用户组
deleteCandidateStarterGroup(String processDefinitionId, String groupId)
deleteCandidateStarterUser(String processDefinitionId, String userId)
// 查询流程对应关系的所有用户
getIdentityLinksForProcessDefinition(String processDefinitionId)

// 添加模型编辑的资源
addModelEditorSource(modelId, byte[])
addModelEditorSourceExtra(modelId, byte[])
创建查询:查询部署信息,查询流程定义,查询模型信息:
	createModelQuery()  createNativeModelQuery()
	createDeploymentQuery()  createNativeDeploymentQuery()
	createProcessDefinitionQuery()  createNativeProcessDefinitionQuery()
	createNativeXXX:使用自定义SQL查询数据
    
获取模型,部署和流程定义等资源:
	ReadOnlyProcessDefinition getDeployedProcessDefinition(processDefinitionId)
	List<String> getDeploymentResourceNames(deploymentId):获取指定部署下所有文件的名称
	List<IdentityLink> getIdentityLinksForProcessDefinition(processDefinitionId)
    getResourceAsStream:根据部署id和资源图片名称获取指定文件的输入流
	Model getModel(modelId)
    
// 检查流程定义是否被挂起
	boolean isProcessDefinitionSuspended(String processDefinitionId);
# 如果一次流程定义部署指定了多个流程文件,则关联的流程定义表中就会有多条流程定义数据
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
		.deploymentId("7738e0f7-ad4b-11ea-bb68-3cf01168e588").singleResult();
// 流程定义ID
String processDefinitionId = processDefinition.getId();
// 流程定义Key
String processDefinitionKey = processDefinition.getKey();
System.out.print("流程id:"+processDefinitionId);
System.out.print("流程key:"+processDefinitionKey);

// 因此此处如果用上述方式去接收流程定义返回的接口则相应会抛出异常
org.flowable.common.engine.api.FlowableException: Query return 3 results instead of max 1
    
// 在实际业务操作的时候需要确认是查询什么表(创建相应的查询实体)、什么条件下(指定查询参数)、返回记录条数限定

// 根据部署id获取指定的资源文件(下载流程图)
@RequestMapping("/getImage")
public void getImage(String deployId) throws IOException {
	List<String> deploymentResource = repositoryService
        				.getDeploymentResourceNames(deployId);
     System.out.println(deploymentResource);
     String imageName = null;
     for(String name : deploymentResource){
       	if(name.indexOf(".png")>0){
			imageName = name;
		}
     }
     // 加载文件
     if(imageName!=null){
     	File file = new File("E:\\"+imageName);
        InputStream resourceAsStream = repositoryService
            			.getResourceAsStream(deployId,imageName);
            FileUtils.copyInputStreamToFile(resourceAsStream,file);
   }
}
changeDeploymentTenantId(deploymentId, newTenantId)
boolean isProcessDefinitionSuspended(processDefinitionId)
setDeploymentCategory(deploymentId, category)
setProcessDefinitionCategory(processDefinitionId, category)
List<ValidationError> validateProcess(BpmnModel)
d.删除部署

根据deploymentId删除指定的部署,指定是否执行级联删除操作

void deleteDeployment(String deploymentId);

void deleteDeployment(String deploymentId, boolean cascade);

将给定的部署和级联删除删除到流程实例、历史流程实例和作业

void deleteDeploymentCascade(String deploymentId);

结合实际需求执行删除操作,如果该流程下不存在运行实例考虑用普通删除,如果存在运行实例则使用级联删除(敏感操作,一般交由管理员处理)

【2】RuntimeService

参考链接:https://www.shangmayuan.com/a/538a0b230dbe4798b273305b.html

与提供静态信息(也就是不会改变,至少不会经常改变的信息)的RepositoryService相反, RuntimeService用于启动流程定义的新流程实例。流程定义中定义了流程中不同步骤的结构与行为。流程实例则是流程定义的实际执行过程。

同一时刻,一个流程定义通常有多个运行中的实例。RuntimeService也用于读取与存储流程变量。流程变量是流程实例中的数据,可以在流程的许多地方使用(例如排他网关经常使用流程变量判断流程下一步要走的路径)。

RuntimeService还可以用于查询流程实例与执行(Execution)。执行也就是BPMN 2.0中'token'的概念。通常执行是指向流程实例当前位置的指针。

最后,还可以在流程实例等待外部触发时使用RuntimeService,使流程可以继续运行。流程有许多等待状态(wait states),RuntimeService服务提供了许多操作用于“通知”流程实例:已经接收到外部触发,流程实例可以继续运行。

  • 启动流程及对流程数据对控制
  • 流程实例(ProcessInstance)与执行流(Execution)查询
  • 触发流程操作、接收消息和信号
a.RuntimeService启动流程变量管理
  • 启动流程的常用方式(id,key,message)
  • 启动流程可选参数(businesskey,variables,tenantId)
  • 变量(variables)的设置和获取
b.流程实例与执行流
  • 流程实例(ProcessInstance)表示一次工作流业务的数据实体
  • 执行流(Execution)表示流程实例中具体的执行路径
  • 流程实例接口继承与执行流
c.流程触发
  • 使用trigger触发ReceiveTask节点
  • 触发信号捕获事件signalEvenReceived
  • 触发消息捕获事件messageEventReceived

参考链接:https://blog.csdn.net/weixin_40816738/article/details/103077356

如果是单例流程(没有分支和聚合),流程实例id和执行对象id是相同的
一个流程中流程实例只有一个,执行对象可以有多个
select * from act_ru_execution;   # 正在执行的执行对象表
select * from act_hi_procinst;    # 流程实例历史表
select * from act_ru_task;        # 正在执行的任务表(只有节点是userTask时,该表中有数据)
select * from act_hi_taskinst;    # 任务历史表(只有节点是userTask时,该表中有数据)
select * from act_hi_actinst;     # 所有活动节点的历史表
启动流程实例
startProcessInstanceByKey:根据流程定义key启动流程(以最新版本的流程定义为参考),部分方法还提供了其他参数
参数说明:
	processDefinitionKey:流程定义key值
	businessKey:业务标识
	variables:流程变量
启动流程和业务关联区别:
	对于自定义表单来说启动的时候会传入businessKey作为业务和流程的关联属性
	对于动态表单来说不需要使用businessKey关联,因为所有的数据都保存在引擎的表中
	对于外部表单来说businessKey是可选的,但是一般不会为空,和自定义表单类似

startProcessInstanceByKeyAndTenantId:
	tenantId:在上述方法的基础上引入‘租户标识’概念,类似区分不同子系统的流程概念

startProcessInstanceById
startProcessInstanceWithForm
.......
以此类推,结合方法理解

关联数据表:
SELECT * FROM act_ru_execution # 流程实例执行表,记录当前流程实例的执行情况
说明:流程实例执行,如果当前只有一个分支时,一个流程实例只有一条记录且执行表的主键 id 和流程实例 id 相同,如果当前有多个分支正在运行则该执行表中有多条记录,存在执行表的主键和流程实例id 不相同的记录。 不论当前有几个分支总会有一条记录的执行表的主键和流程实例 id 相同。一个流程实例运行完成,此表中与流程实例相关的记录删除。

SELECT * FROM act_ru_identitylink # 任务参与者,记录当前参与任务的用户或组
说明:启动流程实例,流程当前执行到第一个任务结点,此表会插入一条记录表示当前任务的执行情况,如果任务完成则记录删除。

SELECT * FROM act_hi_procinst # 流程实例历史表
说明:流程实例启动,会在此表插入一条记录,流程实例运行完成记录也不会删除。

SELECT * FROM act_hi_taskinst # 任务历史表,记录所有任务
说明:开始一个任务,不仅在 act_ru_task 表插入记录,也会在历史任务表插入一条记录,任务历史表的主键就是任务 id,任务完成此表记录不删除。

SELECT * FROM act_hi_actinst #活动历史表,记录所有活动
说明:活动包括任务,所以此表中不仅记录了任务,还记录了流程执行过程的其它活动,比如开始事件、结束事件
查询流程实例
// 流程定义key
String processDefinitionKey = "holiday";
// 获取RunTimeService
RuntimeService runtimeService = processEngine.getRuntimeService();
List<ProcessInstance> list = runtimeService.createProcessInstanceQuery()
					.processDefinitionKey(processDefinitionKey)//.list();
for (ProcessInstance processInstance : list) {
	// "流程实例id: "+ processInstance.getProcessInstanceId()
	// "所属流程定义id: "+ processInstance.getProcessDefinitionId()
	// "是否执行完成: " + processInstance.isEnded()
	// "是否暂停: " + processInstance.isSuspended()
	// " 当前活动标识 : "+ processInstance.getActivityId()
}

// 如果需要判断指定的流程是否结束,但在历史记录中指定流程还是会保存
ProcessInstance processInstance = processEngine.getRuntimeService()
                .createProcessInstanceQuery()
                .processInstanceId("35001")
                .singleResult();
if (processInstance==null){
	System.out.println("already ending");
}else {
	System.out.println("running");
}
挂起/激活流程实例

某些场景下可能由于流程变更需要将当前运行的流程暂停而不是直接删除,流程暂停后将不会继续执行

/**
 *  全部流程实例挂起与激活(针对的是在挂起/激活流程定义的时候设置级联操作)
 */
// 1.得到ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 2.得到RepositoryService
RepositoryService repositoryService = processEngine.getRepositoryService();
// 3.查询流程定义的对象
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .processDefinitionKey("holiday").singleResult();
// 4.得到当前流程定义的实例是否都为暂停状态
boolean suspended = processDefinition.isSuspended();
String processDefinitionId = processDefinition.getId();
// 5.判断
if(suspended){
	//说明是暂停,就可以激活操作
	repositoryService.activateProcessDefinitionById(processDefinitionId,true,null);
	System.out.println("流程定义:"+processDefinitionId+"激活");
}else{
	repositoryService.suspendProcessDefinitionById(processDefinitionId,true,null);
	System.out.println("流程定义:"+processDefinitionId+"挂起");
}
/**
 *  单个流程实例挂起与激活
 */
// 1.得到ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 2.得到RuntimeService
RuntimeService runtimeService = processEngine.getRuntimeService();
// 3.查询流程实例对象
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                .processInstanceId("2501").singleResult();
// 4.得到当前流程定义的实例是否都为暂停状态
boolean suspended = processInstance.isSuspended();
String processInstanceId = processInstance.getId();
// 5.判断
if(suspended){
	//说明是暂停,就可以激活操作
	runtimeService.activateProcessInstanceById(processInstanceId);
	System.out.println("流程:"+processInstanceId+"激活");
}else{
	runtimeService.suspendProcessInstanceById(processInstanceId);
	System.out.println("流程定义:"+processInstanceId+"挂起");
}
c.流程触发
  • 使用trigger触发ReceiveTask节点
  • 触发信号捕获事件signalEvenReceived
  • 触发消息捕获事件messageEventReceived

【3】TaskService

对于像Flowable这样的BPM引擎来说,核心是需要人类用户操作的任务。所有任务相关的东西都组织在TaskService中,例如

  • 查询分派给用户或组的任务
  • 创建独立运行(standalone)任务。这是一种没有关联到流程实例的任务
  • 决定任务的执行用户(assignee),或者将用户通过某种方式与任务关联
  • 认领(claim)与完成(complete)任务。认领是指某人决定成为任务的执行用户,也即他将会完成这个任务。完成任务是指“做这个任务要求的工作”,通常是填写某个表单
a.获取task任务对象
// 任务基础查询对象
TaskQuery taskQuery = taskService.createTaskQuery();
// 某个任务
taskQuery.taskId(taskId);
// 某个经办人的任务
taskQuery.taskAssignee(userId);
// 某个委托人的任务
taskQuery.taskOwner(userId);
// 某个或多个流程实例的任务
taskQuery.processInstanceId(String processInstanceId);
taskQuery.processInstanceIdIn(List<String> processInstanceIds);
// 某个或多个部署实例的任务
taskQuery.deploymentId(String deploymentId);
taskQuery.deploymentIdIn(List<String> deploymentIds);
// 某个活动实例的任务
taskQuery.executionId(String executionId);
// 按照任务建立时间倒序
taskQuery.orderByTaskCreateTime().desc();
// 存活的任务
taskQuery.active();
// 挂起的任务
taskQuery.suspended();
// 没有 删除缘由 的任务
taskQuery.taskWithoutDeleteReason();
// 没有签收的任务
taskQuery.taskUnassigned();
// 单个的任务对象
Task task = taskQuery.singleResult();
// 多个任务对象 begin : 从第几个开始 ; max : 展现多少个
List<Task> tasks = taskQuery.list();
List<Task> tasks = taskQuery.listPage(int begin,int max);
// 任务的数量
long count = taskQuery.count();
b.变量的设值与取值
// 任务ID
String taskId = task.getId();
// 设置全局变量
taskService.setVariable(taskId,"key1","value1");
// 设置局部变量
taskService.setVariableLocal(taskId,"key2","value2");
// 获取全局变量
Map<String,Object> a = taskService.getVariables(taskId);
// 获取局部变量
Map<String,Object> b = taskService.getVariablesLocal(taskId);
// 流程启动后获取变量(全局变量)
Map<String,Object> variables = runtimeService.getVariables(processInstanceId);
// 设置变量(全局变量)
runtimeService.setVariable(processInstanceId,"key","value");
c.任务的流转
// 任务的执行(委托人)
taskService.resolveTask(taskId);
taskService.complete(taskId);
// 任务的执行(经办人) variables : 下次任务所须要的参数 localScope : 变量的存储范围(true:做用范围为当前任务,false:表示这个变量是全局的)
// 博客:https://blog.csdn.net/u013026207/article/details/53405265
taskService.complete(taskId);
taskService.complete(String taskId, Map<String, Object> variables);
taskService.complete(String taskId, Map<String, Object> variables, boolean localScope);
// 添加和删除候选人
taskService.addCandidateUser(taskId, userId);
taskService.deleteCandidateUser(taskId, userId);
// 签收
taskService.claim(taskId, userId);
// 委派
taskService.delegateTask(taskId, acceptUserId);
// 转发
taskService.setAssignee(taskId, acceptUserId);
// 驳回 currTaskKeys : 该任务的节点 ; activityId : 上一个节点ID
List<String> currTaskKeys = new ArrayList<>();
List<Task> tasks = taskService.createTaskQuery()
			.processInstanceId(processInstanceId).list();
for (Task task : tasks) {
	currTaskKeys.add(task.getTaskDefinitionKey());
}
runtimeService.createChangeActivityStateBuilder()
		.processInstanceId(processInstanceId)
		.moveActivityIdsToSingleActivityId(currTaskKeys, activityId)
		.changeState();
// 删除任务
taskService.deleteTask(taskId, deleteReason);
taskService.deleteTasks(List<String> taskIds, deleteReason);

【4】IdentityService

IdentityService用于管理(创建,更新,删除,查询……)组与用户

Flowable实际上在运行时并不做任何用户检查。例如任务可以分派给任何用户,而引擎并不会验证系统中是否存在该用户。这是因为Flowable有时要与LDAP、Active Directory等服务结合使用。这个服务包括用户以及用户组的:创建,保存和删除,以及它们之间的关系,用户详细信息的创建等操作。

接入自定义的权限体系

用户id => 获取到租户id、角色id集、部门id集

单用户(assignee="用户id")、多用户(candidateUsers="用户id1,用户id2")

单角色、多角色(candidateGroups=":角色id1,:角色id2")

单部门、多部门(candidateGroups="部门id1:,部门id2:")

角色或部门(candidateGroups="角色id1:, :部门id1")

【5】FormService

FormService是可选服务。也就是说Flowable没有它也能很好地运行,而不必牺牲任何功能。这个服务引入了开始表单(start form)任务表单(task form)的概念。 开始表单是在流程实例启动前显示的表单,而任务表单是用户完成任务时显示的表单。Flowable可以在BPMN 2.0流程定义中定义这些表单。表单服务通过简单的方式暴露这些数据。再次重申,表单不一定要嵌入流程定义,因此这个服务是可选的

【6】HistoryService

HistoryService暴露Flowable引擎收集的所有历史数据。当执行流程时,引擎会保存许多数据(可配置),例如流程实例启动时间、谁在执行哪个任务、完成任务花费的事件、每个流程实例的执行路径等等。这个服务主要提供查询这些数据的能力

HistoryService公开了正在进行的以及过去的流程实例相关信息。不同于运行时的信息,运行时信息只包含任意给出的时刻实际运行的状态,这有益于运行时流程执行性能。历史信息有利于查询并且是永久保存的

// 获取历史流程实例查询对象
HistoricProcessInstanceQuery historicProcessInstanceQuery = historyService.createHistoricProcessInstanceQuery();
// 已完成的
historicProcessInstanceQuery.finished();
// 未完成的
historicProcessInstanceQuery.unfinished();
// 删除的
historicProcessInstanceQuery.deleted();
// 没有删除的
historicProcessInstanceQuery.notDeleted();
// 在某个时间点以后结束
historicProcessInstanceQuery.finishedAfter(Date date);
// 在某个时间点以前结束
historicProcessInstanceQuery.finishedBefore(Date date);
// 指定父流程ID的流程实例
historicProcessInstanceQuery.superProcessInstanceId(processInstanceId)
// 历史流程实例
HistoricProcessInstance processInstance =historicProcessInstanceQuery
				.processInstanceId(processInstanceId).singleResult();
// 删除该流程的历史记录
historyService.deleteHistoricProcessInstance(processInstanceId);

【7】ManagementService

ManagementService通常在用Flowable编写用户应用时不需要使用。它可以读取数据库表与表原始数据的信息,也提供了对作业(job)的查询与管理操作。Flowable中很多地方都使用作业,例如定时器(timer),异步操作(asynchronous continuation),延时暂停/激活(delayed suspension/activation)等

【8】DynamicBpmnService

DynamicBpmnService可用于修改流程定义中的部分内容,而不需要重新部署它。例如可以修改流程定义中一个用户任务的办理人设置,或者修改一个服务任务中的类名

flowable使用时的数据库变化

流程模型:开始节点 ----> 审批人甲 ----> 审批人乙 ----> 结束节点

(1)部署

act_re_deployment:会有一条部署记录,记录此次部署的基本信息 act_ge_bytearray:有两条记录,记录的是本次上传的bpmn文件和对应的图片文件,每条记录都有act_re_deployment表的外键关联 act_re_procdef:有一条记录,记录的是该bpmn文件包含的基本信息,包含act_re_deployment表外键

(2)发起申请,启动流程

act_ru_execution:插入一条记录,记录这个流程定义的执行实例,其中id和proc_inst_id相同都是流程执行实例id,也就是本次执行这个流程定义的id,包含流程定义的id外键 act_ru_task:插入一条记录,记录的是第一个任务的信息,也就是开始执行第一个任务。包括act_ru_execution表中的execution_id外键和proc_inst_id外键,也就是本次执行实例id act_hi_procinst:插入一条记录,记录的是本次执行实例的历史记录 act_hi_taskinst:插入一条记录,记录的是本次任务的历史记录

(3)审批人甲批准

act_ru_variable:插入变量信息,包含本次流程执行实例的两个id外键,但不包括任务的id,由于setVariable方法设置的是全局变量,也就是整个流程都会有效的变量 act_ru_task:表中审批人甲的记录被删除,新插入审批人乙的任务记录 act_ru_execution:活动记录并无删除,而是将正在执行的任务变成审批人乙 act_hi_var_inst:插入流程实例的历史记录 act_hi_taskinst:插入任务的历史记录

(4)审批人乙批准(流程结束)

act_ru_task:该流程实例任务实例记录全被清空 act_ru_execution:该流程实例活动实例记录全被清空 act_ru_variable:该流程实例的参数记录全被清空 act_hi_actinst:记录该流程实例全部历史活动信息 start+甲+乙+end

3.Flowable的异常策略

​ Flowable在设计的时候避免过大的异常层次结构,但在特定情况下仍然会抛出下述异常子类。所有流程执行与API调用中发生的错误,如果不符合下面列出的异常,会统一抛出FlowableExceptions

FlowableWrongDbException: 当Flowable引擎检测到数据库表结构版本与引擎版本不匹配时抛出

FlowableOptimisticLockingException: 当对同一数据实体的并发访问导致数据存储发生乐观锁异常时抛出

FlowableClassLoadingException: 当需要载入的类(如JavaDelegate, TaskListener, …)无法找到,或载入发生错误时抛出

FlowableObjectNotFoundException: 当请求或要操作的对象不存在时抛出

FlowableIllegalArgumentException: 当调用Flowable API时使用了不合法的参数时抛出。可能是引擎配置中的不合法值,或者是API调用传递的不合法参数,也可能是流程定义中的不合法值

FlowableTaskAlreadyClaimedException: 当对已被认领的任务调用taskService.claim(…)时抛出

评论
  • 按正序
  • 按倒序
  • 按热度
Powered by Waline v3.1.3