Activiti 工作流框架

工作流
 

Activiti是一个项目的名称,Alfresco软件在2010年5月17日宣布Activiti业务流程管理(BPM)开源项目的正式启动,其首席架构师由业务流程管理BPM的专家 Tom Baeyens担任。

 

Activiti项目是一项新的基于Apache许可的开源BPM平台,从基础开始构建,旨在提供支持新的BPMN 2.0标准,包括支持对象管理组(OMG),面对新技术的机遇,诸如互操作性和云架构,提供技术实现。

 

创始人Tom Baeyens是JBoss jBPM的项目架构师,以及另一位架构师Joram Barrez,一起加入到创建Alfresco这项首次实现Apache开源许可的BPMN 2.0引擎开发中来。

 

Activiti是一个独立运作和经营的开源项目品牌,并将独立于Alfresco开源ECM系统运行。 Activiti将是一种轻量级,可嵌入的BPM引擎,而且还设计适用于可扩展的云架构。 Activiti将提供宽松的Apache许可2.0,以便这个项目可以广泛被使用,同时促进Activiti BPM引擎和的BPMN 2.0的匹配,该项目现正由OMG通过标准审定。

 

Activiti官方主页:http://www.activiti.org/index.html

下载:http://www.activiti.org/download.html

用户指南:http://activiti.org/userguide/index.html (用户指南来学习Activiti)

在线API文档: http://activiti.org/javadocs/index.html (开发的时候参阅)

 

 

其实简单的来说工作流就是将需要完成某个流程的各个任务组合起来,实现自动化的去完成这些任务,优点就是它实现了工作流程的自动化并且大大提高企业的运作效率;

 

它具体的实现过程就是:

当然最先应该做的就是创建项目导入依赖:

<!--添加Activiti工作流的支持 一般需要exclusions -->
<dependency>
  <groupId>org.activiti</groupId>
  <artifactId>activiti-engine</artifactId>
  <version>5.19.0.2</version>
</dependency>
<!--添加Activiti工作流对Spring的支持-->
<dependency>
  <groupId>org.activiti</groupId>
  <artifactId>activiti-spring</artifactId>
  <version>5.19.0.2</version>
</dependency>
<dependency>
  <groupId>org.activiti</groupId>
  <artifactId>activiti-bpmn-model</artifactId>
  <version>5.19.0.2</version>
</dependency>

<!-- mysql驱动:根据数据库的版本选择驱动版本 -->
<dependency>
  <groupId>mysql</groupId>
  <artifactId>mysql-connector-java</artifactId>
  <version>5.1.34</version>
</dependency>

 

 

  安装activiti插件

    

点击菜单【File】-->【Settings...】打开【Settings】窗口。

点击左侧【Plugins】按钮,在右侧输出"actiBPM",点击下面的【Search in repositories】链接会打开【Browse Repositories】窗口。

 

进入【Browse Repositories】窗口,选中左侧的【actiBPM】,点击右侧的【Install】按钮,开始安装。

创建BPMN文件

点击菜单【File】-->【New】-->【BpmnFile】

 

1.使用插件画工作图

 

整个图的信息:

请假节点的信息:

Name是这个任务的名称“:

Assignee是执行这个任务的人,此处的意思就是项目经理要请假,其实项目经理这个地方是个变量,设置成为变量的意思就是任何人都可以,而不是只是在这儿设置的项目经理了,当然为了方便理解我们就这样做了;

 

然后就是审批节点的信息:

任务是审批,审批的人是总监

 

然后我们将我们创建的这个文件leave.bpmn赋值一份 然后将其后缀给为xml

然后我们可以看到配置信息:

 

除了头文件以及小编下面截取出来的,其余的都是坐标信息:
首先是流程节点;
<process id="myProcess_1" isClosed="false" isExecutable="true" processType="None">
开始节点
 
  <startEvent id="_2" name="StartEvent"/>
结束节点
 
  <endEvent id="_3" name="EndEvent"/>
第一个请假节点且表面请假的人是项目经理
 
  <userTask activiti:assignee="项目经理" activiti:exclusive="true" id="_4" name="请假"/>
第二个审批节点批准的认时总监
 
  <userTask activiti:assignee="总监" activiti:exclusive="true" id="_5" name="审批"/>
下面三个就是之前画的流程图中的三条线:2~4、4~6、5~3
这是于你生成节点的顺序有关的,最先拉经来的胖子在前面这里:
2是开始
3是结束
4是请假
5是审批
 
  <sequenceFlow id="_6" sourceRef="_2" targetRef="_4"/>
 
  <sequenceFlow id="_7" sourceRef="_4" targetRef="_5"/>
 
  <sequenceFlow id="_8" sourceRef="_5" targetRef="_3"/>
 
</process>


以上就是新建的这个bmp文件的xml表示;

 

2.创建数据库、执行方法

在执行之前还需要解决一个问题:

乱码问题:

Settings—>Editor—>File Encodings utf-8

idea安装目录bin目录:idea.exe.vmoptions;idea64.exe.vmoptions,在文件末尾添加 -Dfile.encoding=UTF-8 ,然后重启idea

 

 

执行的结果:

然后我们去检查数据库就可以发现它自动生成的表:

5种数据库表说明:

Activiti的后台是有数据库的支持,所有的表都以ACT_开头。 第二部分是表示表的用途的两个字母标识。用途也和服务的API对应。

ACT_RE_*: 'RE'表示repository。 这个前缀的表包含了流程定义和流程静态资源 (图片,规则,等等)。
ACT_RU_*: 'RU'表示runtime。 这些运行时的表,包含流程实例,任务,变量,异步任务,等运行中的数据。 Activiti只在流程实例执行过程中保存这些数据, 在流程结束时就会删除这些记录。 这样运行时表可以一直很小速度很快。
ACT_ID_*: 'ID'表示identity。 这些表包含身份信息,比如用户,组等等。
ACT_HI_*: 'HI'表示history。 这些表包含历史数据,比如历史流程实例, 变量,任务等等。
ACT_GE_*: 'GE'表示general。通用数据, 用于不同场景下,如存放资源文件。
 

3.部署

 

在创建完成之后就是部署

部署流程图就是要将这个流程图部署到流程框架当中去,并且将数据添加到数据库,这个步骤只需要一次即可,因为是可以部署的任务是可以重复使用的,上面执行方法船舰表也是一样,只需要一次即可;

因为有了配置文件,下面的测试方法当中我们使用的就是第三种方法:

以下就是我们的部署代码:

部署我们首先应该得到的就是部署的服务对象

@Test
public  void  deploy(){
    ProcessEngine pec=ProcessEngines.getDefaultProcessEngine();

部署的服务对象
    RepositoryService repositoryService = pec.getRepositoryService();

部署请假任务:
    Deployment deploy = repositoryService.createDeployment()
            .addClasspathResource("leave.bpmn")
            .name("请假")
            .deploy();

审批任务会再请假之后自动开启
    System.out.println("请假部署ID:"+deploy.getId());
   
}

因为是两个任务我们分别部署,在部署完毕之后的输出是:

然后我们在去看数据库:

在定义表中(act_re_procdef):

我们可以很清楚的看到我们定义的任务,它们的key是myProcess_1,也就是我们之前画图时,整个图的ID,可以会看;

在部署表(act_re_deployment)当中:

我们可以很清楚的看到我们部署的两个任务请假以及审批

之后我们去看资源表(act_ge_bytearray):

我们可以看到我们传到数据库的的资源包括生成的png的图片都在这里,其实生成了以后我们就可以删除我们在项目当中创建的pnm文件了,因为文件以及保存到了数据库所以那些也就没有必要了;

 

4.开始任务

首先我们也必须根据流程引擎对象,来得到我们的运行时服务对象,然后根据我们定义表当中的key来得到流程实例,代码如下:

@Test
public void start(){

根据流程引擎对象得到运行时服务对象:
    ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
    RuntimeService runtimeService = defaultProcessEngine.getRuntimeService();

根据key得到流程实例
    ProcessInstance myProcess_1 = runtimeService.startProcessInstanceByKey("myProcess_1");
输出运行时流程实例id以及我们启动的流程它的一个定义id  

 System.out.println("流程实例id:"+myProcess_1.getId());
    System.out.println("流程定义ID:"+myProcess_1.getProcessDefinitionId());
}

运行之后结果如下:

流程定义ID我们知道,但是运行时流程id在哪里呢?

 

我们来看我们的运行时任务表:

我们在设立就可以看见我们刚开始的一个任务,就是请假,它的EXECUTION_ID_是2501,而这条任务的id是2504,然后执行的任务name是请假,请假的人是ASSIGNEE_项目经理

 

在这里有些读者肯会有疑惑,就是我们部署了两个任务,

为什么启动了之后就只有请假这一个任务了呢?

 

解释一下:原因就是因为Activiti是流程框架,它的节点有特殊性,也就是一个节点的启动是以上一个节点的结束而被触发的,所以在这里当请假这个任务没有完成的时候,审批这个任务是不会出现的,只有当你的请假任务完成了之后,审批的任务就会出现在你运行时的任务表当中,这时你只需要去完成审批的任务即可;

 

注意:之前说个我们这里只是以项目经理为例,当这里这里编程变量的时候这里可能会同时出现多个请假的任务,就是多线程,多个请假任务同时进行;

 

4.完成任务

同样完成任务我们首先就要得到我们用来完成任务的服务类,我们是根据运行时任务表当中的id来完成的,具体代码如下:

@Test
public void complete(){
    ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
    TaskService taskService = defaultProcessEngine.getTaskService();

根据ID完成任务
    taskService.complete("2504");
}

完成之后我们去刷新我们的任务表:

这时候出现的就是我们的审批任务了,由于请假任务的完成审批任务就自动被触发了,所以我们不需要再去启动审批任务,而是由框架自动初发;

 

在去看我们的历史记录表(act_hi_actinst)

由下面的一个图可以看出我们的开始节点在你开始这个任务的时候是跟随开启的任务是一起进来的时间是一样的,而它们的结束时间是不一样的,请假的结束时间就是我们完成请假任务的时间

而我们完成请假任务的时间恰恰是审批任务的开始时间,而在我们没有完成审批任务之前我们的审批任务是没有结束时间的,因为这个时候它还是待处理此状态;

 

此时我们在去完成处于运行时任务表当中的审批任务它的id时5002,代码如下:

@Test
public void complete2(){
    ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
    TaskService taskService = defaultProcessEngine.getTaskService();
    taskService.complete("5002");
}

同样我们在去刷新我们的运行时任务表:

空空如也,所以说我们的审批任务也完成了;

在这里我们就会发现一个流程框架的机制:

 

那就是:当一个任务被开始的时候,它会出现在我们的运行时任务当中,当这个任务完成了,这个任务的记录就会出现在我们的历史记录表当中,而这时运行时任务表时空的,简单的说,其时运行时的几张表充当的就是相当于电脑内存的作用,做个类比它们就是流程框架的内存;

 

这时候我们在回过头去看历史记录表:

此时审批任务也已经完成,而他完成的时间,也正好就是我们结束节点开始的时间,而结束节点可开始节点一样,它们的开和结束时间是一样的,因为它们一旦开始就不会由等待;

 

以上就是我们整个流程框架的一个过程,当然我们这里只是以单线程方式来演示的,实际应用当中,往往是多个任务同时进行的,而流程图也比这个复杂的多,所以it之路长漫漫,唯有的是努力+坚持!!!

 

Avtiviti

----流程变量(Variables)

那么我们首先看:

 

流程变量是什么?

在流程实例运行过程中,难免要记录或者保存一些数据,然后运行到某个节点的时候,取数据查看,或者是后面学到流程分支的时候 判断流程走向,都要用到一些数据存储。
流程变量,顾名思义就是流程中用来存储数据的变量;
Activiti中基本支持所有的基本数据类型作为流程变量,以及支持序列化对象,所以也可以存一个对象
根据一个流程定义可以启动很多流程实例,每个流程实例里的流程变量都是独立的,互不影响
主要用途:

在执行流程的过程中,传递参数。

接下来我们来将流程变量加入来开发整个流程:

开始----leave----审批-------结束

整个流程的id是:Stuprocess(之后就是用这个key来开启线程)

我们将这个文件复制,然后将它的后缀改为.xml我们就可以看到这张图的信息,因为bpmn文件其本质就是xml文件;

具体的信息如下:

这是主要的头部信息,余下的是坐标这里就不解释了,因为上一篇文章有详细的介绍,在这里我们只看关键信息,如:

id=Stuprocess

第一个节点任务是leave操作的人是傅蕤

第二个节点的任务是审批,操作的人是父王

然后以前以后就是开始和结束节点;

这就是这个图所要描述的信息;

了解了基的任务信息之后,我们就来进行流程的部署:

 

deploy
当然在部署之前我们首先要得到的就是,流程引擎对象:

 

然后我们就来部署:

public void deploy(){
 
得到部署的服务对象:
 
    RepositoryService repositoryService = pec.getRepositoryService()
部署任务
  Deployment deploy = repositoryService.createDeployment()
将整个图作为资源加入
 
            .addClasspathResource("Variables.bpmn")
这个任务部署的名字是请假
 
            .name("请假")
开始部署
 
            .deploy();
打印部署的id
 
    System.out.println("部署id+:"+deploy.getId());
 
}


部署完成之后我们可以在部署表中看见部署的信息,以及在定义表当中看到Stuprocess key的定义;

以上的画图以及部署只需要做一些次就还可以,因为他们是可以重复使用的;

这里再上篇文章当中有详细的价绍,这里就不再赘述;

start

再部署完成之后,我们就要启动我们部署好的任务

 

2 下面是启动的代码:

 

public void startAct(){
得到运行时service
    RuntimeService runtimeService = pec.getRuntimeService();

更具关键字启动我们的流程
    ProcessInstance stuProcess = runtimeService.startProcessInstanceByKey("StuProcess");

打印初流程定义的id以及流程实例的id
    System.out.println("流程实例id:"+stuProcess.getId());
    System.out.println("流程定义id:"+stuProcess.getProcessDefinitionId());
}

 

在启动完成之后,我们在任务表当中我们就可以看到,我们部署的流程的第一个任务;

 

在这里我们就可以加入流程变量了,流程变量可以在运行时加也可以在完成任务的时候加

用的就是:runService和TaskService两个服务对象,这里我们在完成任务的时候来加这个变量。

 

 

3.完成

 

在这接招两种加入流程变量的方法:

一种是直接设置值

一种是通过map的方式来添加值

由上图我们在源码当中可以看到的就是,完成的这个方法其内部是id和map集合来构成的

所以在完成任务的这个地方我们可以用两这方式来添加流程变量

 

但是在启动的时候也是可以的,下面是启动的源码:

它里面同样是可以来放置集合的;

此处我们在完成任务的时候来选择添加流程变量:

下面就是两种添加方式的代码:

public  void complete1(){
 
 
 
        TaskService taskService = pec.getTaskService();
首先,完成一个任务我们需要知道它的任务id,这个我们可以在启动之后的任务表当中看的到,就是它的主键
我们将其设置为一个字符串变量,来供后面使用
 
        String taskId="42503";
灰色的部分用的就是set方法来设置变量的
 
//        taskService.setVariable(taskId,"days",7);
 
//        taskService.setVariable(taskId,"reason","要去赚钱");
 
//        Student student=new Student(1,"傅往");
 
//        taskService.setVariable(taskId,"Student",student);
下面黑色的部分就是用集合的方式来设置流程变量的
 
        Map<String, Object> variables=new HashMap<>();
 
        variables.put("days",7);
 
        taskService.complete(taskId,variables);
 
    }


完成之后我们的请假惹任务就完成了,接下来就是审批任务,之前的文章这说到过,就是当我们的一个任务完成了,这个任务就从我们的任务表当消失了,而在历史表当中会有它的记录,对于它的时间我们也进行过详细的分析,大家可以取看前一篇博文;

 

这样我们就完成了第一个节点的任务;

接下来任务表当中出现的就是下一个任务,审批任务;

注意:在任务表当中,同一个流程的任务除了并状态下会都出现之外,一般同一流程的任务只会由一个,当然不同的人员操作虽然都是请假,但是他们的信息是不一样的,所以不能算是同一个;

 

 

接下来我们来完成第二个任务审批

 

//老师完成审批
 
    public  void complete2(){
 
同样审批也应该有的就是任务服务对象以及新产生审批任务的id
 
        TaskService taskService = pec.getTaskService();
 
        String taskId="42503";
在这里我们可以得到前面在完成第一个任务时设置的流程变两的值:
 
        int days = (int)taskService.getVariable(taskId, "days");
 
//        String reason = (String) taskService.getVariable(taskId, "reason");
 
//        Student student = (Student)taskService.getVariable(taskId, "Student");
 
//        System.out.println("天数"+days+"====="+"理由"+reason+"======"+"申请人"+student.getName());
 
        System.out.println("天数==="+days);
 
        taskService.complete(taskId);
 
    }


那么流程变量的值得到之后有什么作用呢?

主要有两个作用:

就是可以当作流程判断的条件值,因为真的流出是少不了判断的,在这里我们只是用简单的来做演示而已;
就是可以供操作者来,参考决策,在于前端整合之后就可以以界面的形式将这些信息显示出来了;
以上就是流程变量的作用以及关于他的一些基本操作;

 

接下来我们来介绍两个网关

排他性网管
什么意思呢就是两条路线你只能够走一个

下面是画的图以及信息:

我们用到得是排他性网管关按钮

表示得就是在不同得情况下直接转向不同得流程,从而进入不同测程序,再执行之前就进行了判断,而之前得是再自己看过了之后周期提交去判断时结束还是转向不同得处理方式;

平行网关


我们用的是平行网关按钮

 

下面是具体得图所示:

 

表示得就是在审批1和审批2之间只要是二者之中有一个没有完成那么这个流程就不能结束,而在具体的操作当中,当即将gohome执行完毕之后,两个审批任务是同时出现在表当中的,这就是在任务表当中会出现同一流程的多个任务的情况;

 

至于其它的部署,启动完成操作和之前的文章当中谈到的是一样的,大家可以自行去测试,在后面的文章当中,我们会逐步将这个流程框架整合到Spring当中去;

 

相关代码连接:https://github.com/Wuwenxu/study.git

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页