简介
Flowable是一款基于Java的开源业务流程引擎,核心BPMN流程引擎,附带DMN决策表和CMMN案例管理引擎。
与Spring完美集成,本身自带REST API。
目前最新版是Flowable 6.4.0(2018年10月26日)
官网地址:https://www.flowable.org/
github地址:https://github.com/flowable
个人demo地址:https://github.com/xwbz2017/flowable-demo
集成到springboot
1. maven依赖
使用的springboot版本
2.0.5.RELEASE
flowable提供了与springboot集成的starter包,只需要引入到pom文件里,
一定要注意引入自己需要的就行了!
starter | 详细 |
---|---|
flowable-spring-boot-starter-cmmn | 包含CMMN案例管理引擎 |
flowable-spring-boot-starter-cmmn-rest | 同上,另外包含REST API |
flowable-spring-boot-starter-dmn | 包含DMN决策表引擎 |
flowable-spring-boot-starter-dmn-rest | 同上,另外包含REST API |
flowable-spring-boot-starter-process | 包含业务流程引擎,会自动扫描resources/processes 下的.bpmn20 、.bpmn20.xml 文件并部署 |
flowable-spring-boot-starter-process-rest | 同上,另外包含REST API |
flowable-spring-boot-starter | 包含flowable全家桶(Process流程引擎, CMMN案例管理引擎, DMN决策表引擎, Form表单, Content 以及 IDM用户认证) |
flowable-spring-boot-starter-rest | 同上,另外包含REST API |
flowable-spring-boot-starter-actuator | Spring启动的一些依赖 |
在mvnrepository里有一个flowable-spring-boot-starter-basic
,这个其实就是flowable-spring-boot-starter-process
,对,是改名的锅。
flowable-spring-boot-starter-actuator
好像没什么用。
这次引入的maven依赖:
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-spring-boot-starter-process-rest</artifactId>
<version>6.4.0</version>
</dependency>
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-spring-boot-starter-actuator</artifactId>
<version>6.4.0</version>
</dependency>
<!------------------------------- 其他 --------------------------------->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- mysql数据库驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- druid连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>${druid.version}</version>
</dependency>
2. 数据源配置
由于使用的是阿里巴巴的druid连接池,注册DruidDataSource
就行了,详情参考DruidDataSource配置。
第一次使用会创建表到数据库里,如果遇到liquibase.exception.LockException
,需要手动把表名后缀为databasechangeloglock
的字段LOCKED
里的值由1改成0(原因可能是多次更换flowable依赖)。
3. 流程设计器、用户和流程管理系统
在webapps
目录里有四个war
包
- flowable-idm:用户管理、授权
- flowable-admin:实例、任务管理
- flowable-modeler:设计器
- flowable-task:个人任务管理
这些war
包都能直接使用java -jar flowable-[项目].war
启动。
注意:flowable-idm
也用于其他项目的登陆授权。
这时还不能启动,需要修改一些配置:
- 依次解压,打开其中的
WEB-INF\classes
目录,修改flowable-default.properties
文件里的数据库连接信息(
spring.datasource.driver-class-name
、
spring.datasource.url
、
spring.datasource.username
、
spring.datasource.password
),之后重命名文件为application.properties
- 往
WEB-INF\lib
里加入数据库驱动文件,我的是mysql-connector-java-5.1.47.jar
最后使用/tomcat-flowable/bin/startup.bat
启动,默认端口8080
,访问地址:实例管理、设计器、用户管理、个人任务。
- 默认账号:admin
- 默认密码:test
具体流程设计可以参考官方文档
4. 使用方法
这次使用的是
ProcessEngine
ProcessEngine
里常用的几个:
RepositoryService
: 定义流程和部署流程RuntimeService
: 开始新流程实例和查询IdentityService
:用户相关TaskService
: 任务查询与操作HistoryService
: 流程实例历史记录
在ProcessEngineServicesAutoConfiguration
里已经把这些类注册到Spring里,使用的时候这样声明就行:
@Autowired
private RepositoryService repositoryService;
部署流程
Deployment deployment = repositoryService.createDeployment()
// 项目路径
.addClasspathResource(classpath)
// 业务归档(BAR)文件
// .addZipInputStream(inputStream)
// 字节流
// .addInputStream(in)
// 文本
// .addString(xml)
.deploy();
开始流程(创建流程实例)
try {
// 设置发起人
identityService.setAuthenticatedUserId(user.getId());
// processDefinitionKey 流程id
// businessKey 自定义编号,可以放业务编号
// variables 自定义参数
runtimeService.startProcessInstanceByKey(key, user.getId(), vars);
} finally {
// 单线程需要这样处理,原文如下:
// Passes the authenticated user id for this particular thread. All service method (from any service) invocations done by the same thread will have access to this authenticatedUserId.
identityService.setAuthenticatedUserId(null);
}
处理任务
taskService.complete(taskId, params);
获取历史流程实例
HistoricProcessInstanceQuery query = historyService.createHistoricProcessInstanceQuery();
// query.unfinished() 未结束的流程实例
// query.finished() 已结束的流程实例
// query.variableValueEquals("UserId", user.getId()) 查询实例变量
// query.startedBy(user.getId()) 由谁发起,需要开始的时候设置identityService.setAuthenticatedUserId(user.getId())
// 按照开始时间倒序
List<HistoricProcessInstance> list = query.orderByProcessInstanceStartTime().desc().list()
获取历史流程实例变量
Map<String, Object> params = historyService.createHistoricVariableInstanceQuery()
// 实例id
.processInstanceId(id)
.list().stream()
// 组装成Map
.collect(Collectors.toMap(HistoricVariableInstance::getVariableName, HistoricVariableInstance::getValue));
获取进行中的流程实例任务变量(不能获取已结束的)
TaskQuery query = taskService.createTaskQuery();
Task task = query.taskId(taskId).singleResult();
Map<String, Object> params = runtimeService.getVariables(task.getExecutionId());
获取历史流程实例活动
List<HistoricActivityInstance> activities = historyService.createHistoricActivityInstanceQuery()
// 实例id
.processInstanceId(id)
.list();
通用查询流程实例任务
// 需要事先指定是否正在进行
TaskInfoQueryWrapper taskInfoQueryWrapper = runtime ? new TaskInfoQueryWrapper(taskService.createTaskQuery())
: new TaskInfoQueryWrapper(historyService.createHistoricTaskInstanceQuery());
TaskInfoQuery query = taskInfoQueryWrapper.getTaskInfoQuery();
List<TaskInfo> tasks = query.list();