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 (开发的时候参阅)

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

如果java底子不好的可以试试XJR快速开发平台的可视化流程开发。整合activity工作流引擎的图形化流程设计器,通过可视化配置界面。只需要拖拽组件,拼接流程,就能实现各层的审批。

 

 它具体的实现过程就是:

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

<!--添加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>

1.使用插件画工作图

  

 Idea当中加入插件之后,画如下的流程图:

整个图的信息:

 

 请假节点的信息:

 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.创建数据库、执行方法

 

 接下来就测是第一种的到流程引擎的方式

代码如下:

@Test

public void shouldAnswerWithTrue()

{

    //得到流程引擎的方式一

    ProcessEngineConfiguration pec =    ProcessEngineConfiguration.createStandaloneProcessEngineConfiguration();
下面是设置数据源

    pec.setJdbcUrl("jdbc:mysql://localhost:3306/db_activiti?characterEncoding=utf-8");

    pec.setJdbcDriver("com.mysql.jdbc.Driver");

    pec.setJdbcUsername("root");

    pec.setJdbcPassword("root2");
设置自动生成表的属性是true, DB_SCHEMA_UPDATE_TRUE它的值就是true

    pec.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);

    ProcessEngine processEngine = pec.buildProcessEngine();
}

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

乱码问题:

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。通用数据, 用于不同场景下,如存放资源文件。
 

第二种获取流程引擎的方法

创建核心配置文件,但是配置文件的名字必须是activiti.cfg.xml原因下面会提到:然后使用加载配置文件的方式产生流程引擎,当然我们的表已经生成,此时就不再执行方法,附上代码:

//得到流程引擎的方式二,加载配置文件
ProcessEngineConfiguration pec2 = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti.cfg.xml");
ProcessEngine processEngine1 = pec2.buildProcessEngine();

第三种获取流程引擎的方法

//得到流程引擎的方式三,利用底层封装,来加载配置文件,只需要调用方法即可
ProcessEngine pec3 = ProcessEngines.getDefaultProcessEngine();

原因就是源码当中有一个init的方法,里面他会自动去加载配置文件:

 

 这也就是为什么配置文件的名字是固定,不可变的了,因为默认加载的就是这个配置文件,如果你换了配置文件的名字,会报异常

 

 以下附上配置文件的代码:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans  
      http://www.springframework.org/schema/beans/spring-beans.xsd">


  <bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneInMemProcessEngineConfiguration">

 

以下是数据源的配置

 <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/db_activiti?characterEncoding=utf-8"></property>
        <property name="jdbcDriver" value="com.mysql.jdbc.Driver"></property>
        <property name="jdbcUsername" value="root"></property>
        <property name="jdbcPassword" value="root2"></property>

以下是自动生成表二设置,和第一种方法的直接设置是一样的

     <property name="databaseSchemaUpdate"    value="true"></property>
    </bean>
 
</beans>

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之路长漫漫,唯有的是努力+坚持!!!

 ————————————————

版权声明:本文为CSDN博主「非往」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_42112846/article/details/81106814

 

猜你喜欢

转载自www.cnblogs.com/wosoft/p/12418344.html