1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > 请假流程如何快速实现(OA )呢?:Activiti工作流

请假流程如何快速实现(OA )呢?:Activiti工作流

时间:2022-06-09 00:09:54

相关推荐

请假流程如何快速实现(OA )呢?:Activiti工作流

大家好,

在公司中,每个人都需要经常创建或者审批一些流程,比如说转正申请请假流程出差申请等等

那么,你有没有想过,要是你,你会如何实现这些流程的控制逻辑呢?

比如说请假申请,首先需要提前定义好一个流程模板吧,包括当请假天数大于 3 天的话,需要公司级的领导审批等这些规则

然后当某个员工发起请假申请时,根据这个员工所在的部门以及请假天数等信息,便可以确定其具体的流程信息,包括每个节点的审批人

在任何一个审批节点,都需要看到这个流程的历史审批信息以及将来要走的流程吧,所以还需要将完成的和将要完成的任务保存下来

你应该很容易想到,我们可以通过表的字段状态来进行流程的这些逻辑控制

但是呢,简单的流程的话,还可以实现,流程一旦复杂一点,不仅需要实现的代码会增加,而且需要操作的表的数量也特别多,逻辑只会更复杂

那么,有没有现成的工作流框架,可以直接拿来使用,轻松实现这些逻辑,实现流程的自动化控制呢?

答案是肯定的,今天带领大家认识的就是一个专门用来管理工作流的框架:Activiti

一 理论篇

1 实现逻辑

Activiti 就是使用BPMN 2.0进行流程建模、流程执行管理,那么,BPMN又是什么呢?

BPMN(Business Process Model AndNotation)- 业务流程模型和符号 是由BPMI(BusinessProcess Management Initiative)开发的一套标准的业务流程建模符号,使用BPMN提供的符号可以创建业务流程

定义好的流程模板,最终会被存储至数据库表中,而它的实现逻辑其实就是封装了诸多流程控制的表的操作,提供给开发人员一些快捷操作的 API ,来进行快捷的工作流管理

2 实现步骤

使用 Activiti 这种工作流框架大致都分为以下几个步骤:

流程定义

部署流程定义

启动流程实例

查询当前用户的待办任务

完成任务

说明:

流程定义就相当于是一个个的流程模板,比如预先定义好的请假流程、出差流程模板,而流程实例则是由各个员工发起的实实在在的流程,流程实例一旦创建,那么这个流程需要经历哪些审批环节,每个环节由哪个(或者哪些)人负责审批,便完全确定下来了

流程定义与流程实例的关系,你也可以理解为类与对象实例的关系。一个是静态的,一个则是真正被拿来使用的,相对动态

3 Service

Activiti 提供了几个Service类,用来管理工作流,常用的有以下四项:

1)RepositoryService:提供流程定义和部署等功能。比如说,实现流程的的部署、删除,暂停和激活以及流程的查询等功能

2)RuntimeService:提供了处理流程实例不同步骤的结构和行为。包括启动流程实例、暂停和激活流程实例等功能

3)TaskService:提供有关任务相关功能的服务。包括任务的查询、删除以及完成等功能

4)HistoryService:提供 Activiti 引擎收集的历史记录信息服务。主要用于历史信息的查询功能

还有以下两项:

**1)**ManagementService:job 任务查询和数据库操作

**2)**DynamicBpmnService:无需重新部署就能修改流程定义内容

4 认识表结构

二 实战篇

以下进入实战环节,分别从生成 25 张表运行第一个Activiti流程实例,快速认识这个工作流框架的简单易用性

这两个例子,采用 Activiti7 版本,需要预先引入如下依赖:

<dependencies><dependency><groupId>org.activiti</groupId><artifactId>activiti-engine</artifactId><version>7.1.0.M6</version></dependency><dependency><groupId>org.activiti</groupId><artifactId>activiti-spring</artifactId><version>7.1.0.M6</version></dependency><dependency><groupId>org.activiti</groupId><artifactId>activiti-bpmn-model</artifactId><version>7.1.0.M6</version></dependency><dependency><groupId>org.activiti</groupId><artifactId>activiti-bpmn-converter</artifactId><version>7.1.0.M6</version></dependency><dependency><groupId>org.activiti</groupId><artifactId>activiti-json-converter</artifactId><version>7.1.0.M6</version></dependency><dependency><groupId>org.activiti</groupId><artifactId>activiti-bpmn-layout</artifactId><version>7.1.0.M6</version></dependency><dependency><groupId>org.activiti.cloud</groupId><artifactId>activiti-cloud-services-api</artifactId><version>7.0.0.Beta1</version></dependency><!--mysql连接--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.29</version></dependency><dependency><groupId>commons-dbcp</groupId><artifactId>commons-dbcp</artifactId><version>1.4</version></dependency><!--lombok工具--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.24</version><optional>true</optional></dependency><dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-slf4j-impl</artifactId><version>2.17.2</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency><dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.11.0</version></dependency></dependencies>复制代码

然后来看看如何生成25张表

(一) 生成 25 张表

1 代码编写

1) activiti.cfg.xml 文件配置

我们在resources目录下,创建一个文件 activiti.cfg.xml ,主要用来配置数据库的信息

<?xmlversion="1.0"encoding="UTF-8"?><beansxmlns="/schema/beans"xmlns:xsi="/2001/XMLSchema-instance"xsi:schemaLocation="/schema/beans/schema/beans/spring-beans.xsd"><!--配置数据库dataSouce信息--><beanid="dataSource"class="mons.dbcp.BasicDataSource"><propertyname="driverClassName"value="com.mysql.cj.jdbc.Driver"/><propertyname="url"value="jdbc:mysql://localhost:3306/activiti"/><propertyname="username"value="root"/><propertyname="password"value="123456"/><propertyname="maxActive"value="3"/><propertyname="maxIdle"value="1"/></bean><beanid="processEngineConfiguration"class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration"><propertyname="dataSource"ref="dataSource"/><!--配置模式true:自动创建和更新表--><propertyname="databaseSchemaUpdate"value="true"/></bean></beans>复制代码

Activiti7 支持h2、mssql、mysql 、db2、oracle hsql以及postgres7种数据库,我们在这里使用mysql数据库

分别配置mysql数据库的url数据库驱动以及用户名密码等信息,然后通过定义类型为 StandaloneProcessEngineConfiguration 的对象 processEngineConfiguration,并指定其配置模式为databaseSchemaUpdate,表示每次启动项目,均会检查数据库中的表,如果不存在,则创建,否则检查更新

2)代码编写

通过 ProcessEngines.getDefaultProcessEngine() 方法,实现25张表的自动创建

@Slf4jpublicclassTestCreat{/***数据库表结构的创建*/@TestpublicvoidtestCreateDbTable(){/***创建processEngine时,会自动加载/resources目录下的activiti.cfg.xml文件*进行mysql数据库中表的创建*/ProcessEngineprocessEngine=ProcessEngines.getDefaultProcessEngine();log.info(processEngine.getName());}复制代码

在创建processEngine时,Activiti 会自动加载/resources目录下的 activiti.cfg.xml 文件进行mysql数据库中表的创建

感兴趣的话,可以一路点下去,看看这个方法的源码。

一直到 ProcessEngines 的 init() 方法(当系统判断,当前还未在数据库中进行过表的创建动作时),会发现其加载的就是resource目录下的 activiti.cfg.xml 文件

当然要是Spring项目,则加载的是activiti-context.xml文件。Spring与 Activiti 的集成,本篇暂且不看,留在下一篇去讨论

2 运行

启动运行,发现控制台中日志打印如下

通过执行 org/activiti/db/create/activiti.mysql.create.engine.sql 这个sql文件,完成了 Activiti 所需要的25张表的创建动作

检查数据库,你会发现,数据库中便生成了25张表

(二) 第一个 activiti 流程实例

Activiti 在eclipseIDEA中均有流程定义的插件,在IDEA中需要安装的插件如下

插件安装完毕之后,重启IDEA,然后在resources目录下创建一个文件夹bpmn(专门用于存储 Activiti 的流程文件)

1 流程定义

1)流程文件创建

如下图所示,创建我们的第一个bpmn文件

右键,New -> New Activiti 6.x BPMN 2.0 file->填写文件名称,创建好之后发现,其实该文件就是一个 xml 文件

右键该文件,点击:View BPMN(Activiti) Diagram,便可以进行流程的设计了

2)流程文件设计

在空白处,右键点击

可以看到有分别有流程启动事件活动架构网关边界事件紧急捕获紧急抛出事件以及结束事件等,点击对应的右三角,便可以创建对应的事件或活动

比如

通过拖动各个事件右上角的箭头,即可画一条连线。这里我们创建了一个比较简单的请假流程

需要注意,点击空白处,可以更新流程定义的名称与 id,这里,我们的流程定义 idleaveApplication流程定义名称请假流程定义

然后,分别指定两个活动的名称与负责人。一个流程模板每个工作节点的负责人当然不可能是固定的,所以,在这里我们采用 Activiti 所支持的UEL表达式,将负责人定义为动态参数:assignee0assignee1

- 创建申请

- 审批申请

好了,这样我们就定义好了一个简单的流程,接下来,进行流程的部署操作,也就是说需要把我们所创建的流程定义文件,真正与数据库的表关联起来

2 流程部署

/***部署流程--RepositoryService*/@TestpublicvoidtestDeploy(){ProcessEngineprocessEngine=ProcessEngines.getDefaultProcessEngine();RepositoryServicerepositoryService=processEngine.getRepositoryService();Deploymentdeploy=repositoryService.createDeployment().name("请假申请流程定义").addClasspathResource("bpmn/leaveApplication.bpmn20.xml").deploy();log.info("流程部署id:{}",deploy.getId());log.info("流程部署名称:{}",deploy.getName());}复制代码

因为需要对流程本身进行部署操作,而流程本身属于静态资源,需要进行存储的,所以采用 RepositoryService 这个服务的API进行部署操作

运行该测试方法,发现控制台对以下三张表分别进行了插入记录操作

act_re_procdef(流程定义数据表)act_re_deployment(部署信息表)act_ge_bytearray(二进制数据表,存储流程定义时的资源文件信息,如这里的bpmn/leaveApplication.bpmn20.xml文件)复制代码

也就是说我们将这个流程定义文件中的信息分别存入了数据库中关于流程定义的表中

3 启动流程实例

/***启动流程--RuntimeService**/@TestpublicvoidtestStartProcess(){ProcessEngineprocessEngine=ProcessEngines.getDefaultProcessEngine();RuntimeServiceruntimeService=processEngine.getRuntimeService();Map<String,Object>map=newHashMap<>();map.put("assignee0","张三");map.put("assignee1","王经理");ProcessInstanceinstance=runtimeService.startProcessInstanceByKey(key,map);System.out.println("流程定义id:"+instance.getProcessDefinitionId());System.out.println("流程实例id:"+instance.getId());System.out.println("当前活动的id:"+instance.getActivityId());}复制代码

启动流程时,分别指定各个任务的负责人,上述代码表示该请假流程是由张三发起的,审批人是王经理

由于启动一个流程,就表示是流程实例被运行起来了,那么,就使用 RuntimeService 的 startProcessInstanceByKey() 方法进行,其中参数key表示指定所启动的流程定义,而map则是为其启动之后的流程实例赋值

启动一个流程实例,我们的预期就是完成 Start event 事件,流程进入到张三的“创建申请”这个步骤

那么就会执行完 Start event 这个任务节点,并将相应的信息存入历史信息表中,然后将下一步要执行的“创建申请”这个任务节点的信息,存入运行时信息表中。具体是怎样的呢?

我们运行该启动方法,观察控制台,发现所操作的表如下:

1)历史表ACT_HI_VARINST历史变量表ACT_HI_TASKINST历史任务实例表ACT_HI_PROCINST历史流程实例表ACT_HI_ACTINST历史节点表ACT_HI_IDENTITYLINK历史人员参与表2)运行时表ACT_RU_EXECUTION运行时流程执行实例ACT_RU_TASK运行时任务节点表ACT_RU_IDENTITYLINK运行时人员参与表ACT_RU_VARIABLE运行时变量表复制代码

通过查看这些表的变化,结果是符合上述预期的。比如查看一下ACT_RU_TASK表,会发现任务节点信息已被存入表中,表示当前将要进行的任务就是创建申请

4 查询代表任务

/***查询个人待执行的任务--TaskService*/@TestpublicvoidtestFindPersonalTaskList(){ProcessEngineprocessEngine=ProcessEngines.getDefaultProcessEngine();TaskServicetaskService=processEngine.getTaskService();List<Task>taskList=taskService.createTaskQuery().processDefinitionKey(key).taskAssignee("张三").list();for(Tasktask:taskList){System.out.println("流程实例id:"+task.getProcessInstanceId());System.out.println("任务id:"+task.getId());System.out.println("任务负责人:"+task.getAssignee());System.out.println("任务名称:"+task.getName());}}复制代码

通过TaskService进行查询,分别通过请假流程的key用户名称,查询该用户名下的所有任务

5 完成任务

@TestpublicvoidcompleteProcess(){Stringassignee="张三";/***完成任务*/ProcessEngineprocessEngine=ProcessEngines.getDefaultProcessEngine();TaskServicetaskService=processEngine.getTaskService();Tasktask=taskService.createTaskQuery().processDefinitionKey(key).taskAssignee(assignee).singleResult();plete(task.getId());}复制代码

首先查询到所需要完成的任务,然后通过TaskService的 complete() 方法进行任务的完成动作(当然实际业务中,需要先进行任务的具体操作,比如添加自己的审批意见等之后才会点击任务的完成,进入下一步骤)

完成任务时,通过查看日志,发现其与启动任务的任务节点所操作的表类似,就是将当前节点所完成的任务转存到历史信息表中,再将下一步需要完成的任务存入运行时信息表中

这里,我们完成创建申请的任务之后,表里面当前需要执行的任务,变成了“审批申请”

说明任务已经成功得到了执行 接下来,采用同样的方法,完成审批申请的任务,我们可以猜想一下,表中的数据又会得到怎样的变化

/***完成任务--TaskService*/@TestpublicvoidcompleteTask(){//Stringassignee="张三";Stringassignee="王经理";/***完成任务*/ProcessEngineprocessEngine=ProcessEngines.getDefaultProcessEngine();TaskServicetaskService=processEngine.getTaskService();Tasktask=taskService.createTaskQuery().processDefinitionKey(key).taskAssignee(assignee).singleResult();plete(task.getId());}复制代码

是的,依旧是一样的操作,将当前节点所完成的任务转存到历史信息表中,只是这里已经是最后一步任务了,所以执行完成之后,也会直接执行 End event

所以,运行完这个步骤之后,我们会发现 act_ru_task 表变成了空的,而 act_hi_taskinst 表中可以看到历史所有执行过的任务实例,包括启动事件、创建申请、审批申请以及结束事件

总结

好了,到这里,我们就轻松完成了一个请假流程的流程的定义流程定义的部署流程实例的启动任务完成的所有操作

会发现,其实Activiti 的逻辑其实就是通过控制表来进行具体的任务状态操作的。每一步的操作都需要根据一定的逻辑关系,更新数张表来进行控制的

而这些操作,都由 Activiti 框架帮助我们封装好了,提供给我们的只是一个个服务的API,从而大大简化了工作流的操作,所以还不快用起来?

文章演示代码地址:

/helemile/Sp…

嗯,就这样。每天学习一点,时间会见证你的强大~

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。