环境说明:
org.activiti.dependencies
activiti-dependencies
7.1.0.M6
pom
org.activiti
activiti-spring-boot-starter
7.1.0.M6
org.springframework.boot
spring-boot-starter-security
org.springframework.boot
spring-boot-starter-web
org.mybatis.spring.boot
mybatis-spring-boot-starter
2.1.4
mysql
mysql-connector-java
runtime
org.springframework.boot
spring-boot-starter-test
test
org.junit.vintage
junit-vintage-engine
不知为何activit7中要吧这security强关联。。。
以上是pom.xml中所要引入的依赖。
所有的表:
图片
表结构说明:
ACT_RE_*: 'RE’表示repository。这个前缀的表包含了流程定义和流程 静态资源(图片、规则等等)
ACT_RU_*: 'RU’表示runtime。这些运行时的表,包含流程实例,认为,变量,异步任务等运行中的数据。Activiti只在流程实例执行过程中保持这些数据,在流程结束时就会删除这些记录。这样运行时表可以一直很小速度很快。
ACT_HI_*: 'HI’表示history。这些表包含历史数据,比如历史流程实例,遍历,任务等等。
ACT_GE_*: 'GE’表示general。通用数据,用于不同场景。
数据表分类
通用数据(act_ge_*)
图片
流程定义(act_re_*)
图片
运行实例(act_ru_*)
图片
历史流程(act_hi_*)
图片
其他
图片
来源网络
核心类
ProcessEngine
流程引擎的抽象,可以通过此类获取需要的所有服务。
通过ProcessEngine获取,Activiti将不同生命周期的服务封装在不同Service中,包括定义、部署、运行。通过服务类可获取相关生命周期中的服务信息。
TaskService
流程运行过程中,每个任务节点的相关操作接口,如complete,delete,delegate等。
RepositoryService
流程定义和部署相关的存储服务。
RuntimeService
流程运行时相关的服务,如根据流程好启动流程实例startProcessInstanceByKey。
HistoryService
历史记录相关服务接口。
关于eclipse中安装插件就不说了,我是把插件下载下来安装的,在线安装不上。
设计请假流程
在src/main/resources下新建processes文件夹,springboot下默认的流程文件定义路径前缀及文件后缀如下:
图片
这里可以在application.yml配置文件中更改。
设计一个请假的流程holiday.bpmn
图片
上面的每一个节点(任务)都动态的指派了用户执行。
填写审批单:${assignee};
部门经理审批: ${mgr};
总经理审批:${top};
每一个节点执行完成时都需要指明下一个节点的执行人。
配置文件
mybatis:
mapper-locations: classpath:mapper
public void createDeploy() {
Deployment deployment = repositoryService.createDeployment()
.addClasspathResource("processes/holiday.bpmn")
.addClasspathResource("processes/holiday.png")
.name("请假申请单流程")
.key("holiday")
.category("InnerP")
.deploy();
logger.info("流程部署id: {}", deployment.getId());
logger.info("流程部署名称: {}", deployment.getName());
}
// 注意这里这个方法是当我们没有开启自动部署流程定义时,就需要手动部署。
public List queryProcessDefinitionByKey(String processDefinition) {
// 查询流程定义
ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();
List list = processDefinitionQuery.processDefinitionKey(processDefinition).list();
list.forEach(pd -> {
logger.info("------------------------------------------------");
logger.info("流程部署id:{}", pd.getDeploymentId());
logger.info("流程定义id:{}", pd.getId());
logger.info("流程定义名称:{}", pd.getName());
logger.info("流程定义key:{}", pd.getKey());
logger.info("流程定义版本:{}", pd.getVersion());
logger.info("------------------------------------------------");
});
return list ;
}
public void deleteDeployment(String deploymentId) {
// 设置true 级联删除流程定义,即使该流程有流程实例启动也可以删除,设置为false非级别删除方式,如果流程
repositoryService.deleteDeployment(deploymentId, true);
}
public void startProcessInstanceById(String processDefinitionId) {
ProcessInstance processInstance = runtimeService.startProcessInstanceById(processDefinitionId) ;
logger.info("流程定义ID: {}", processInstance.getProcessDefinitionId());
logger.info("流程实例ID: {}", processInstance.getId());
}
public void startProcessInstanceToBussinessKey(String processDefinitionId, String bussinessKey) {
ProcessInstance processInstance = runtimeService.startProcessInstanceById(processDefinitionId, bussinessKey);
logger.info("流程定义ID: {}", processInstance.getProcessDefinitionId());
logger.info("流程实例ID: {}", processInstance.getId());
logger.info("BussinessKey: {}", processInstance.getBusinessKey()) ;
}
public void startProcessInstanceAssignVariables(String processDefinitionId, Map variables) {
ProcessInstance processInstance = runtimeService.startProcessInstanceById(processDefinitionId, variables);
logger.info("流程定义ID: {}", processInstance.getProcessDefinitionId());
logger.info("流程实例ID: {}", processInstance.getId());
logger.info("BussinessKey: {}", processInstance.getBusinessKey()) ;
}
public List queryTasks(String assignee) {
TaskQuery query = taskService.createTaskQuery() ;
return query.taskAssignee(assignee).orderByTaskCreateTime().asc().list() ;
}
public void executionTask(Map variables, String instanceId) {
Task task = taskService.createTaskQuery().processInstanceId(instanceId).singleResult() ;
if (task == null) {
logger.error("任务【{}】不存在", instanceId) ;
throw new RuntimeException("任务【" + instanceId + "】不存在") ;
}
taskService.complete(task.getId(), variables) ;
}
}
- HolidayController接口
@RestController
@RequestMapping("/holidays")
public class HolidayController {
@Resource
private HolidayService holidayService ;
@GetMapping("")
public R lists(String key) {
return R.success(holidayService.queryProcessDefinitionByKey(key)) ;
}
@GetMapping("/_deploy")
public R createDeploy() {
holidayService.createDeploy();
return R.success() ;
}
@GetMapping("/start")
public R startProcess(String userId, String processDefinitionId) {
Map variables = new HashMap<>() ;
variables.put("assignee", userId) ;
holidayService.startProcessInstanceAssignVariables(processDefinitionId, variables) ;
return R.success() ;
}
@GetMapping("/tasks")
public R myTasks(String userId) {
List list = holidayService.queryTasks(userId) ;
// 注意这里需要我们自己组装下数据,不然会报错。
List
测试:
启动服务
这里放在processes中的流程定义文件已经被自动部署上了。查看表act_re_procdef
- 查询制定key的流程审批
接口:/holidays
图片
- 启动请假审批流程
接口:/holidays/start
图片
参数:
processDefinitionId:流程定义中的ID。
userId:要处理用户的id。
查看表信息:
图片
这时候就为用户id为:10000的生成了一个要处理的任务,填写审批单。
- 查询指派给我需要处理的任务
接口:/holidays/tasks
图片
- 填写审批单
接口:/holidays/apply
图片
参数:
mgr:指定下一个节点处理人。
explain:请假原因。
days:请假天数。
这里根据自己的业务需要去设置。
再次调用查询接口userId=10002
图片
流程已经到了部门经理。
再次调用/holidays/apply接口。
图片
参数:
top:指明总经理节点需要处理的userId。
图片
再次调用/holidays/apply接口。(总经理处理)
图片
查询对应的任务表信息,已经没有数据了。
图片
查询表:act_hi_actinst
图片
到此一个流程就走完了。下篇 查看流程图。
完毕!!!