Activiti工作流简单入门

自jBPM创始人Tom离开之后,jBPM和Activiti就开始大相径庭,jBPM被迫使用新的LGPL协议,而Activiti则使用一种更为宽松的Apache License 2.0协议。不管使用jBPM还是Activiti,两者都遵循BPMN 2.0规范,都可满足项目的一般需求,相比于jBPM的,Activiti的使用起来不会进行太大的二次改动,但jBPM的则是使用的Drools较为强大的规则引擎作为后盾,至于两者谁优谁劣,需要在实际项目中权衡利弊。

目录[ - ]
BPMN 2.0
BPMN最初由业务流程倡议组织(BPMI)定案,现在BPMI并入OMG(Object Management Group)了,则由OMG建立规范和维护。
BPMN 2.0正式更名为(Business Process Model And Notation)业务流程符号和模型,也有人继续称呼为业务流程建模标记法(Business Process Modeling Notaion),不过无所谓,不管是jBPM,Activiti还是国人开发的FixFlow,都遵循BPMN规范。
Maven的配置
JBoss的的开源框架都是比较庞大的,不过相对Activiti的体积要小一点。下面为配置的依赖项。
<! - Junit的 - >
<依赖性>
    <的groupId>的junit </的groupId>
    <artifactId的>的junit </ artifactId的>
    <版本> $ {junit.version} </版本>
</依赖性>
 
<! - Activiti的 - >
<依赖性>
    <groupId>org.activiti</groupId>
    <artifactId>activiti-engine</artifactId>
    <version>${activiti.version}</version>
</dependency>
 
<dependency>
    <groupId>org.activiti</groupId>
    <artifactId>activiti-bpmn-layout</artifactId>
    <version>${activiti.version}</version>
</dependency>
 
<dependency>
    <groupId>org.activiti</groupId>
    <artifactId>activiti-spring</artifactId>
    <version>${activiti.version}</version>
</dependency>
 
<!--apache组件-->
...

整合数据库
为什么要整合数据库?如果不整合数据库,我们大可以使用Quartz这些框架来做流程任务。实际上,Work Flow是用于一种 长周期的几乎异步的项目运行环境中,并且我们时刻需要将工作流程的状态记录下来,就是一种既注重结果,又注重过程的事务中,因此,整合数据库很有必要。
下面为配置源数据的XML文件,并且将databaseSchemaUpdate属性配置为drop-create,即在运行前删除原有的数据内容。
?
<?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.StandaloneProcessEngineConfiguration">
        <property   name="databaseSchemaUpdate"   value="drop-create"/>
        <property   name="jdbcUrl"   value="jdbc:mysql://localhost:3306/db_activiti?useUnicode=true&amp;characterEncoding=utf-8"/>
        <property   name="jdbcDriver"   value="com.mysql.jdbc.Driver"/>
        <property   name="jdbcUsername"   value="root"/>
        <property   name="jdbcPassword"   value="****"/>
        <property   name="jobExecutorActivate"   value="true"/>
    </bean>
</beans>

默认配置文件名为activiti.cfg.xml,可以在源文件中找到。
另外,如果有必要,请将MySQL设置为区分大小写,即lower_case_table_names = 0。
数据内容会在运行前自动创建,详细表结构内容可参考官网完整信息。
创建工作流文件
由于BPMN规范的作用,一些高级的IDE会自动识别后缀为*.bpmn的文件,不过这些都无所谓,bpmn文件实际上就是XML文件,只是加上了一些图形的标记,如width、height、x和y的坐标,下面为一个招聘面试流程,只包含流程节点,不包含位置标记节点。
?
<?xml   version="1.0"   encoding="UTF-8"?>
<definitions   xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
             xmlns:activiti="http://activiti.org/bpmn"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             targetNamespace="Examples"
             xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL
             http://www.omg.org/spec/BPMN/2.0/20100501/BPMN20.xsd">
    <process   id="Interview"   name="某公司2012年实习生招聘流程">
        <documentation>招聘工作流程</documentation>
        <startEvent   id="start"   name="实习生招聘启动"/>
        <userTask   id="bishi"   name="笔试"   activiti:candidateGroups="人力资源部"/>
        <sequenceFlow   id="flow1"   name=""   sourceRef="start"   targetRef="bishi"/>
        <userTask   id="yimian"   name="技术一面"   activiti:candidateGroups="技术部"/>
        <sequenceFlow   id="flow2"   name=""   sourceRef="bishi"   targetRef="yimian"/>
        <userTask   id="ermian"   name="技术二面"   activiti:candidateGroups="技术部"/>
        <sequenceFlow   id="flow3"   name=""   sourceRef="yimian"   targetRef="ermian"/>
        <userTask   id="hrmian"   name="HR面"   activiti:candidateGroups="人力资源部"/>
        <sequenceFlow   id="flow4"   name=""   sourceRef="ermian"   targetRef="hrmian"/>
        <userTask   id="luyong"   name="录用,发放Offer"   activiti:candidateGroups="人力资源部"/>
        <sequenceFlow   id="flow5"   name=""   sourceRef="hrmian"   targetRef="luyong"/>
        <endEvent   id="end"   name="实习生招聘结束"/>
        <sequenceFlow   id="flow6"   name=""   sourceRef="luyong"   targetRef="end"/>
    </process>
 
</definitions>

为了便于阅读,一些高级IDE可以转化为图形符号,如下图:
测试运行
有了流程引擎的配置文件和流程文件后,就可以编写代码启动流程引擎并加载该流程文件了。测试清单如下:
?
@Test
public   void   processTests(){
    // 加载配置文件
    ProcessEngine processEngine = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti.cfg.xml").buildProcessEngine();
    RepositoryService repositoryService = processEngine.getRepositoryService();
    RuntimeService runtimeService = processEngine.getRuntimeService();
    repositoryService.createDeployment().addClasspathResource("Interview.bpmn").deploy();
    String processId = runtimeService.startProcessInstanceByKey("Interview").getId();
 
    TaskService taskService = processEngine.getTaskService();
    //得到笔试的流程
    System.out.println("\n***************笔试流程开始***************");
 
    List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("人力资源部").list();
    for   (Task task : tasks) {
        System.out.println("人力资源部的任务:name:"+task.getName()+",id:"+task.getId());
        taskService.claim(task.getId(), "张三");
    }
 
    System.out.println("张三的任务数量:"+taskService.createTaskQuery().taskAssignee("张三").count());
    tasks = taskService.createTaskQuery().taskAssignee("张三").list();
    for   (Task task : tasks) {
        System.out.println("张三的任务:name:"+task.getName()+",id:"+task.getId());
        taskService.complete(task.getId());
    }
 
    System.out.println("张三的任务数量:"+taskService.createTaskQuery().taskAssignee("张三").count());
    System.out.println("***************笔试流程结束***************");
 
    System.out.println("\n***************一面流程开始***************");
    tasks = taskService.createTaskQuery().taskCandidateGroup("技术部").list();
    for   (Task task : tasks) {
        System.out.println("技术部的任务:name:"+task.getName()+",id:"+task.getId());
        taskService.claim(task.getId(), "李四");
    }
 
    System.out.println("李四的任务数量:"+taskService.createTaskQuery().taskAssignee("李四").count());
    for   (Task task : tasks) {
        System.out.println("李四的任务:name:"+task.getName()+",id:"+task.getId());
        taskService.complete(task.getId());
    }
 
    System.out.println("李四的任务数量:"+taskService.createTaskQuery().taskAssignee("李四").count());
    System.out.println("***************一面流程结束***************");
 
    System.out.println("\n***************二面流程开始***************");
    tasks = taskService.createTaskQuery().taskCandidateGroup("技术部").list();
    for   (Task task : tasks) {
        System.out.println("技术部的任务:name:"+task.getName()+",id:"+task.getId());
        taskService.claim(task.getId(), "李四");
    }
 
    System.out.println("李四的任务数量:"+taskService.createTaskQuery().taskAssignee("李四").count());
    for   (Task task : tasks) {
        System.out.println("李四的任务:name:"+task.getName()+",id:"+task.getId());
        taskService.complete(task.getId());
    }
 
    System.out.println("李四的任务数量:"+taskService.createTaskQuery().taskAssignee("李四").count());
    System.out.println("***************二面流程结束***************");
 
    System.out.println("***************HR面流程开始***************");
    tasks = taskService.createTaskQuery().taskCandidateGroup("人力资源部").list();
    for   (Task task : tasks) {
        System.out.println("技术部的任务:name:"+task.getName()+",id:"+task.getId());
        taskService.claim(task.getId(), "李四");
    }
 
    System.out.println("李四的任务数量:"+taskService.createTaskQuery().taskAssignee("李四").count());
    for   (Task task : tasks) {
        System.out.println("李四的任务:name:"+task.getName()+",id:"+task.getId());
        taskService.complete(task.getId());
    }
 
    System.out.println("李四的任务数量:"+taskService.createTaskQuery().taskAssignee("李四").count());
    System.out.println("***************HR面流程结束***************");
 
    System.out.println("\n***************录用流程开始***************");
    tasks = taskService.createTaskQuery().taskCandidateGroup("人力资源部").list();
    for   (Task task : tasks) {
        System.out.println("技术部的任务:name:"+task.getName()+",id:"+task.getId());
        taskService.claim(task.getId(), "李四");
    }
 
    System.out.println("李四的任务数量:"+taskService.createTaskQuery().taskAssignee("李四").count());
    for   (Task task : tasks) {
        System.out.println("李四的任务:name:"+task.getName()+",id:"+task.getId());
        taskService.complete(task.getId());
    }
 
    System.out.println("李四的任务数量:"+taskService.createTaskQuery().taskAssignee("李四").count());
    System.out.println("***************录用流程结束***************");
 
    HistoryService historyService = processEngine.getHistoryService();
    HistoricProcessInstance historicProcessInstance = historyService
            .createHistoricProcessInstanceQuery()
            .processInstanceId(processId).singleResult();
    System.out.println("\n流程结束时间:"+historicProcessInstance.getEndTime());
}

代码清单中使用 ProcessEngines 类加载默认的流程配置文件(activiti.cfg.xml),再获取各个服务组件的实例。 RepositoryService 主要用于管理流程的资源, RuntimeService 主要用于流程运行时的流程管理,TaskService主要用于管理流程任务。最后, HistoricProcessInstance 会将工作的流程历史记录下来。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值