springboot整合flowable
自动部署
流程图提前画好,放入 指定文件夹
配置:
spring.datasource.username=root
spring.datasource.password=root
# nullCatalogMeansCurrent=true 自动生成表
spring.datasource.url=jdbc:mysql:///flowable_process?serverTimezone=UTC&nullCatalogMeansCurrent=true&characterEncoding=utf-8
logging.level.org.flowable=debug
# 是否在项目启动的时候,自动去检查流程定义目录下,是否有对应的流程定义文件,,如果为false,则不会自动部署
flowable.check-process-definitions=true
# 默认的部署位置
flowable.process-definition-location-prefix=classpath*:/processes/
# 默认文件后缀 "**.bpmn20.xml", "**.bpmn"
flowable.process-definition-location-suffixes=**.bpmn20.xml,**.bpmn
手动部署
项目启动成功之后,再去部署流程
@RestController
public class ProcessDeployController {
// 操作流程存储表 act_re_xxx
@Autowired
RepositoryService repositoryService;
// procdef#category : 流程的分类,,xml中的 targetNameSpace
@PostMapping("/deploy")
public RespBean deploy(MultipartFile file) throws IOException {
// act_re_deployment
DeploymentBuilder deploymentBuilder = repositoryService.createDeployment()
.name("deployment的name字段")
.category("实例的分类,deployment的category")
.key("deployment的key字段")
// .addString()
// 变成 ByteOutputStream#toByteArray
// .addBytes()
// 设置文件的输入流,通过这个输入流,自动读取文件
// 资源名称不能随便取值,建议最好和文件名保持一致 ,,不然act_re_procdef 不添加数据
.addInputStream(file.getOriginalFilename(), file.getInputStream());
// System.out.println("file.getOriginalFilename() = " + file.getOriginalFilename());
// System.out.println("file.getName() = " + file.getName());
// 完成部署
Deployment deploy = deploymentBuilder.deploy();
return RespBean.ok("部署成功",deploy.getId());
}
}
flowable API
RepositoryServcie
act_re_procdef
表
void test01() {
List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().list();
// for (ProcessDefinition processDefinition : list) {
//
// }
// 查看最新版本
List<ProcessDefinition> list1 = repositoryService.createProcessDefinitionQuery().latestVersion().list();
for (ProcessDefinition processDefinition : list1) {
System.out.println("processDefinition.getId() = " + processDefinition.getId());
}
List<ProcessDefinition> list2 = repositoryService.createProcessDefinitionQuery().processDefinitionKey("").desc().list();
List<ProcessDefinition> list3 = repositoryService.createNativeProcessDefinitionQuery().sql("").parameter("", "").list();
}
act_re_deployment
表:
public void test02(){
List<Deployment> list = repositoryService.createDeploymentQuery().list();
// repositoryService.createDeploymentQuery().deploymentCategory("")
// 根据 流程部署的id 查找流程定义
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId("").singleResult();
List<Deployment> list1 = repositoryService.createNativeDeploymentQuery().sql("").parameter("", "").list();
// 删除 。。涉及到流程定义的表,都会被删除
repositoryService.deleteDeployment(deployment.getId());
}
RuntimeService
流程执行 act_run_xxx
流程启动:
// 流程运行时数据表
@Autowired
RuntimeService runtimeService;
// 当一个流程执行完后,流程的数据 act_ru_xxx 将会被清空,,你只能从历史表中查询以前的数据
@Test
void test() {
// 设置流程发起人
Authentication.setAuthenticatedUserId("ww");
// processDefinitionKey : 数据库中的 key字段,,xml文件的 流程id
// 启动一个流程,获取流程实例
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("leave");
// 流程定义的id 需要自己查询,,,
// runtimeService.startProcessInstanceById("")
System.out.println(processInstance.getId()+"---"+processInstance.getName());
}
public void test06(){
// 设置流程发起人
identityService.setAuthenticatedUserId("zl");
// 流程定义可以修改,发布很多个版本,,根据key查找会有很多个,,, 要查找 latestVersion()
ProcessDefinition leave = repositoryService.createProcessDefinitionQuery().processDefinitionKey("leave").latestVersion().singleResult();
ProcessInstance processInstance = runtimeService.startProcessInstanceById(leave.getId());
System.out.println(processInstance.getId()+"--"+processInstance.getStartUserId());
}
TaskService
act_ru_task
: 需要用户处理的数据
查询某个人要参与的任务:
public void test03(){
// 查询某个人 需要处理的任务
List<Task> list = taskService.createTaskQuery().taskAssignee("ww").list();
for (Task task : list) {
System.out.println(task.getId()+"---"+task.getName());
// 完成任务 ,, act_ru_task 先添加新的任务,然后删除完成的任务,
taskService.complete(task.getId());
}
}
act_ru_task
先添加新的任务,然后删除完成的任务,
act_ru_actinst
: 流程活动的执行情况,,新增下一个执行实例
的任务
流程执行完成后 act_ru_xxx
表中记录全部清空
查看流程是否结束:
@Test
public void test04(){
// act_ru_xxx 是否空了 act_ru_execution 的 PROC_INST_ID_
// ACT_RU_EXECUTION ACT_RE_PROCDEF
String processId = "4f452a00-96f5-11ed-bebc-f0b61e94ce8e";
// 流程实例只有一个 ,,, ACT_RU_EXECUTION存的是执行实例
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processId).singleResult();
System.out.println("processInstance = " + processInstance);
}
查看流程走到哪一步
@Test
public void test05(){
// 查看当前流程走到哪一步了
List<Execution> list = runtimeService.createExecutionQuery().list();
for (Execution execution : list) {
// 查询一个执行实例的 活动节点
List<String> activeActivityIds = runtimeService.getActiveActivityIds(execution.getId());
// act_ru_execution 的 act_id_
System.out.println("activeActivityIds = " + activeActivityIds);
}
}
删除流程实例
@Test
public void test07(){
runtimeService.deleteProcessInstance("4f452a00-96f5-11ed-bebc-f0b61e94ce8e","delete reason");
}
流程定义挂起
@Test
public void test08(){
// 查询流程定义
List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().list();
for (ProcessDefinition processDefinition : list) {
// 挂起的流程定义 是无法开启流程实例的,,, 判断流程定义是否挂起
boolean processDefinitionSuspended = repositoryService.isProcessDefinitionSuspended(processDefinition.getId());
// 挂起一个 流程定义 修改 act_re_procdef 的 SUSPENSION_STATE_ 字段: 2:suspend 1:没有挂起
repositoryService.suspendProcessDefinitionById(processDefinition.getId());
// 激活流程定义
repositoryService.activateProcessDefinitionById(processDefinition.getId());
}
}
挂起的流程定义不能启动 流程实例
挂起流程实例
挂起的流程实例 不能 强制执行 task,,
修改 act_ru_execution
,act_ru_task
…act_re_procdef
的 suspension_status_ 字段
@Test
public void test09(){
// 对于一个挂起的流程实例,,我们是无法执行相应的 Task
List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().list();
for (ProcessDefinition processDefinition : list) {
// suspendProcessInstance : 是否挂起 这个流程定义对应的 流程实例,,,, suspensionDate:挂起时间,到时间之后才会挂起,,null表示立即挂起,,
// 流程实例被挂起,,,流程定义也被挂起
// 涉及的表 : act_ru_execution act_ru_task act_re_procdef
repositoryService.suspendProcessDefinitionById(processDefinition.getId(),true,null);
// 激活 流程实例
repositoryService.activateProcessDefinitionById(processDefinition.getId(),true,null);
}
}
DataObject
设置全局属性,最终是存储在act_ru_variable
中
@Test
public void test11(){
// DataObject : 设置流程的一些全局属性,,, 整个流程的`数据对象`
// <dataObject> 节点
// 查询一个DataObject
// dataObject: act_ru_variable表的name字段
DataObject dataObject = runtimeService.getDataObject("7e02f91d-9708-11ed-a857-f0b61e94ce8e", "绘制时间");
System.out.println(dataObject.getName()+"-------"+dataObject.getValue());
// 查询多个DataObject
List<Execution> list = runtimeService.createExecutionQuery().list();
for (Execution execution : list) {
// key: DataObject的name ,,, value是DataObject
Map<String, DataObject> dataObjects = runtimeService.getDataObjects(execution.getId());
Set<String> keys = dataObjects.keySet();
for (String key : keys) {
System.out.println(key+"----"+dataObjects.get(key).getValue());
}
}
}
租户 tenant
租户: tenant ,, 不同的子系统,,,部署相同的流程,,区分流程定义,属于哪个tenant
act_re_procdef
中 tenant_id_ 字段
如果设置了 tenant_id 在 启动流程实例的时候,必须携带 tenant_id
Authentication.setAuthenticatedUserId("ww");
// 启动指定 tenantId
runtimeService.startProcessInstanceByKeyAndTenantId("leave","cc");
act_ru_task
中有 tenant_id_
字段,但是在执行task的时候不需要传入 tenantId,,
可以根据tanentId查找task
List<Task> list = taskService.createTaskQuery().taskTenantId("cc").list();