Activiti介绍(二):Activiti建表,执行操作流程

上次说道Activiti集成了Maven环境,这次用Activiti来跑一下项目。

一、新建项目

新建一个简单Activiti项目,如下图所示:

项目结构

在项目结构中,需要在resource里放入activiti.cfg.xml文件,此文件是activiti的配置文件,利用此配置文件可以构造关于Activiti的24张表,Activiti中的所有操作都是在这24张表之中进行的。有两种构建方式可以配置activiti.cfg.xml。如下:

activiti.cfg.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:tx="http://www.springframework.org/schema/tx" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:aop="http://www.springframework.org/schema/aop" 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-3.0.xsd   
    http://www.springframework.org/schema/tx   
    http://www.springframework.org/schema/tx/spring-tx-3.0.xsd   
    http://www.springframework.org/schema/aop    
    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
    <!-- 
    	 ProcessEngineConfiguration processEngineConfiguration = ProcessEngineConfiguration  
                .createStandaloneProcessEngineConfiguration();  
        // 连接数据库的配置  
        processEngineConfiguration.setJdbcDriver("com.mysql.jdbc.Driver");  
        processEngineConfiguration  
                .setJdbcUrl("jdbc:mysql://localhost:3306/testactiviti?useUnicode=true&characterEncoding=utf8");  
        processEngineConfiguration.setJdbcUsername("****");  
        processEngineConfiguration.setJdbcPassword("****");  
        // Activiti的24个表不存在则自动创建  
        processEngineConfiguration  
                .setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);  
     -->
    <bean id="processEngineConfiguration"
		class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
		<property name="jdbcDriver" value="com.mysql.jdbc.Driver"></property>
		<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/testactiviti?useUnicode=true&amp;characterEncoding=utf8"></property>
		<property name="jdbcUsername" value="****"></property>
		<property name="jdbcPassword" value="****"></property>
		<property name="databaseSchemaUpdate" value="true"></property>
	</bean>
</beans>

二、画流程图

现在开始设计一个流程,可以用activiti插件中的图标bpmn绘制工具,使用方法,新建-->other-->Activiti Diagram-->选择你需要绘制的路径,这里,我们将其放在了resource目录下面的diagrams之中了。

建好bpmn文件之后,开始绘图,使用右侧的绘图工具绘制一个流程图。

绘制好基本图形了,分别对每个元素进行属性设置,这里可以更改属性中的General的Name值,以及Main-config下面的Assignee值(办理人)。这样,每个流程都有自己的名称,ID,和办理人了,这就是一个完整的流程。保存此流程,就可以在其目录下生成一张相同名称的png流程图片,打开图片,即是自己绘制的流程示意图。

当然,这个bpmn文件也可以不使用Activiti视图打开,可以使用xml浏览器方式进行打开,出现的是xml结构的流程说明,在这里,我贴上自己的bpmn文件结构记录:

<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.activiti.org/test">
  <process id="helloworld" name="helloworldName" isExecutable="true">
    <startEvent id="startevent1" name="Start"></startEvent>
    <endEvent id="endevent1" name="End"></endEvent>
    <userTask id="usertask1" name="提交申请" activiti:assignee="张三"></userTask>
    <userTask id="usertask2" name="部门经理审批" activiti:assignee="李四"></userTask>
    <userTask id="usertask3" name="总经理审批" activiti:assignee="王五"></userTask>
    <sequenceFlow id="flow1" sourceRef="startevent1" targetRef="usertask1"></sequenceFlow>
    <sequenceFlow id="flow2" sourceRef="usertask1" targetRef="usertask2"></sequenceFlow>
    <sequenceFlow id="flow3" sourceRef="usertask2" targetRef="usertask3"></sequenceFlow>
    <sequenceFlow id="flow4" sourceRef="usertask3" targetRef="endevent1"></sequenceFlow>
  </process>
  <bpmndi:BPMNDiagram id="BPMNDiagram_helloworld">
    <bpmndi:BPMNPlane bpmnElement="helloworld" id="BPMNPlane_helloworld">
      <bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1">
        <omgdc:Bounds height="35.0" width="35.0" x="130.0" y="30.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1">
        <omgdc:Bounds height="35.0" width="35.0" x="130.0" y="420.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="usertask1" id="BPMNShape_usertask1">
        <omgdc:Bounds height="55.0" width="105.0" x="95.0" y="100.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="usertask2" id="BPMNShape_usertask2">
        <omgdc:Bounds height="55.0" width="105.0" x="95.0" y="200.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="usertask3" id="BPMNShape_usertask3">
        <omgdc:Bounds height="55.0" width="105.0" x="95.0" y="300.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1">
        <omgdi:waypoint x="147.0" y="65.0"></omgdi:waypoint>
        <omgdi:waypoint x="147.0" y="100.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">
        <omgdi:waypoint x="147.0" y="155.0"></omgdi:waypoint>
        <omgdi:waypoint x="147.0" y="200.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3">
        <omgdi:waypoint x="147.0" y="255.0"></omgdi:waypoint>
        <omgdi:waypoint x="147.0" y="300.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow4" id="BPMNEdge_flow4">
        <omgdi:waypoint x="147.0" y="355.0"></omgdi:waypoint>
        <omgdi:waypoint x="147.0" y="420.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</definitions>

三、java实例化流程

当配置文件写好、流程图绘制完毕后,就可以直接上代码进行测试了:

ActivitiDemo.java


import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.apache.commons.io.*;
import org.junit.Test;

public class ActivitiDemo {
	
	ProcessEngine pe=ProcessEngines.getDefaultProcessEngine();
	/**部署流程定义*/
	@Test
	public void deploymentProcessDefinition(){
		Deployment deploye=pe.getRepositoryService()//与流程定义和部署对象的Service
			.createDeployment()//创建一个部署对象
			.name("部署名称")
			.addClasspathResource("diagrams/MyProcess.bpmn")//从classpath加载,一次只能加载一个文件
			.addClasspathResource("diagrams/MyProcess.png")
			.deploy();
		System.out.println(deploye.getId());
		System.out.println(deploye.getName());
	}
}

这一个测试就是针对这个流程最开始的启动工作来做的。启动完毕后,会在数据库中得到24张表。目前在这个流程中,由于这个流程是单线操作,所以存在一个流程实例,一个流程对象。ProcessEngine是整个流程管理的核心,通过引擎来管理所有的流程操作,在这里,流程引擎通过ProcessEngines.getDefaultProcessEngine()方法获得;引擎中创建了各种操作流程的Service,包括:

    ResponsitoryService:管理流程定义

    RuntimeService:执行管理定义

    TaskService:任务管理定义

    HistoryService:历史管理定义

    IdentityService:组织机构管理定义

    FormService:任务表单管理定义

执行测试方法,可以将其打印出来,其中5001是流程ID,流程名称则是在创建流程时赋予的名称。这个部署完毕,就会在数据库中act_re_deployment(流程表)表中留下一条记录。

5001
部署名称

部署流程定义后,需要将其实例化,需要启动流程实例,测试代码为:

    @Test
	public void startProcessInstance(){
		ProcessInstance processInstance=pe.getRuntimeService()//启动相关的Service
			.startProcessInstanceByKey("helloworld");//通过流程Key启动,key对应的是bpmn文件中的ID属性
		System.out.println("流程实例ID"+processInstance.getId());
		System.out.println("流程定义ID"+processInstance.getProcessDefinitionId());
	}
流程实例ID7501
流程定义IDhelloworld:3:5004

这样就获取了一个流程实例,在流程实例表中可以看到增加了一条数据,说明这个流程开始启动了:

四、办理人执行任务

流程实例启动后,我们的研究对象就从流程实例转到流程对象了,流程对象可以在act_ru_execution(流程对象表)中查看,可以在任务表中查询到相应的历史任务(act_hi_taskinst)和正在进行的任务(act_ru_task),可以看到流程的进展情况;可以看到任务流程在开始后已经变成了“提交申请”,转给了办理人 张三。

流程对象表:

任务表:

当然,这写查询的操作可以用java完成,我们在任务表中看到当前有一个任务记录,办理人Assignee是张三,这个是在bpmn表中定义好了的。可以用java语句来审批一下任务,让工作流继续传递下去,下面就是查询个人任务并完成个人任务的写法;

	/**查询当前人的个人任务*/
	@Test
	public void findProcessTask(){
		List<Task> t=pe.getTaskService()
			.createTaskQuery()
			.taskAssignee("张三")
			.list();
		if(t!=null&&t.size()>0){
			for(Task task:t){
				System.out.println("任务ID"+task.getId());
				System.out.println("任务名称"+task.getName());
				System.out.println(task.getCreateTime());
				System.out.println("办理人"+task.getAssignee());//办理人
				System.out.println("流程实例ID"+task.getProcessInstanceId());//流程实例ID
				System.out.println("执行对象ID"+task.getExecutionId());//流程实例ID
				System.out.println("流程定义ID"+task.getProcessDefinitionId());//流程实例ID
			}
		}
	}
任务ID7504
任务名称提交申请
Tue Jan 30 16:19:43 CST 2018
办理人张三
流程实例ID7501
执行对象ID7501
流程定义IDhelloworld:3:5004

可以将此任务的状态设置为完成,在java中的测试代码为

	/**完成任务*/
	@Test
	public void completeTask(){
		pe.getTaskService()
			.complete("7504");
	}

这是如果打开任务表,就会发现任务已经由张三转为李四了,表明张三的提交审批任务已经完成,当前的任务会转给李四,可以在ru_task表中证实;

同理,获取当前任务的ID后,完成任务,就会讲此任务转给王五,依此类推,直至流程结束。

完成流程后,可以在hi_taskinst表(历史任务表)中查看到完成的任务记录

也可以在hi_procinst(历史流程表)中看到流程记录,可以看到这是一个有始有终的项目,包含有start_time,end_time;

五、附

这是一个Activiti的逻辑说明例子,在实际项目中,任务办理人不会直接写死在bpmn中,各种任务的ID,办理人等也会由程序获取,并且关联在一起。

猜你喜欢

转载自my.oschina.net/u/2344382/blog/1615678