我先总结一下,说实话现在开发都很简单了,尤其spring boot出来之后。activiti就是一个工作流插件,用起来也是相当的简单,所以整理一个spring boot activiti教程。当然这里只是一个关键流程的具体实现,在实际开发可能会有更复杂的表单和业务。
源码地址:https://github.com/houyong2011/activitiDemo
1.引入activiti
这里就不多说spring boot的架构搭建,也很简单,搭建好后引入activiti的包。
<dependency> <groupId>org.activiti</groupId> <artifactId>activiti-spring-boot-starter-basic</artifactId> <version>6.0.0</version> </dependency>
2.新建mysql数据库,配置数据源
新建请假单leave_info表包括字段:id,message '请假内容',status '请假单状态'
spring boot 配置数据源:
spring: datasource: driver-class-name: com.mysql.jdbc.Driver type: com.alibaba.druid.pool.DruidDataSource url: jdbc:mysql://localhost:3306/activitidemo?useUnicode=true&characterEncoding=UTF-8 username: root password: 11111111
3.用eclipse画流程图
3.1 eclipse安装流程设计插件请参考:/article/14.html
3.2安装完后在src/main/resources/目录下新建文件夹processes,activiti默认会在这个文件夹找流程图。
3.3然后在processes文件夹右键-》new-》other。选择Activiti Diagram。输入名称LeaveProcess。建一个请假流程单。
3.4打开这个LeaveProcess.bpmn,然后再整个流程图的properties窗口中的id舒服LeaveProcess,后面的程序会根据这个id来区分流程。
然后依次选择startEvent-serviceTask-userTask-exclusivegateway-endEvent。拖放进来画出请假流程图如下:用户提交请假申请单-修改申请单状态为已提交-部门经理审批-人事经理审批-修改申请单状态为通过。
4.流程图具体配置
除了起始节点,终止节点和连接线,其他都是需要配置参数的,其实道理很简单,无非就是每一步去调用你具体的业务代码,流程引擎只管走通这个流程,然后再每个节点去配置调用具体的方法。调用某个类某个方法,也是按照spring的方式,只要再spring容器管理的类中,就能用类似el表达式来调用到你自己的业务方法。在调某个方法的时候需要传当前流程execution,来告诉那个方法,是哪个流程在调用。
4.1 提交修改申请单状态
用户提交请假单,需要再第一个节点中调用修改请假单状态的方法,
选中此节点,修改properties->Main config->Task Type->选择Express表达式->Expression填写:${leaveServiceImpl.updateStatus(execution,'Submited')}
传入Submited,表示用户提交了申请。
4.2 部门经理审批配置
部门经理打开软件就需要能看到他的代办,这种user task只需要调用获取部门经理的方法。
properties->Main Config->candidate user->${leaveServiceImpl.getDeptManager(execution)}
4.3 人事审批
调用获取人事经理的方法
properties->Main Config->candidate user->${leaveServiceImpl.getHrManager(execution)}
4.4 审批通过修改审批单状态
这里还是调用修改审批单状态的方法,只不过这里需要传审批通过的状态参数
properties->Main config->Task Type->选择Express表达式->Expression填写:${leaveServiceImpl.updateStatus(execution,'ok')}
4.5审批没有通过的修改审批单状态
properties->Main config->Task Type->选择Express表达式->Expression填写:${leaveServiceImpl.updateStatus(execution,'no')}
4.6 审批通过或拒绝路由分支线的配置
路由分支需要根据传入来的参数来确定接下来走那条线,如果用户前端传来的参数和本分支线的条件匹配就会走这个分支线。
通过->选中分支线->Main Config->Condition->${result=='yes'}
拒绝->选中分支线->Main Config->Condition->${result=='no'}
其中result就是前端传来的审批结果状态,这个状态是要封装在map里面的,这个具体看后面的讲解。
5.具体业务实现代码依次详解
5.1 用户在界面填写表单后提交请假申请单代码。
这一步就是用户提交请假单了,线保存这个请假单然后再启动流程。
5.1.1 保存请假单启动流程代码
LeaveInfo leaveInfo=new LeaveInfo();//请假单实体 leaveInfo.setMessage("我要请假 去玩游戏"); leaveInfo.setStatus("wait"); leaveService.apply(leaveInfo);//保存请假单 leaveService.startProcess(leaveInfo.getId()+"");//把请假单的id作为流程key启动流程
5.1.2 请假单实体代码就对应数据库,也是三个字段id,message,status具体去看源码
5.1.3 保存请假单就是mybatis inser方法保存到数据库,具体去看源码
5.1.4 startProcess启动流程代码
@Resource private RuntimeService runtimeService;//直接引入用就可以 public void startProcess(String bizKey) { runtimeService.startProcessInstanceByKey("LeaveProcess",bizKey);//LeaveProcess就是前面填写的流程的id }
5.2 获取部门经理代码
上面用户提交了请假单,下面是要部门经理来审批的,所以流程要转到部门经理那里去,那么部门经理是谁?怎么转?
在流程图中配置了获取部门经理的表达式,我这里都写的很简单,你自己的根据你自己的业务系统来写。
public List<String> getDeptManager(DelegateExecution delegateExecution) { return Arrays.asList("m1","m2");//直接返回两个部门经理的id }
5.3 部门经理获取待办任务
前面两步,提交了请假单,启动了流程,流程引擎也把流程转给了我的方法返回去的部门经理。那现在就是要部门经理登陆到系统获取到待办任务了。
List<Task> tasks=leaveService.getToDoListByUserId("m1");//m1就是前面一个部门经理的id
service获取代办的具体实现
@Resource private TaskService taskService;//引入直接用 public List<Task> getToDoListByUserId(String userId) { return taskService.createTaskQuery().processDefinitionKey("LeaveProcess").taskCandidateOrAssigned(userId).list();//传入流程id,和当前用户id }
5.4 部门经理审批
部门经理前端选择是否批准后 后台的实现审批代码:
leaveService.examine("m1","50010","no");
service的具体实现
@Resource private TaskService taskService; @Override public void examine(String userId,String taskId,String result) { taskService.claim(taskId,userId); Map<String,Object> map=new HashMap<>();//这个map中的参数都会传到流程上去 map.put("result",result);//流程上的路由分支线根据result参数来判断要走哪个分支 taskService.complete(taskId,map);//taskId就是查询代办中task的id }
5.5 获取人事经理代码-人事经理查询代办-人事经理审批
人事经理的业务代码其实和部门经理一样,不一样的是人员id。这里就不贴代码解释了。
5.6 审批完成修改请假单状态
人事经理审批完成后,最后有个service task是配置的修改请假单状态的方法,具体调用方法的实现,也是一样
public void updateStatus(DelegateExecution delegateExecution, String status) { String processId=delegateExecution.getProcessInstanceBusinessKey();//获取到流程key LeaveInfo leaveInfo=leaveDao.selectById(Integer.valueOf(processId));//获取到请假单 if(leaveInfo!=null){ leaveInfo.setStatus(status); } leaveDao.update(leaveInfo);//修改状态 }
总结:
最重要的就是第五点,是从一整个流程来讲的代码如何实现:提交请假单-启动流程-流程引擎获取部门经理-流程引擎转给部门经理-部门经理获取代办-部门经理审批-路由分支根据传审批结果传来的result来判断走哪个分支-(人事经理和部门经理一样的流程)-修改审批结果到请假单。具体的代码还请看git源码。