学习来源
https://www.bilibili.com/video/BV1Pb4y1p7Ku?p=1
很重要的东西
一. 关于 Flowable 的介绍就不写了,自己去看上面的视频
二. 首先脑海中必须有一幅图
这里是整工作流引擎的使用窗口工具。
1.PeocessEngine
这个类是 flowable 工作流的执行引擎,后续所有的子工具使用都是从这个类出发构建的。
2.RepositoryService
可以想象成所有的执行流程图都是存放在这个类的仓库里的。
只有一张图在那里工作流是肯定不能开始扭转的,你必须把这张图从仓库中拿出来,告知给引擎,也就是部署。
这张图是在Repository 这个仓库里的 那么 Repository 也有能力让这张图消失,也就是删除。
3.RuntimeService
这个类顾名思义,运行时服务,负责将部署进引擎的图跑起来,并且填充这张图里基本参数,也就时流程变量,图一定是凭借类似于 if else 这种分支跳转运行的
4.TaskService
图运转起来了,每个节点都是对应的处理人,对于人来将这就是个任务,那么就可以通过TaskService 来拉取任务,执行任务,完成任务。
5.HistoryService
任务执行完了,理所当然的可以得到执行任务的历史信息,这些信息可以用来做数据分析等诸如此类的事情
三.对于数据库
个人认为,flowable 的数据库表是非常多的,虽然有一定的规律,但是如果是初次入门,可以先放一放,但是对于被部署的图必须是十分清楚的
就比如说视频中当教材的这张图
https://tkjohn.github.io/flowable-userguide/
这个网址去找对应的图的 xml 文件
实操正文
先搭建环境 ,建议先搭建 maven 环境 ,先不要搭建 spring 环境 ,先熟悉基本操作 ,并且不要纠结使用到的 API 基本见名知意,而且是链式编程,按照常理的逻辑想就可以了。
`
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-engine</artifactId>
<version>6.3.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.21</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.21</version>
</dependency>
`
创建 xml 文件 (就是那个流程图文件)
在xml的第一个 userTask 中指定 负责人
创建日志文件(这个可有可无)
一. 获取流程引擎
`
// 全局引擎
private ProcessEngine processEngine;
@Before
public void testProcessEngine() {
// 引擎全局配置对象 ,这里配置了数据库
ProcessEngineConfiguration configuration = new StandaloneInMemProcessEngineConfiguration();
// 数据库
configuration.setJdbcDriver("com.mysql.cj.jdbc.Driver");
configuration.setJdbcUsername("root");
configuration.setJdbcPassword("100544");
configuration.setJdbcUrl("jdbc:mysql://42.192.121.155:3306/flowable?serverTimezone=UTC&nullCatelogMeansCurrent=true");
// 创建表 默认的 35 张 参数是创建的表策略
configuration.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
// 获取流程引擎
processEngine = configuration.buildProcessEngine();
}
`
获取到流程引擎后 ,去打开你的数据库 ,你会惊喜的发现出现了 34 张表 ,而且大有规律
二. 部署流程实例
`
// 部署流程实例
@Test
public void processDeployment() {
// 注意到这里 ,是引擎获取的 RepositoryService 对象干活的
RepositoryService repository = processEngine.getRepositoryService();
// 这里部署也是 RepositoryService 对象部署的
Deployment deploy = repository.createDeployment()
.addClasspathResource("holiday-request.bpmn20.xml")
.name("请求流程").deploy();
String id = deploy.getId();
System.out.println(" id = " + id);
String name = deploy.getName();
System.out.println(" name = " + name);
}
`
部署完成后去查看你的 act_re_deployment act_re_procdef act_ge_bytearray 表
三. 查询流程实例
`
// 查询流程实例
@Test
public void processDeploymentQuery() {
// 这里也是 RepositoryService对象干活
RepositoryService repository = processEngine.getRepositoryService();
ProcessDefinitionQuery processDefinitionQuery = repository.createProcessDefinitionQuery();
// 这里注意 ,如果确定就一个 可以返回 singleResult 否则就返回 list ,不然会报错
ProcessDefinition result = processDefinitionQuery.deploymentId("2501").singleResult();
String deploymentId = result.getDeploymentId();
String name = result.getName();
String description = result.getDescription();
System.out.println(deploymentId);
System.out.println(name);
System.out.println(description);
}
`
四.删除部署的流程
`
// 删除部署的流程
@Test
public void processDeploymentDelete() {
RepositoryService repository = processEngine.getRepositoryService();
// 根据流程id 删除流程 ,可以设置级联删除,这个方法后面有个参数 true 就是级联删除 ,相关的任务一定会被删除掉
repository.deleteDeployment("7501", true);
}
`
五.启动流程实例
`
// 启动流程实例
@Test
public void processDeploymentStart() {
// 运行时服务 注意看 此时的 对象已经变了 ,是 RuntimeService
RuntimeService runtimeService = processEngine.getRuntimeService();
// 构建流程变量
Map<String, Object> variables = new HashMap<>();
variables.put("employee", "张三");
variables.put("nroOfHolidays", 3);
variables.put("descrition", "老子累了");
// 根据主键启动流程实例
ProcessInstance holidayRequest = runtimeService.startProcessInstanceByKey("holidayRequest", variables);
String processDefinitionId = holidayRequest.getProcessDefinitionId();
System.out.println(processDefinitionId);
String activityId = holidayRequest.getActivityId();
System.out.println(activityId);
}
`
启动流程实例
引擎已经走到这里了
启动实例涉及到的表结构
六. 查询任务
`
@Test
public void queryTask() {
// 此时实例已经启动了,启动就是一个任务,那么相应的调用的也就是任务的服务
// 注意看这里 TaskService
TaskService service = processEngine.getTaskService();
List<Task> list = service.createTaskQuery()
.processDefinitionKey("holidayRequest")
.taskAssignee("zhangsan")
.list();
System.out.println(list.size());
for (Task task : list) {
System.out.println("任务链表");
System.out.println(task.getAssignee());
System.out.println(task.getDescription());
System.out.println(task.getId());
System.out.println(task.getName());
}
}
`
七.完成任务
`
@Test
public void completeTask() {
// TaskService
TaskService service = processEngine.getTaskService();
List
.processDefinitionKey("holidayRequest")
.taskAssignee("zhangsan")
.list();
// 流程变量 ,就那个网关里需要的值
HashMap<String, Object> map = new HashMap<>();
map.put("approved", false);
task.forEach((t) -> {
service.complete(t.getId(), map);
});
}
`
流程图跳转
完成任务就跑到这里来了
注意 : 流程图中的完成任务 本例中走的是不同意 ,咱们需要实现不同意方向的实现类
代码示例
`
// 注意实现的接口 这是一个类似出发器的东西
public class SendRejectionMail implements JavaDelegate {
@Override
public void execute(DelegateExecution delegateExecution) {
System.out.println(" 这里模拟发一封邮件 --------------------- ");
System.out.println(" 请求被拒接了 , 资本家是吸血的 ");
}
}
`
八.查看历史任务
`
@Test
public void historyTaskQuery() {
// 注意看这里
HistoryService service = processEngine.getHistoryService();
List
.processDefinitionId("holidayRequest:1:12503")
.finished()
.list();
list.forEach((o)->{
System.out.println(o.getActivityName());
System.out.println(o.getActivityId());
System.out.println(o.getAssignee());
});
}
`
关于画流程图
视频中的波哥使用的是 Eclipse
如果你会使用 docker 的话
去dockerhub 拉一个镜像
https://hub.docker.com/r/flowable/flowable-ui
启动后访问 ip:8080/flowable-ui/modeler/
user:admin
password : test