springboot整合activity基础入门

pom.xml引入依赖:

          <dependencies>
		<dependency>
			<groupId>io.springfox</groupId>
			<artifactId>springfox-swagger2</artifactId>
			<version>2.9.2</version>
		</dependency>
		<dependency>
			<groupId>io.springfox</groupId>
			<artifactId>springfox-swagger-ui</artifactId>
			<version>2.8.0</version>
		</dependency>
		<dependency>
			<groupId>org.activiti</groupId>
			<artifactId>activiti-spring-boot-starter-basic</artifactId>
			<version>6.0.0</version>
		</dependency>
		<dependency>
			<groupId>org.activiti</groupId>
			<artifactId>activiti-spring-boot-starter-jpa</artifactId>
			<version>6.0.0</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>
		<dependency>
			<groupId>org.mybatis.spring.boot</groupId>
			<artifactId>mybatis-spring-boot-starter</artifactId>
			<version>1.3.0</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-tomcat</artifactId>
		</dependency>
		<dependency>
			<groupId>org.apache.tomcat.embed</groupId>
			<artifactId>tomcat-embed-jasper</artifactId>
		</dependency>
		<!-- servlet支持 -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>javax.servlet-api</artifactId>
		</dependency>

		<!-- jstl 支持 -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jstl</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

在项目根路径下创建process文件夹,创建helloworld.bpmn文件

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" expressionLanguage="http://www.w3.org/1999/XPath" id="m1567831900728" name="" targetNamespace="http://www.activiti.org/testm1567831900728" typeLanguage="http://www.w3.org/2001/XMLSchema">
  <process id="myProcess_1" isClosed="false" isExecutable="true" processType="None">
    <startEvent id="_2" name="StartEvent"/>
    <endEvent id="_3" name="EndEvent"/>
    <userTask activiti:assignee="zhagnsan" activiti:exclusive="true" id="_4" name="apply"/>
    <userTask activiti:assignee="lisi" activiti:exclusive="true" id="_5" name="manager apply"/>
    <userTask activiti:assignee="wangwu" activiti:exclusive="true" id="_6" name="boss apply"/>
    <sequenceFlow id="_7" sourceRef="_2" targetRef="_4"/>
    <sequenceFlow id="_8" sourceRef="_4" targetRef="_5"/>
    <sequenceFlow id="_9" sourceRef="_5" targetRef="_6"/>
    <sequenceFlow id="_10" sourceRef="_6" targetRef="_3"/>
  </process>
  <bpmndi:BPMNDiagram documentation="background=#FFFFFF;count=1;horizontalcount=1;orientation=0;width=842.4;height=1195.2;imageableWidth=832.4;imageableHeight=1185.2;imageableX=5.0;imageableY=5.0" id="Diagram-_1" name="New Diagram">
    <bpmndi:BPMNPlane bpmnElement="myProcess_1">
      <bpmndi:BPMNShape bpmnElement="_2" id="Shape-_2">
        <dc:Bounds height="32.0" width="32.0" x="75.0" y="170.0"/>
        <bpmndi:BPMNLabel>
          <dc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="_3" id="Shape-_3">
        <dc:Bounds height="32.0" width="32.0" x="645.0" y="180.0"/>
        <bpmndi:BPMNLabel>
          <dc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="_4" id="Shape-_4">
        <dc:Bounds height="55.0" width="85.0" x="190.0" y="165.0"/>
        <bpmndi:BPMNLabel>
          <dc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="_5" id="Shape-_5">
        <dc:Bounds height="55.0" width="85.0" x="335.0" y="165.0"/>
        <bpmndi:BPMNLabel>
          <dc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="_6" id="Shape-_6">
        <dc:Bounds height="55.0" width="85.0" x="490.0" y="170.0"/>
        <bpmndi:BPMNLabel>
          <dc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge bpmnElement="_7" id="BPMNEdge__7" sourceElement="_2" targetElement="_4">
        <di:waypoint x="107.0" y="186.0"/>
        <di:waypoint x="190.0" y="192.5"/>
        <bpmndi:BPMNLabel>
          <dc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="_8" id="BPMNEdge__8" sourceElement="_4" targetElement="_5">
        <di:waypoint x="275.0" y="192.5"/>
        <di:waypoint x="335.0" y="192.5"/>
        <bpmndi:BPMNLabel>
          <dc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="_9" id="BPMNEdge__9" sourceElement="_5" targetElement="_6">
        <di:waypoint x="420.0" y="192.5"/>
        <di:waypoint x="490.0" y="197.5"/>
        <bpmndi:BPMNLabel>
          <dc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="_10" id="BPMNEdge__10" sourceElement="_6" targetElement="_3">
        <di:waypoint x="575.0" y="197.5"/>
        <di:waypoint x="645.0" y="196.0"/>
        <bpmndi:BPMNLabel>
          <dc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</definitions>

application.yml配置数据源

spring:
  jpa:
    properties:
      show-sql: true
      hibernate:
        hbm2ddl:
          auto: update
  mvc:
    view:
      prefix: /WEB-INF/jsp/
      suffix: .jsp
  datasource:
      url: jdbc:mysql://localhost:3306/activity
      username: root
      password: 123
      driverClassName: com.mysql.jdbc.Driver
      minPoolSize: 3
      maxPoolSize: 25
activiti:
    database-schema-update: true
    # 自动部署验证设置:true-开启(默认)、false-关闭
    check-process-definitions: false

流程的核心类是ProcessEngine,流程部署,启动,查询都需要

public class HelloWorld {
	
	ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();//默认从项目根目录下的activiti.cfg.xml读取配置信息,springboot可以注入

	/**部署流程定义*/
	@Test
	public void deploymentProcessDefinition(){
		Deployment deployment = processEngine.getRepositoryService()//与流程定义和部署对象相关的Service
						.createDeployment()//创建一个部署对象
						.name("helloworld入门程序")//添加部署的名称
						.addClasspathResource("process/helloworld.bpmn")//从classpath的资源中加载,一次只能加载一个文件
						.addClasspathResource("process/helloworld.png")//从classpath的资源中加载,一次只能加载一个文件
						.deploy();//完成部署
		System.out.println("部署ID:"+deployment.getId());//1
		System.out.println("部署名称:"+deployment.getName());//helloworld入门程序  
	}
	
	/**启动流程实例*/
	@Test
	public void startProcessInstance(){
		//流程定义的key
		String processDefinitionKey = "helloworld";
		ProcessInstance pi = processEngine.getRuntimeService()//与正在执行的流程实例和执行对象相关的Service
						.startProcessInstanceByKey(processDefinitionKey);//使用流程定义的key启动流程实例,key对应helloworld.bpmn文件中id的属性值,使用key值启动,默认是按照最新版本的流程定义启动(同一个key部署多次)
		System.out.println("流程实例ID:"+pi.getId());//流程实例ID    101
		System.out.println("流程定义ID:"+pi.getProcessDefinitionId());//流程定义ID   helloworld:1:4
	}
	
	
	/**查询当前人的个人任务*/
	@Test
	public void findMyPersonalTask(){
		String assignee = "王五";
		List<Task> list = processEngine.getTaskService()//与正在执行的任务管理相关的Service
						.createTaskQuery()//创建任务查询对象
						.taskAssignee(assignee)//指定个人任务查询,指定办理人
						.list();
		if(list!=null && list.size()>0){
			for(Task task:list){
				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());
				System.out.println("执行对象ID:"+task.getExecutionId());
				System.out.println("流程定义ID:"+task.getProcessDefinitionId());
				System.out.println("########################################################");
			}
		}
	}
	
	/**完成我的任务*/
	@Test
	public void completeMyPersonalTask(){
		//任务ID
		String taskId = "302";
		processEngine.getTaskService()//与正在执行的任务管理相关的Service
					.complete(taskId);
		System.out.println("完成任务:任务ID:"+taskId);
	}
	
}

 service的作用:

RepositoryService

管理流程定义

RuntimeService

执行管理,包括启动、推进、删除流程实例等操作

TaskService

任务管理

HistoryService

历史管理(执行完的数据的管理)

IdentityService

组织机构管理

FormService

一个可选服务,任务表单管理,可在节点上设置获取参数

ManagerService

Job任务管理;数据库相关通用操作;执行流程引擎命令(Command)

 

	@Override
	public String findTaskFormKeyByTaskId(String taskId) {
		TaskFormData formData = formService.getTaskFormData(taskId);
		//获取Form key的值
		String url = formData.getFormKey();
		return url;
	}

Deployment   部署对象

1、一次部署的多个文件的信息。对于不需要的流程可以删除和修改。

2、对应的表:

  act_re_deployment:部署对象表

  act_re_procdef:流程定义表

  act_ge_bytearray:资源文件表

  act_ge_property:主键生成策略表

 

ProcessDefinition 流程定义

解析.bpmn后得到的流程定义规则的信息,工作流系统就是按照流程定义的规则执行的。

Execution   执行对象

 按流程定义的规则执行一次的过程.

 对应的表:

  act_ru_execution: 正在执行的信息

  act_hi_procinst:已经执行完的历史流程实例信息

  act_hi_actinst:存放历史所有完成的活动

ProcessInstance  流程实例

 特指流程从开始到结束的那个最大的执行分支,一个执行的流程中,流程实例只有1个。

注意

    (1)如果是单例流程,执行对象ID就是流程实例ID

    (2)如果一个流程有分支和聚合,那么执行对象ID和流程实例ID就不相同

    (3)一个流程中,流程实例只有1个,执行对象可以存在多个。

Task 任务

 执行到某任务环节时生成的任务信息。

 对应的表:

  act_ru_task:正在执行的任务信息

  act_hi_taskinst:已经执行完的历史任务信息

 

public class ProcessDefinitionTest {

	ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
	
	/**部署流程定义(从classpath)*/
	@Test
	public void deploymentProcessDefinition_classpath(){
		Deployment deployment = processEngine.getRepositoryService()//与流程定义和部署对象相关的Service
						.createDeployment()//创建一个部署对象
						.name("流程定义")//添加部署的名称
						.addClasspathResource("process/helloworld.bpmn")//从classpath的资源中加载,一次只能加载一个文件
						.addClasspathResource("process/helloworld.png")//从classpath的资源中加载,一次只能加载一个文件
						.deploy();//完成部署
		System.out.println("部署ID:"+deployment.getId());//
		System.out.println("部署名称:"+deployment.getName());//
	}
	
	/**部署流程定义(从zip)*/
	@Test
	public void deploymentProcessDefinition_zip(){
		InputStream in = this.getClass().getClassLoader().getResourceAsStream("process/helloworld.zip");
		ZipInputStream zipInputStream = new ZipInputStream(in);
		Deployment deployment = processEngine.getRepositoryService()//与流程定义和部署对象相关的Service
						.createDeployment()//创建一个部署对象
						.name("流程定义")//添加部署的名称
						.addZipInputStream(zipInputStream)//指定zip格式的文件完成部署
						.deploy();//完成部署
		System.out.println("部署ID:"+deployment.getId());//
		System.out.println("部署名称:"+deployment.getName());//
	}
	
	/**查询流程定义*/
	@Test
	public void findProcessDefinition(){
		List<ProcessDefinition> list = processEngine.getRepositoryService()//与流程定义和部署对象相关的Service
						.createProcessDefinitionQuery()//创建一个流程定义的查询
						/**指定查询条件,where条件*/
//						.deploymentId(deploymentId)//使用部署对象ID查询
//						.processDefinitionId(processDefinitionId)//使用流程定义ID查询
//						.processDefinitionKey(processDefinitionKey)//使用流程定义的key查询
//						.processDefinitionNameLike(processDefinitionNameLike)//使用流程定义的名称模糊查询
						
						/**排序*/
						.orderByProcessDefinitionVersion().asc()//按照版本的升序排列
//						.orderByProcessDefinitionName().desc()//按照流程定义的名称降序排列
						
						/**返回的结果集*/
						.list();//返回一个集合列表,封装流程定义
//						.singleResult();//返回惟一结果集
//						.count();//返回结果集数量
//						.listPage(firstResult, maxResults);//分页查询
		if(list!=null && list.size()>0){
			for(ProcessDefinition pd:list){
				System.out.println("流程定义ID:"+pd.getId());//流程定义的key+版本+随机生成数
				System.out.println("流程定义的名称:"+pd.getName());//对应helloworld.bpmn文件中的name属性值
				System.out.println("流程定义的key:"+pd.getKey());//对应helloworld.bpmn文件中的id属性值
				System.out.println("流程定义的版本:"+pd.getVersion());//当流程定义的key值相同的相同下,版本升级(同一个key部署多次),默认1
				System.out.println("资源名称bpmn文件:"+pd.getResourceName());
				System.out.println("资源名称png文件:"+pd.getDiagramResourceName());
				System.out.println("部署对象ID:"+pd.getDeploymentId());
				System.out.println("#########################################################");
			}
		}			
	}
	
	/**删除流程定义*/
	@Test
	public void deleteProcessDefinition(){
		//使用部署ID,完成删除
		String deploymentId = "601";
		/**
		 * 不带级联的删除
		 *    只能删除没有启动的流程,如果流程启动,就会抛出异常
		 */
//		processEngine.getRepositoryService()//
//						.deleteDeployment(deploymentId);
		
		/**
		 * 级联删除
		 * 	  不管流程是否启动,都能可以删除
		 */
		processEngine.getRepositoryService()//
						.deleteDeployment(deploymentId, true);
		System.out.println("删除成功!");
	}
	
	/**查看流程图
	 * @throws IOException */
	@Test
	public void viewPic() throws IOException{
		/**将生成图片放到文件夹下*/
		String deploymentId = "801";
		//获取图片资源名称
		List<String> list = processEngine.getRepositoryService()//
						.getDeploymentResourceNames(deploymentId);
		//定义图片资源的名称
		String resourceName = "";
		if(list!=null && list.size()>0){
			for(String name:list){
				if(name.indexOf(".png")>=0){
					resourceName = name;
				}
			}
		}
		
		
		//获取图片的输入流
		InputStream in = processEngine.getRepositoryService()//
						.getResourceAsStream(deploymentId, resourceName);
		
		//将图片生成到D盘的目录下
		File file = new File("D:/"+resourceName);
		//将输入流的图片写到D盘下
		FileUtils.copyInputStreamToFile(in, file);
	}
	
	/***附加功能:查询最新版本的流程定义*/
	@Test
	public void findLastVersionProcessDefinition(){
		List<ProcessDefinition> list = processEngine.getRepositoryService()//
						.createProcessDefinitionQuery()//
						.orderByProcessDefinitionVersion().asc()//使用流程定义的版本升序排列
						.list();
		/**
		 * Map<String,ProcessDefinition>
  map集合的key:流程定义的key
  map集合的value:流程定义的对象
  map集合的特点:当map集合key值相同的情况下,后一次的值将替换前一次的值
		 */
		Map<String, ProcessDefinition> map = new LinkedHashMap<String, ProcessDefinition>();
		if(list!=null && list.size()>0){
			for(ProcessDefinition pd:list){
				map.put(pd.getKey(), pd);
			}
		}
		List<ProcessDefinition> pdList = new ArrayList<ProcessDefinition>(map.values());
		if(pdList!=null && pdList.size()>0){
			for(ProcessDefinition pd:pdList){
				System.out.println("流程定义ID:"+pd.getId());//流程定义的key+版本+随机生成数
				System.out.println("流程定义的名称:"+pd.getName());//对应helloworld.bpmn文件中的name属性值
				System.out.println("流程定义的key:"+pd.getKey());//对应helloworld.bpmn文件中的id属性值
				System.out.println("流程定义的版本:"+pd.getVersion());//当流程定义的key值相同的相同下,版本升级,默认1
				System.out.println("资源名称bpmn文件:"+pd.getResourceName());
				System.out.println("资源名称png文件:"+pd.getDiagramResourceName());
				System.out.println("部署对象ID:"+pd.getDeploymentId());
				System.out.println("#########################################################");
			}
		}	
	}
	
	/**附加功能:删除流程定义(删除key相同的所有不同版本的流程定义)*/
	@Test
	public void deleteProcessDefinitionByKey(){
		//流程定义的key
		String processDefinitionKey = "helloworld";
		//先使用流程定义的key查询流程定义,查询出所有的版本
		List<ProcessDefinition> list = processEngine.getRepositoryService()//
						.createProcessDefinitionQuery()//
						.processDefinitionKey(processDefinitionKey)//使用流程定义的key查询
						.list();
		//遍历,获取每个流程定义的部署ID
		if(list!=null && list.size()>0){
			for(ProcessDefinition pd:list){
				//获取部署ID
				String deploymentId = pd.getDeploymentId();
				processEngine.getRepositoryService()//
							.deleteDeployment(deploymentId, true);
			}
		}
	}
	/**查询流程状态(判断流程正在执行,还是结束)*/
	@Test
	public void isProcessEnd(){
		String processInstanceId = "1001";
		ProcessInstance pi = processEngine.getRuntimeService()//表示正在执行的流程实例和执行对象
						.createProcessInstanceQuery()//创建流程实例查询
						.processInstanceId(processInstanceId)//使用流程实例ID查询
						.singleResult();
		if(pi==null){
			System.out.println("流程已经结束");
		}
		else{
			System.out.println("流程没有结束");
		}
	}
	
	/**查询历史任务*/
	@Test
	public void findHistoryTask(){
		String taskAssignee = "张三";
		List<HistoricTaskInstance> list = processEngine.getHistoryService()//与历史数据(历史表)相关的Service
						.createHistoricTaskInstanceQuery()//创建历史任务实例查询
						.taskAssignee(taskAssignee)//指定历史任务的办理人
						.list();
		if(list!=null && list.size()>0){
			for(HistoricTaskInstance hti:list){
				System.out.println(hti.getId()+"    "+hti.getName()+"    "+hti.getProcessInstanceId()+"   "+hti.getStartTime()+"   "+hti.getEndTime()+"   "+hti.getDurationInMillis());
				System.out.println("################################");
			}
		}
	}
	
	/**查询历史流程实例*/
	@Test
	public void findHistoryProcessInstance(){
		String processInstanceId = "1001";
		HistoricProcessInstance hpi = processEngine.getHistoryService()//与历史数据(历史表)相关的Service
						.createHistoricProcessInstanceQuery()//创建历史流程实例查询
						.processInstanceId(processInstanceId)//使用流程实例ID查询
						.singleResult();
		System.out.println(hpi.getId()+"    "+hpi.getProcessDefinitionId()+"    "+hpi.getStartTime()+"    "+hpi.getEndTime()+"     "+hpi.getDurationInMillis());
	}
}

说明:

  1. 因为是任务查询,所以从processEngine中应该得到TaskService
  2. 使用TaskService获取到任务查询对象TaskQuery
  3. 为查询对象添加查询过滤条件,使用taskAssignee指定任务的办理者(即查询指定用户的代办任务),同时可以添加分页排序等过滤条件
  4. 调用list方法执行查询,返回办理者为指定用户的任务列表
  5. 任务ID、名称、办理人、创建时间可以从act_ru_task表中查到。
  6. 如果assignee属性为部门经理,结果为空。因为现在流程只到了”填写请假申请”阶段,后面的任务还没有执行,即在数据库中没有部门经理可以办理的任务,所以查询不到。
  7. 一个Task节点和Execution节点是1对1的情况,在task对象中使用Execution_来表示他们之间的关系
  8. 任务ID在数据库表act_ru_task中对应“ID_”列

关于ProcessDefinitionEntity(流程定义实体)的相关内容

上面的这个图就是对于一个流程的相关内容,这部分要特别注意,是非常重要的一个内容。

public class ProcessDefinitionEntityTest {
	/**
	 * 根据pdid得到processDefinitionEntity
	 */
	@Test
	public void testProcessDefinitionEntity(){
		ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
		/**
		 * 根据pdid得到ProcessDefinitionEntry
		 */
		ProcessDefinitionEntity processDefinitionEntity = (ProcessDefinitionEntity)processEngine.getRepositoryService()
		.getProcessDefinition("qingjia1:1:804");
        /**
        *ProcessInstance process;
        *(ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
        *                .getDeployedProcessDefinition(process.getProcessDefinitionId())
        */
		
	}
	
	/**
	 * 根据pdid得到processDefinitionEntity中的activityimpl
	 */
	@Test
	public void testGetActivityImpl(){
		ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
		/**
		 * 根据pdid得到ProcessDefinitionEntry
		 */
		ProcessDefinitionEntity processDefinitionEntity = (ProcessDefinitionEntity)processEngine.getRepositoryService()
		.getProcessDefinition("qingjia1:1:804");
		/**
		 * ActivityImpl是一个对象
		 * 一个activityImpl代表processDefinitionEntity中的一个节点
		 */
		List<ActivityImpl> activityImpls = processDefinitionEntity.getActivities();
		for (ActivityImpl activityImpl : activityImpls) {
			System.out.println(activityImpl.getId());
			System.out.print("hegiht:"+activityImpl.getHeight());
			System.out.print("width:"+activityImpl.getWidth());
			System.out.print(" x:"+activityImpl.getX());
			System.out.println(" y:"+activityImpl.getY());
		}
	}
		
	/**
	 * 得到ProcessDefinitionEntity中的所有的ActivityImpl的所有的PvmTransition
	 */
	@Test
	public void testSequenceFlow(){
		ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
		/**
		 * 根据pdid得到ProcessDefinitionEntry
		 */
		ProcessDefinitionEntity processDefinitionEntity = (ProcessDefinitionEntity)processEngine.getRepositoryService()
		.getProcessDefinition("qingjia1:1:804");
		
		/**
		 * ActivityImpl是一个对象
		 * 一个activityImpl代表processDefinitionEntity中的一个节点
		 */
		List<ActivityImpl> activityImpls = processDefinitionEntity.getActivities();
		for (ActivityImpl activityImpl : activityImpls) {
			/**
			 * 得到一个activityimpl的所有的outgoing
			 */
			List<PvmTransition> pvmTransitions = activityImpl.getOutgoingTransitions();
			for (PvmTransition pvmTransition : pvmTransitions) {
				System.out.println("sequenceFlowId:"+pvmTransition.getId());
			}
		}
	}
	
	/**
	 * 得到当前正在执行的流程实例的activityimpl-->PvmTransition
	 */
	@Test
	public void testQueryActivityImpl_Ing(){
		ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
		ProcessDefinitionEntity processDefinitionEntity = (ProcessDefinitionEntity)processEngine.getRepositoryService()
		.getProcessDefinition("qingjia:1:504");
		//根据piid获取到activityId
		ProcessInstance pi = processEngine.getRuntimeService()
		.createProcessInstanceQuery()
		.processInstanceId("1001")
		.singleResult();
		//根据流程实例得到当前正在执行的流程实例的正在执行的节点
		ActivityImpl activityImpl = processDefinitionEntity.findActivity(pi.getActivityId());
		System.out.print("流程实例ID:"+pi.getId());
		System.out.print(" 当前正在执行的节点:"+activityImpl.getId());
		System.out.print(" hegiht:"+activityImpl.getHeight());
		System.out.print(" width:"+activityImpl.getWidth());
		System.out.print(" x:"+activityImpl.getX());
		System.out.println(" y:"+activityImpl.getY());
	}

}

附加:

在activiti任务中,主要分为两大类查询任务(个人任务和组任务):

  1. 确切指定了办理者的任务,这个任务将成为指定者的私有任务,即个人任务。
  2. 无法指定具体的某一个人来办理的任务,可以把任务分配给几个人或者一到 多个小组,让这个范围内的用户可以选择性(如有空余时间时)来办理这类任务,即组任务。

Activiti里面本身自带有很多的数据表,它里面都是存在着关联关系,那么如何将其本身的表与我们的实际业务中的表进行关联呢?

解惑:其实,这个对于Activiti早已经想到这个问题,(1)就是通过act_ru_exectution这个表中的business_key这个字段来进行关联,启动流程的时候有个方法第一个参数是流程key,第二个是business_key,第三个是流程变量Map,对于business_key的值我们可以设置为流程key+“:”+业务id;

public LeaveBill findLeaveBillByTaskId(String taskId) {
		//1:使用任务ID,查询任务对象Task
		Task task = taskService.createTaskQuery()//
						.taskId(taskId)//使用任务ID查询
						.singleResult();
		//2:使用任务对象Task获取流程实例ID
		String processInstanceId = task.getProcessInstanceId();
		//3:使用流程实例ID,查询正在执行的执行对象表,返回流程实例对象
		ProcessInstance pi = runtimeService.createProcessInstanceQuery()//
						.processInstanceId(processInstanceId)//使用流程实例ID查询
						.singleResult();
		//4:使用流程实例对象获取BUSINESS_KEY
		String buniness_key = pi.getBusinessKey();
		//5:获取BUSINESS_KEY对应的主键ID,使用主键ID,查询请假单对象(LeaveBill.1)
		String id = "";
		if(StringUtils.isNotBlank(buniness_key)){
			//截取字符串,取buniness_key小数点的第2个值
			id = buniness_key.split("\\.")[1];
		}
		//查询请假单对象
		//使用hql语句:from LeaveBill o where o.id=1
		LeaveBill leaveBill = leaveBillDao.findLeaveBillById(Long.parseLong(id));
		return leaveBill;
	}

(2)将proc_inst_id即启动流程返回的实例id放到我们的业务表中

act_ge_*:

‘ge’代表general(一般)。普通数据,各种情况都使用的数据。

  • act_ge_bytearray:二进制数据表,用来保存部署文件的大文本数据
    1.ID_:资源文件编号,自增长
    2.REV_INT:版本号
    3.NAME_:资源文件名称
    4.DEPLOYMENT_ID_:来自于父表act_re_deployment的主键
    5.BYTES_:大文本类型,存储文本字节流

  • act_ge_property:属性数据表,存储这整个流程引擎级别的数据。在初始化表结构时,会默认插入三条记录。
    1.NAME_:属性名称
    2.VALUE_:属性值
    3.REV_INT:版本号


act_hi_*:

’hi’代表 history(历史)。就是这些表包含着历史的相关数据,如结束的流程实例、变量、任务、等等。

  • act_hi_actinst:历史节点表
    1.ID_ : 标识
    2.PROC_DEF_ID_ :流程定义id
    3.PROC_INST_ID_ : 流程实例id
    4.EXECUTION_ID_ : 执行实例
    5.ACT_ID_ : 节点id
    6.ACT_NAME_ : 节点名称
    7.ACT_TYPE_ : 节点类型
    8.ASSIGNEE_ : 节点任务分配人
    9.START_TIME_ : 开始时间
    10.END_TIME_ : 结束时间
    11.DURATION : 经过时长

  • act_hi_attachment:历史附件表

  • act_hi_comment:历史意见表
    1.ID_ :标识
    2.TYPE_ : 意见记录类型 为comment 时 为处理意见
    3.TIME_ : 记录时间
    4.USER_ID_ :
    5.TASK_ID_ : 对应任务的id
    6.PROC_INST_ID_ : 对应的流程实例的id
    7.ACTION_ : 为AddComment 时为处理意见
    8.MESSAGE_ : 处理意见
    9.FULL_MSG_ :

  • act_hi_detail:历史详情表,启动流程或者在任务complete之后,记录历史流程变量
    1.ID_ : 标识
    2.TYPE_ : variableUpdate 和 formProperty 两种值
    3.PROC_INST_ID_ : 对应流程实例id
    4.EXECUTION_ID_ : 对应执行实例id
    5.TASK_ID_ : 对应任务id
    6.ACT_INST_ID : 对应节点id
    7.NAME_ : 历史流程变量名称,或者表单属性的名称
    8.VAR_TYPE_ : 定义类型
    9.REV_ : 版本
    10.TIME_ : 导入时间
    11.BYTEARRAY_ID_
    12.DOUBLE_ : 如果定义的变量或者表单属性的类型为double,他的值存在这里
    13.LONG_ : 如果定义的变量或者表单属性的类型为LONG ,他的值存在这里
    14.TEXT_ :  如果定义的变量或者表单属性的类型为string,值存在这里
    15.TEXT2_:

  • act_hi_identitylink:历史流程人员表

  • act_hi_procinst: 历史流程实例表
    1.ID_ : 唯一标识
    2.PROC_INST_ID_ : 流程ID
    3.BUSINESS_KEY_ : 业务编号
    4.PROC_DEF_ID_ : 流程定义id
    5.START_TIME_ : 流程开始时间
    6.ENT__TIME : 结束时间
    7.DURATION_ : 流程经过时间
    8.START_USER_ID_ : 开启流程用户id
    9.START_ACT_ID_ : 开始节点
    10.END_ACT_ID_: 结束节点
    11.SUPER_PROCESS_INSTANCE_ID_ : 父流程流程id
    12.DELETE_REASON_ : 从运行中任务表中删除原因

  • act_hi_taskinst: 历史任务实例表
    1.ID_ : 标识
    2.PROC_DEF_ID_ : 流程定义id
    3.TASK_DEF_KEY_ : 任务定义id
    4.PROC_INST_ID_ : 流程实例id
    5.EXECUTION_ID_ : 执行实例id
    6.PARENT_TASK_ID_ : 父任务id
    7.NAME_ : 任务名称
    8.DESCRIPTION_ : 说明
    9.OWNER_ : 拥有人(发起人)
    10.ASSIGNEE_ : 分配到任务的人
    11.START__TIME_ : 开始任务时间
    12.END_TIME_ : 结束任务时间
    13.DURATION_ : 时长
    14.DELETE_REASON_ :从运行时任务表中删除的原因
    15.PRIORITY_ : 紧急程度
    16.DUE_DATE_ :

  • act_hi_varinst:历史变量表


act_id_*:

’id’代表 identity(身份)。这些表包含着标识的信息,如用户、用户组、等等。

  • act_id_group:用户组信息表,用来存储用户组信息。
    1.ID_:用户组名*
    2.REV_INT:版本号
    3.NAME_:用户组描述信息*
    4.TYPE_:用户组类型

  • act_id_info:用户扩展信息表

  • act_id_membership:用户与用户组对应信息表,用来保存用户的分组信息
    1.USER_ID_:用户名
    2.GROUP_ID_:用户组名

  • act_id_user:用户信息表
    1.ID_:用户名
    2.REV_INT:版本号
    3.FIRST_:用户名称
    4.LAST_:用户姓氏
    5.EMAIL_:邮箱
    6.PWD_:密码


act_re_*:

’re’代表 repository(仓库)。带此前缀的表包含的是静态信息,如,流程定义、流程的资源(图片、规则,等)。

  • act_re_deployment:部署信息表,用来存储部署时需要持久化保存下来的信息
    1.ID_:部署编号,自增长
    2.NAME_:部署包的名称
    3.DEPLOY_TIME_:部署时间

  • act_re_model 流程设计模型部署表

  • act_re_procdef:业务流程定义数据表
    1.ID_:流程ID,由“流程编号:流程版本号:自增长ID”组成
    2.CATEGORY_:流程命名空间(该编号就是流程文件targetNamespace的属性值)
    3.NAME_:流程名称(该编号就是流程文件process元素的name属性值)
    4.KEY_:流程编号(该编号就是流程文件process元素的id属性值)
    5.VERSION_:流程版本号(由程序控制,新增即为1,修改后依次加1来完成的)
    6.DEPLOYMENT_ID_:部署编号
    7.RESOURCE_NAME_:资源文件名称
    8.DGRM_RESOURCE_NAME_:图片资源文件名称
    9.HAS_START_FROM_KEY_:是否有Start From Key

注:此表和ACT_RE_DEPLOYMENT是多对一的关系,即,一个部署的bar包里可能包含多个流程定义文件,每个流程定义文件都会有一条记录在ACT_REPROCDEF表内,每个流程定义的数据,都会对于ACT_GE_BYTEARRAY表内的一个资源文件和PNG图片文件。和ACT_GE_BYTEARRAY的关联是通过程序用ACT_GE_BYTEARRAY.NAME与ACT_RE_PROCDEF.NAME_完成的,在数据库表结构中没有体现。


act_ru_*:

’ru’代表 runtime(运行时)。就是这个运行时的表存储着流程变量、用户任务、变量、作业,等中的运行时的数据。 activiti 只存储流程实例执行期间的运行时数据,当流程实例结束时,将删除这些记录。这就使这些运行时的表保持 的小且快。

  • act_ru_event_subscr

  • act_ru_execution:运行时流程执行实例表
    1.ID_:主键,这个主键有可能和PROC_INST_ID_相同,相同的情况表示这条记录为主实例记录。
    2.REV_:版本,表示数据库表更新次数。
    3.PROC_INST_ID_:流程实例编号,一个流程实例不管有多少条分支实例,这个ID都是一致的。
    4.BUSINESS_KEY_:业务编号,业务主键,主流程才会使用业务主键,另外这个业务主键字段在表中有唯一约束。
    5.PARENT_ID_:找到该执行实例的父级,最终会找到整个流程的执行实例
    6.PROC_DEF_ID_:流程定义ID
    7.SUPER_EXEC_: 引用的执行模板,这个如果存在表示这个实例记录为一个外部子流程记录,对应主流程的主键ID。
    8.ACT_ID_: 节点id,表示流程运行到哪个节点
    9.IS_ACTIVE_: 是否活动流程实例
    10.IS_CONCURRENT_:是否并发。上图同步节点后为并发,如果是并发多实例也是为1。
    11.IS_SCOPE_: 主实例为1,子实例为0。
    12.TENANT_ID_ : 这个字段表示租户ID。可以应对多租户的设计。
    13.IS_EVENT_SCOPE: 没有使用到事件的情况下,一般都为0。
    14.SUSPENSION_STATE_:是否暂停。

  • act_ru_identitylink:运行时流程人员表,主要存储任务节点与参与者的相关信息
    1.ID_: 标识
    2.REV_: 版本
    3.GROUP_ID_: 组织id
    4.TYPE_: 类型
    5.USER_ID_: 用户id
    6.TASK_ID_: 任务id

  • act_ru_job

  • act_ru_task:运行时任务节点表
    1.ID_:
    2.REV_:
    3.EXECUTION_ID_: 执行实例的id
    4.PROC_INST_ID_: 流程实例的id
    5.PROC_DEF_ID_: 流程定义的id,对应act_re_procdef 的id_
    6.NAME_: 任务名称,对应 ***task 的name
    7.PARENT_TASK_ID_ : 对应父任务
    8.DESCRIPTION_:
    9.TASK_DEF_KEY_: ***task 的id
    10.OWNER_ : 发起人
    11.ASSIGNEE_: 分配到任务的人
    12.DELEGATION_ : 委托人
    13.PRIORITY_: 紧急程度
    14.CREATE_TIME_: 发起时间
    15.DUE_TIME_:审批时长

  • act_ru_variable:运行时流程变量数据表
    1.ID_:标识
    2.REV_:版本号
    3.TYPE_:数据类型
    4.NAME_:变量名
    5.EXECUTION_ID_: 执行实例id
    6.PROC_INST_ID_: 流程实例id
    7.TASK_ID_: 任务id
    8.BYTEARRAY_ID_:
    9.DOUBLE_:若数据类型为double ,保存数据在此列
    10.LONG_: 若数据类型为Long保存数据到此列
    11.TEXT_: string 保存到此列
    12.TEXT2_:

 

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值