ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

工作流第七篇之流程存储

2021-01-06 10:32:19  阅读:257  来源: 互联网

标签:engine 存储 activiti 流程 第七篇 org import repositoryService


RepositoryService主要用于对Activiti中的流程存储的相关数据进行操作,这些操作包括对流程存储数据的管理、流程部署以及对流程的基本操作等。
流程文件部署
RepositoryService负责对流程文件的部署以及流程的定义进行管理,不管是JBPM还是Activiti等工作流引擎,都会产生流程文件,工作流引擎需要对这些文件进行管理,这些文件包括流程描述文件、流程图等。
在Activiti中,如果需要对这些资源文件进行操作(包括添加、删除、查询等),可以使用RepositoryService提供的API。这些文件数据被保存在ACT_GE_BYTEARRAY表中,对应的实体为ResourceEntityImpl。
设置用户图片同样会向ACT_GE_BYTEARRAY表中写入数据,但是当数据为用户图片时,对应的实体是ByteArrayEntityImpl。ResourceEntityImpl与ByteArrayEntityImpl区别如下。
➢ ByteArrayEntityImpl对应的数据有版本管理数据,而ResourceEntityImpl则没有。
➢ ResourceEntityImpl 会设置 ACT_GE_BYTEARRAY 表的 GENERATED_字段值,而ByteArrayEntityImpl在进行保存时,该值为null。

Deployment对象
Deployment对象是一个接口,一个Deployment实例表示一条ACT_RE_DEPLOYMENT表的数据,同样,Deployment也遵循Activiti的实体命名规则,子接口为DeploymentEntity,实现类为DeploymentEntityImpl。如果要对属性进行修改,需要调用DeploymentBuilder提供的方法,Deployment只提供了一系列getter方法。DeploymentEntityImpl中包含以下映射属性。
➢ id:主键,对应ACT_RE_DEPLOYMENT表的ID_列。
➢ name:部署名称,对应ACT_RE_DEPLOYMENT表的NAME_列。
➢ deploymentTime:部署时间,对应DEPLOY_TIME_列。
➢ category:部署的类别,对应CATEGORY_列。
➢ tenantId:在云时代,同一个软件有可能被多个租户所使用,因此 Activiti 在部署、流程定义等数据中都预留了tenantId字段。
➢ key:为部署设置键属性,保存在KEY_列。
DeploymentBuilder对象
对流程文件进行部署,需要使用DeploymentBuilder对象,获取该对象,可以调用RepositoryService的createDeployment方法,
DeploymentBuilder中包含了多个addXXX方法,可以用于为部署添加资源,这些方法有:
➢ addClasspathResource(String resource):添加classpath下的资源文件。
➢ addInputStream(String resourceName,InputStream):添加输入流资源。
➢ addString(String resourceName,String text):添加字符串资源。
➢ addZipInputStream(ZipInputStream inputStream):添加zip压缩包资源。
➢ addBpmnModel(String resourceName,BpmnModel bpmnModel):解析BPMN模型对象,并作为资源保存。
➢ addBytes(String resourceName,byte[] bytes):添加字节资源。
除此之外,还提供了修改部署信息的方法,例如key、name、category等。下面将讲述这些方法的使用。
添加输入流资源
在DeploymentEntityImpl类中,使用一个Map来维护资源,表示一次部署中会有多个资源,就是我们平常所说的一对多关系。调用DeploymentBuilder的addInputStream方法,实际上就是往DeploymentEntityImpl的Map里面添加元素,Map的key是资源名称,value是解析InputStream后获得的byte数组。
使用addInputStream方法添加部署流程图资源。

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.DeploymentBuilder;
/**
 * 调用DeploymentBuilder的AddInputStream方法
 * 
 * @author yangenxiong
 * 
 */
public class AddInputStream {

	public static void main(String[] args) throws Exception {
		// 创建流程引擎
		ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
		// 得到流程存储服务实例
		RepositoryService repositoryService = engine.getRepositoryService();
		// 第一个资源输入流
		InputStream is1 = new FileInputStream(new File(
				"resource/artifact/flow_inputstream1.png"));
		// 第二个资源输入流
		InputStream is2 = new FileInputStream(new File(
				"resource/artifact/flow_inputstream1.png"));
		// 创建DeploymentBuilder实例
		DeploymentBuilder builder = repositoryService.createDeployment();
		// 为DeploymentBuilder添加资源输入流
		builder.addInputStream("inputA", is1);
		builder.addInputStream("inputB", is2);
		// 执行部署方法
		builder.deploy();
	}

}

在这里插入图片描述在这里插入图片描述 添加classpath资源
与addInputStream方法类似,addClasspathResource方法也是往部署实体的Map里面添加元素,但不同的是,addClasspathResource方法会得到当前的ClassLoader对象。调用getResourceAsStream方法将指定的classpath下的资源文件转换为InputStream,再调用addInputStream方法。

import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.DeploymentBuilder;

/**
 * 调用DeploymentBuilder的AddClasspathResource方法
 * @author yangenxiong
 *
 */
public class AddClasspathResource {

	public static void main(String[] args) {
		//创建流程引擎
		ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
		//得到流程存储服务对象
		RepositoryService repositoryService = engine.getRepositoryService();
		//创建DeploymentBuilder实例
		DeploymentBuilder builder = repositoryService.createDeployment();
		//添加classpath下的资源
		builder.addClasspathResource("artifact/classpath.png");
		//执行部署(写入到数据库中)
		builder.deploy();		
	}
}

使用addClasspathResource方法将一份图片文件保存到ACT_GE_BYTEARRAY表中。需要注意的是,使用addClasspathResource方法并不需要指定名称参数,Activiti会使用其传入的路径作为资源的名称。
在这里插入图片描述


import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.DeploymentBuilder;

/**
 * 调用DeploymentBuilder的AddString方法
 * @author yangenxiong
 *
 */
public class AddString {

	public static void main(String[] args) {
		//创建流程引擎
		ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
		//得到流程存储服务对象
		RepositoryService repositoryService = engine.getRepositoryService();
		//创建DeploymentBuilder实例
		DeploymentBuilder builder = repositoryService.createDeployment();
		//添加String资源
		builder.addString("test", "this is string method");
		//执行部署(写入到数据库中)
		builder.deploy();
	}

}

添加压缩包资源
在实际应用中,可能需要将多个资源部署到流程引擎中,如果这些关联的资源被放在一个压缩包(zip包)中,则可以使用DeploymentBuilder提供的addZipInputStream方法直接部署压缩包,该方法会遍历压缩包内的全部文件,然后将这些文件转换为byte数组,写到资源表中。使用addZipInputStream方法添加资源。

import java.io.File;
import java.io.FileInputStream;
import java.util.zip.ZipInputStream;

import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.DeploymentBuilder;

/**
 * 调用DeploymentBuilder的AddZipInputStream方法
 * @author yangenxiong
 *
 */
public class AddZipInputStream {

	public static void main(String[] args) throws Exception {
		//创建流程引擎
		ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
		//得到流程存储服务对象
		RepositoryService repositoryService = engine.getRepositoryService();
		//创建DeploymentBuilder实例
		DeploymentBuilder builder = repositoryService.createDeployment();
		//获取zip文件的输入流
		FileInputStream fis = new FileInputStream(new File("resource/artifact/ZipInputStream.zip"));
		//读取zip文件,创建ZipInputStream对象
		ZipInputStream zi = new ZipInputStream(fis);
		//添加Zip压缩包资源
		builder.addZipInputStream(zi);
		//执行部署(写入到数据库中)
		builder.deploy();
	}

}

添加BPMN模型资源
DeploymentBuilder提供了一个addBpmnModel方法,可传入BPMN规范的模型(BpmnModel类)来进行部署

import org.activiti.bpmn.model.BpmnModel;
import org.activiti.bpmn.model.EndEvent;
import org.activiti.bpmn.model.SequenceFlow;
import org.activiti.bpmn.model.StartEvent;
import org.activiti.bpmn.model.UserTask;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.DeploymentBuilder;

public class AddBpmnModel {

	public static void main(String[] args) {
		// 创建流程引擎
		ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
		// 得到流程存储服务对象
		RepositoryService repositoryService = engine.getRepositoryService();
		// 创建DeploymentBuilder实例
		DeploymentBuilder builder = repositoryService.createDeployment();
		builder.addBpmnModel("MyCodeProcess", createProcessModel())
				.name("MyCodeDeploy").deploy();
	}

	private static BpmnModel createProcessModel() {
		// 创建BPMN模型对象
		BpmnModel model = new BpmnModel();
		org.activiti.bpmn.model.Process process = new org.activiti.bpmn.model.Process();
		model.addProcess(process);
		process.setId("myProcess");
		process.setName("My Process");
		// 开始事件
		StartEvent startEvent = new StartEvent();
		startEvent.setId("startEvent");
		process.addFlowElement(startEvent);
		// 用户任务
		UserTask userTask = new UserTask();
		userTask.setName("User Task");
		userTask.setId("userTask");
		process.addFlowElement(userTask);
		// 结束事件
		EndEvent endEvent = new EndEvent();
		endEvent.setId("endEvent");
		process.addFlowElement(endEvent);
		// 添加流程顺序
		process.addFlowElement(new SequenceFlow("startEvent", "userTask"));
		process.addFlowElement(new SequenceFlow("userTask", "endEvent"));
		return model;
	}
}

修改部署信息
使用DeploymentBuilder的name、key、category、tenanId方法可以设置部署属性,保存后会将数据保存到ACT_RE_DEPLOYMENT表的对应字段中。

import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngineConfiguration;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.DeploymentBuilder;

/**
 * 使用DeploymentBuilder的name方法
 * @author yangenxiong
 *
 */
public class Name {

	public static void main(String[] args) {
		//创建流程引擎
		ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
		//得到流程存储服务对象
		RepositoryService repositoryService = engine.getRepositoryService();
		//创建DeploymentBuilder实例
		DeploymentBuilder builder = repositoryService.createDeployment();
		//设置各个属性
		builder.name("crazyit").tenantId("tenanId").key("myKey").category("myCategory");
		//执行部署(写入到数据库中)
		builder.deploy();
	}

}

过滤重复部署
进行了第一次部署后,资源没有发生变化而再次进行部署,同样会将部署数据写入数据库中,想避免这种情况,可以调用DeploymentBuilder的enableDuplicateFiltering方法,该方法仅将DeploymentBuilder的isDuplicateFilterEnabled属性设置为true。在执行deploy方法时,如果发现该值为true,则根据部署对象的名称去查找最后一条部署记录,如果发现最后一条部署记录与当前需要部署的记录一致,则不会重复部署。
搭建环境
创建activiti.cfg.xml配置文件

<?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="jdbcUrl" value="jdbc:mysql://localhost:3306/act" />
		<property name="jdbcDriver" value="com.mysql.jdbc.Driver" />
		<property name="jdbcUsername" value="root" />
		<property name="jdbcPassword" value="root" />
		<property name="databaseSchemaUpdate" value="true"/>
	</bean>

</beans>

创建log4j.properties配置文件

# Set root category priority to INFO and its only appender to CONSOLE.
log4j.rootCategory=INFO, CONSOLE
#log4j.rootCategory=INFO, CONSOLE, LOGFILE

# Set the enterprise logger category to FATAL and its only appender to CONSOLE.
log4j.logger.org.apache.axis.enterprise=FATAL, CONSOLE

# CONSOLE is set to be a ConsoleAppender using a PatternLayout.
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1} - %m%n
log4j.logger.org.apache=INFO
log4j.logger.org.htmlparser=INFO
log4j.logger.org.htmlparser=INFO
log4j.logger.com.angus=INFO

创建DuplicateFilter.txt

abc

创建DuplicateFilterB.txt

abc

测试

package org.crazyit.activiti;

import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngineConfiguration;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.DeploymentBuilder;

/**
 * 
 * @author yangenxiong
 *
 */
public class DuplicateFilter {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		//创建流程引擎
		ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
		//得到流程存储服务实例
		RepositoryService repositoryService = engine.getRepositoryService();
		//创建第一个部署对象
		DeploymentBuilder builderA = repositoryService.createDeployment();
		builderA.addClasspathResource("artifact/DuplicateFilter.txt");
		builderA.name("DuplicateFilterA");
		builderA.deploy();		
		//由于资源一样,并且调用了enableDuplicateFiltering方法,因此不会再写入到数据库中
		DeploymentBuilder builderB = repositoryService.createDeployment();
		builderB.addClasspathResource("artifact/DuplicateFilter.txt");
		builderB.name("DuplicateFilterA");
		builderB.enableDuplicateFiltering();
		builderB.deploy();
		//由于资源发生变化,即使调用了enableDuplicateFiltering方法,也会写到数据库中
		DeploymentBuilder builderC = repositoryService.createDeployment();
		builderC.addClasspathResource("artifact/DuplicateFilterB.txt");
		builderC.name("DuplicateFilterA");
		builderC.enableDuplicateFiltering();
		builderC.deploy();
	}
}

取消部署时的验证
默认情况下,在部署时会对流程的XML文件进行验证,包括验证是否符合BPMN 2.0的规范、定义的流程是否可执行。如果XML文件不符合规范或者定义的流程不可执行,那么将会在部署时抛出异常。如果想跳过这两个验证,可以调用DeploymentBuilder的disableSchemaValidation与disableBpmnValidation方法。
创建bpmnError.bpmn.xml配置文件

<?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="vacationProcess" name="vacation" isExecutable="true">
    <startEvent id="startevent1" name="Start"></startEvent>
    <userTask id="usertask1" name="User Task"></userTask>
    <startEvent id="startevent2" name="Start"></startEvent>
    <sequenceFlow id="flow1" sourceRef="startevent1" targetRef="usertask1"></sequenceFlow>
    <sequenceFlow id="flow2" sourceRef="usertask1" targetRef="startevent2"></sequenceFlow>
  </process>
  <bpmndi:BPMNDiagram id="BPMNDiagram_vacationProcess">
    <bpmndi:BPMNPlane bpmnElement="vacationProcess" id="BPMNPlane_vacationProcess">
      <bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1">
        <omgdc:Bounds height="35.0" width="35.0" x="50.0" y="122.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="usertask1" id="BPMNShape_usertask1">
        <omgdc:Bounds height="60.0" width="100.0" x="190.0" y="110.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="startevent2" id="BPMNShape_startevent2">
        <omgdc:Bounds height="35.0" width="35.0" x="370.0" y="122.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1">
        <omgdi:waypoint x="85.0" y="139.0"></omgdi:waypoint>
        <omgdi:waypoint x="158.0" y="139.0"></omgdi:waypoint>
        <omgdi:waypoint x="190.0" y="140.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">
        <omgdi:waypoint x="290.0" y="140.0"></omgdi:waypoint>
        <omgdi:waypoint x="370.0" y="139.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</definitions>

在这里插入图片描述创建xmlError.bpmn.xml配置文件

<?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: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="vacationProcess" name="vacation">
		<userTask id="usertask1" name="User Task"></userTask>
		<endEvent id="endevent1" name="End"></endEvent>
		<sequenceFlow id="flow2" name="" sourceRef="usertask1"
			targetRef="endevent1"></sequenceFlow>
		<startEvent id="startevent1" name="Start"></startEvent>
		<sequenceFlow id="flow3" name="" sourceRef="startevent1"
			targetRef="usertask1"></sequenceFlow>
	</process>
	<abc></abc>
	<bpmndi:BPMNDiagram id="BPMNDiagram_vacationProcess">
		<bpmndi:BPMNPlane bpmnElement="vacationProcess"
			id="BPMNPlane_vacationProcess">
			<bpmndi:BPMNShape bpmnElement="usertask1" id="BPMNShape_usertask1">
				<omgdc:Bounds height="55" width="105" x="310" y="160"></omgdc:Bounds>
			</bpmndi:BPMNShape>
			<bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1">
				<omgdc:Bounds height="35" width="35" x="490" y="170"></omgdc:Bounds>
			</bpmndi:BPMNShape>
			<bpmndi:BPMNShape bpmnElement="startevent1"
				id="BPMNShape_startevent1">
				<omgdc:Bounds height="35" width="35" x="170" y="170"></omgdc:Bounds>
			</bpmndi:BPMNShape>
			<bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">
				<omgdi:waypoint x="415" y="187"></omgdi:waypoint>
				<omgdi:waypoint x="490" y="187"></omgdi:waypoint>
			</bpmndi:BPMNEdge>
			<bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3">
				<omgdi:waypoint x="205" y="187"></omgdi:waypoint>
				<omgdi:waypoint x="310" y="187"></omgdi:waypoint>
			</bpmndi:BPMNEdge>
		</bpmndi:BPMNPlane>
	</bpmndi:BPMNDiagram>
</definitions>

在这里插入图片描述
测试

package org.crazyit.activiti;

import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.DeploymentBuilder;

public class DisableValidation {

	public static void main(String[] args) {
		// 创建流程引擎
		ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
		// 得到流程存储服务实例
		RepositoryService repositoryService = engine.getRepositoryService();
		// 部署一份错误的xml文件,不会报错
		DeploymentBuilder builderA = repositoryService.createDeployment();
		builderA.addClasspathResource("bpmn/xmlError.bpmn")
				.disableSchemaValidation().deploy();
		// 部署一份不可执行bpmn文件,不会报错
		DeploymentBuilder builderB = repositoryService.createDeployment();
		builderB.addClasspathResource("bpmn/bpmnError.bpmn")
				.disableBpmnValidation().deploy();
	}

}

流程定义的管理
这里所说的流程定义管理是指由RepositoryService提供的一系列对流程定义的控制,包括中止流程定义、激活流程定义和设置流程权限等。
ProcessDefinition对象
ProcessDefinition对象是一个接口,一个ProcessDefinition实例表示一条流程定义数据,在Activiti中,它的实现类为ProcessDefinitionEntityImpl,对应的数据表为ACT_RE_PROCDEF。ProcessDefinition接口有以下方法。
➢ getCategory:返回流程定义的category属性,对应CATEGORY_字段的值。
➢ getDeploymentId:返回部署的 id,这个流程定义是由哪次部署产生的,对应字段为DEPLOYMENT_ID_。
➢ getDescription:返回流程定义的描述。
➢ getDiagramResourceName:如果流程定义有流程图的话,将返回流程图对应的资源名称。
➢ getEngineVersion:返回流程引擎版本,当前无须关心该方法。
➢ getId:返回流程定义主键。
➢ getKey:返回流程定义的名称,此名称唯一。
➢ getName:返回流程定义显示的名称。
➢ getResourceName:在部署时,会将流程定义的XML文件存到资源表中,该方法返回资源的名称。
➢ getTenantId:返回租户ID。
➢ getVersion:返回流程定义的版本号,对应VERSION_字段,注意并不是revision属性。
➢ hasGraphicalNotation:该流程定义文件是否有流程图的XML元素。
➢ hasStartFormKey:流程的开始事件中是否存在activiti:formKey的定义。
➢ isSuspended:是否为中断状态,SUSPENSION_STATE_字段值为1表示激活状态,值为2则表示中断状态。
流程部署
流程部署实际上就是将流程的描述文件写入数据库中,Activiti在获取资源文件后,会对其后缀进行解析,如果后缀名为“BPMN 20.xml”或者“bpmn”,则它们均会被看作流程描述文件,交由Activiti的Deployer(部署流程描述文件实现类为BpmnDeployer)进行部署。
创建processDeploy.bpmn.xml配置文件

<?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: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="vacationProcess" name="vacation">
		<userTask id="usertask1" name="User Task"></userTask>
		<endEvent id="endevent1" name="End"></endEvent>
		<sequenceFlow id="flow2" name="" sourceRef="usertask1"
			targetRef="endevent1"></sequenceFlow>
		<startEvent id="startevent1" name="Start"></startEvent>
		<sequenceFlow id="flow3" name="" sourceRef="startevent1"
			targetRef="usertask1"></sequenceFlow>
	</process>
	<bpmndi:BPMNDiagram id="BPMNDiagram_vacationProcess">
		<bpmndi:BPMNPlane bpmnElement="vacationProcess"
			id="BPMNPlane_vacationProcess">
			<bpmndi:BPMNShape bpmnElement="usertask1" id="BPMNShape_usertask1">
				<omgdc:Bounds height="55" width="105" x="310" y="160"></omgdc:Bounds>
			</bpmndi:BPMNShape>
			<bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1">
				<omgdc:Bounds height="35" width="35" x="490" y="170"></omgdc:Bounds>
			</bpmndi:BPMNShape>
			<bpmndi:BPMNShape bpmnElement="startevent1"
				id="BPMNShape_startevent1">
				<omgdc:Bounds height="35" width="35" x="170" y="170"></omgdc:Bounds>
			</bpmndi:BPMNShape>
			<bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">
				<omgdi:waypoint x="415" y="187"></omgdi:waypoint>
				<omgdi:waypoint x="490" y="187"></omgdi:waypoint>
			</bpmndi:BPMNEdge>
			<bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3">
				<omgdi:waypoint x="205" y="187"></omgdi:waypoint>
				<omgdi:waypoint x="310" y="187"></omgdi:waypoint>
			</bpmndi:BPMNEdge>
		</bpmndi:BPMNPlane>
	</bpmndi:BPMNDiagram>
</definitions>

在这里插入图片描述
流程部署测试

package org.crazyit.activiti;

import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngineConfiguration;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.DeploymentBuilder;

/**
 * 部署流程文件
 * @author yangenxiong
 *
 */
public class ProcessDeploy {

	public static void main(String[] args) {
		//创建流程引擎
		ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
		//得到流程存储服务对象
		RepositoryService repositoryService = engine.getRepositoryService();
		//创建DeploymentBuilder实例
		DeploymentBuilder builder = repositoryService.createDeployment();
		builder.addClasspathResource("bpmn/processDeploy.bpmn").deploy();
	}
}

流程图部署测试代码

package org.crazyit.activiti;

import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngineConfiguration;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;

/**
 * 部署流程图
 * 
 * @author yangenxiong
 *
 */
public class DeployDiagram {

	public static void main(String[] args) {
		// 创建流程引擎
		ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
		// 得到流程存储服务实例
		RepositoryService repositoryService = engine.getRepositoryService();		
		//部署流程描述文件与流程图
		Deployment dep = repositoryService.createDeployment()
				.addClasspathResource("bpmn/diagram.bpmn")
				.addClasspathResource("bpmn/diagram.png").deploy();
		//查询流程定义实体
		ProcessDefinition def = repositoryService.createProcessDefinitionQuery()
				.deploymentId(dep.getId()).singleResult();
		// 输出结果为 bpmn/diagram.vacationProcess.png
		System.out.println(def.getDiagramResourceName());
	}
}

流程图自动生成
如果在部署时我们不提供流程图,但在流程定义的XML文件中保存了BPMN流程图的元素,则Activiti会自动生成流程图,并保存到资源表中。如果不希望Activiti帮我们生成流程图,则可以在流程引擎配置文件中加入以下属性:
在这里插入图片描述

package org.crazyit.activiti;

import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngineConfiguration;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;

public class NoGenDiagram {

	public static void main(String[] args) {
		// 创建流程引擎
		ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
		// 得到流程存储服务实例
		RepositoryService repositoryService = engine.getRepositoryService();
		// 部署流程描述文件与流程图
		Deployment dep = repositoryService.createDeployment()
				.addClasspathResource("bpmn/noGenDiagram.bpmn").deploy();
		// 查询流程定义实体
		ProcessDefinition def = repositoryService
				.createProcessDefinitionQuery().deploymentId(dep.getId())
				.singleResult();
		// 输出结果为 bpmn/diagram.vacationProcess.png
		System.out.println("自动生成流程图:" + def.getDiagramResourceName());

		// 读取不生成流程图的配置文件
		ProcessEngineConfiguration config = ProcessEngineConfiguration
				.createProcessEngineConfigurationFromResource("noGenDiagram.cfg.xml");
		ProcessEngine noGenEngine = config.buildProcessEngine();
		RepositoryService noGenService = noGenEngine.getRepositoryService();
		Deployment noGenDep = noGenService.createDeployment()
				.addClasspathResource("bpmn/noGenDiagram.bpmn").deploy();
		ProcessDefinition noGenDef = noGenService
				.createProcessDefinitionQuery().deploymentId(noGenDep.getId())
				.singleResult();
		// 输出结果为null
		System.out.println("不生成流程图,查询资源为:" + noGenDef.getDiagramResourceName());
	}
}

中止与激活流程定义
RepositoryService中提供了多个中止与激活流程定义的方法,可以将流程定义的数据置为中止与激活状态。其中有多个suspendProcessDefinitionById、suspendProcessDefinitionByKey重载的中止方法,也有多个activateProcessDefinitionById、activateProcessDefinitionByKey重载的激活方法。以activateProcessDefinitionById方法为例,有两个重载方法。
➢ activateProcessDefinitionById(String processDefinitionId):根据流程定义的id激活流程定义。
➢ activateProcessDefinitionById(String processDefinitionId,boolean activateProcessInstances,Date activationDate):在某个时间激活流程定义,需要注意的是activateProcessInstances参数,如果为true,则该流程定义下的流程实例,也会被激活。
本身流程定义就没有所谓的中止与激活的概念(流程才有),这里所说的中止与激活,只是流程定义的数据状态设置为中止状态和激活状态。流程定义文件一旦被部署,那么对应的流程定义数据状态为激活,可以调用RepositoryService的中止流程定义的方法改变其状态。RepositoryService提供了两个中止流程定义的方法。
➢ suspendProcessDefinitionById(String processDefinitionId):根据流程ID中止流程定义。
➢ suspendProcessDefinitionByKey(String processDefinitionKey):根据流程定义文件中的process 节点的 id 属性中止流程定义,也可以看作根据 ACT_RE_PROCDEF 表中的KEY_字段值中止流程定义。
当流程定义被中止后,如果想激活流程定义,同样可以使用RepositoryService中提供的激活流程定义的方法,方法描述如下。
➢ activateProcessDefinitionById(String processDefinitionId):根据流程ID激活流程定义。
➢ activateProcessDefinitionByKey(String processDefinitionKey):根据流程的key激活流程定义,与中止流程定义的suspendProcessDefinitionByKey方法一致。
创建suspendProcessDef.bpmn.xml配置文件

<?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: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="vacationProcess" name="vacation">
		<startEvent id="startevent1" name="Start"></startEvent>
		<userTask id="usertask1" name="Write Vacation"></userTask>
		<endEvent id="endevent1" name="End"></endEvent>
		<sequenceFlow id="flow1" name="" sourceRef="startevent1"
			targetRef="usertask1"></sequenceFlow>
		<sequenceFlow id="flow2" name="" sourceRef="usertask1"
			targetRef="endevent1"></sequenceFlow>
	</process>
</definitions>

在这里插入图片描述
创建activiti.cfg.xml配置文件

<?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="jdbcUrl" value="jdbc:mysql://localhost:3306/act" />
		<property name="jdbcDriver" value="com.mysql.jdbc.Driver" />
		<property name="jdbcUsername" value="root" />
		<property name="jdbcPassword" value="root" />
		<property name="databaseSchemaUpdate" value="true"/>
	</bean>

</beans>

创建log4j.properties配置文件

# Set root category priority to INFO and its only appender to CONSOLE.
log4j.rootCategory=INFO, CONSOLE
#log4j.rootCategory=INFO, CONSOLE, LOGFILE

# Set the enterprise logger category to FATAL and its only appender to CONSOLE.
log4j.logger.org.apache.axis.enterprise=FATAL, CONSOLE

# CONSOLE is set to be a ConsoleAppender using a PatternLayout.
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1} - %m%n
log4j.logger.org.apache=INFO
log4j.logger.org.htmlparser=INFO
log4j.logger.org.htmlparser=INFO
log4j.logger.com.angus=INFO

测试

import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngineConfiguration;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;

/**
 * 中断流程
 * @author yangenxiong
 *
 */
public class SuspendProcessDef {

	public static void main(String[] args) {
		// 创建流程引擎
		ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
		// 得到流程存储服务实例
		RepositoryService repositoryService = engine.getRepositoryService();
		// 部署流程描述文件
		Deployment dep = repositoryService.createDeployment()
				.addClasspathResource("bpmn/suspendProcessDef.bpmn")
				.deploy();
		//查询流程定义实体
		ProcessDefinition def = repositoryService.createProcessDefinitionQuery()
				.deploymentId(dep.getId()).singleResult();		
		// 调用suspendProcessDefinitionById中止流程定义 
		repositoryService.suspendProcessDefinitionById(def.getId());
		// 调用activateProcessDefinitionById激活流程定义 
		repositoryService.activateProcessDefinitionById(def.getId());
		// 调用suspendProcessDefinitionByKey中止流程定义 
		repositoryService.suspendProcessDefinitionByKey(def.getKey());
		// 调用activateProcessDefinitionByKey激活流程定义 
		repositoryService.activateProcessDefinitionByKey(def.getKey());
	}

}

流程定义缓存配置
为了减少数据的查询,提升流程引擎性能,Activiti本身对某些常用的数据做了缓存。例如在解析完流程定义的XML文件后,会将流程定义缓存到一个Map中,key为流程定义的id(数据库的ID_字段),value为封装好的缓存对象。默认情况下,不需要进行配置,流程引擎会进行缓存的工作。
创建default-cache.bpmn.xml配置文件

<?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: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="testCache" name="testCache">
		<userTask id="usertask1" name="User Task"></userTask>
		<endEvent id="endevent1" name="End"></endEvent>
		<sequenceFlow id="flow2" name="" sourceRef="usertask1"
			targetRef="endevent1"></sequenceFlow>
		<startEvent id="startevent1" name="Start"></startEvent>
		<sequenceFlow id="flow3" name="" sourceRef="startevent1"
			targetRef="usertask1"></sequenceFlow>
	</process>
	<bpmndi:BPMNDiagram id="BPMNDiagram_vacationProcess">
		<bpmndi:BPMNPlane bpmnElement="vacationProcess"
			id="BPMNPlane_vacationProcess">
			<bpmndi:BPMNShape bpmnElement="usertask1" id="BPMNShape_usertask1">
				<omgdc:Bounds height="55" width="105" x="310" y="160"></omgdc:Bounds>
			</bpmndi:BPMNShape>
			<bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1">
				<omgdc:Bounds height="35" width="35" x="490" y="170"></omgdc:Bounds>
			</bpmndi:BPMNShape>
			<bpmndi:BPMNShape bpmnElement="startevent1"
				id="BPMNShape_startevent1">
				<omgdc:Bounds height="35" width="35" x="170" y="170"></omgdc:Bounds>
			</bpmndi:BPMNShape>
			<bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">
				<omgdi:waypoint x="415" y="187"></omgdi:waypoint>
				<omgdi:waypoint x="490" y="187"></omgdi:waypoint>
			</bpmndi:BPMNEdge>
			<bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3">
				<omgdi:waypoint x="205" y="187"></omgdi:waypoint>
				<omgdi:waypoint x="310" y="187"></omgdi:waypoint>
			</bpmndi:BPMNEdge>
		</bpmndi:BPMNPlane>
	</bpmndi:BPMNDiagram>
</definitions>

在这里插入图片描述创建activiti.cfg.xml配置文件

<?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="jdbcUrl" value="jdbc:mysql://localhost:3306/act" />
		<property name="jdbcDriver" value="com.mysql.jdbc.Driver" />
		<property name="jdbcUsername" value="root" />
		<property name="jdbcPassword" value="root" />
		<property name="databaseSchemaUpdate" value="true"/>
	</bean>

</beans>

创建日志log4j.properties

# Set root category priority to INFO and its only appender to CONSOLE.
log4j.rootCategory=INFO, CONSOLE
#log4j.rootCategory=INFO, CONSOLE, LOGFILE

# Set the enterprise logger category to FATAL and its only appender to CONSOLE.
log4j.logger.org.apache.axis.enterprise=FATAL, CONSOLE

# CONSOLE is set to be a ConsoleAppender using a PatternLayout.
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1} - %m%n
log4j.logger.org.apache=INFO
log4j.logger.org.htmlparser=INFO
log4j.logger.org.htmlparser=INFO
log4j.logger.com.angus=INFO

创建my-cache.cfg.xml配置文件

<?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="jdbcUrl" value="jdbc:mysql://localhost:3306/act" />
		<property name="jdbcDriver" value="com.mysql.jdbc.Driver" />
		<property name="jdbcUsername" value="root" />
		<property name="jdbcPassword" value="root" />
		<property name="databaseSchemaUpdate" value="true" />
		<property name="processDefinitionCache">
			<ref bean="myCache" />
		</property>
	</bean>

	<bean id="myCache" class="org.crazyit.activiti.MyCacheBean"></bean>
</beans>

创建use-limit.cfg.xml配置文件

<?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="jdbcUrl" value="jdbc:mysql://localhost:3306/act" />
		<property name="jdbcDriver" value="com.mysql.jdbc.Driver" />
		<property name="jdbcUsername" value="root" />
		<property name="jdbcPassword" value="root" />
		<property name="databaseSchemaUpdate" value="true"/>
		<property name="processDefinitionCacheLimit" value="2" />		
	</bean>

</beans>

测试类


import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl;

/**
 * 测试默认情况下的缓存
 * 
 * @author yangenxiong
 *
 */
public class DefaultCache {

	public static void main(String[] args) {
		// 创建流程引擎
		ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
		ProcessEngineConfigurationImpl config = (ProcessEngineConfigurationImpl) engine
				.getProcessEngineConfiguration();
		// 得到流程存储服务实例
		RepositoryService repositoryService = engine.getRepositoryService();
		// 进行10次部署
		for (int i = 0; i < 10; i++) {
			repositoryService.createDeployment()
					.addClasspathResource("bpmn/default-cache.bpmn")
					.name("dep_" + i).key("key_" + i).deploy();
		}
		// 获取缓存
		DefaultDeploymentCache cache = (DefaultDeploymentCache) config
				.getProcessDefinitionCache();
		// 遍历缓存,输出Map中的key
		for (Iterator it = cache.cache.keySet().iterator(); it.hasNext();) {
			String key = (String) it.next();
			System.out.println(key);
		}
	}

}

先进行10次部署,然后读取缓存对象,获取Map属性并输出内容。需要注意以下细节:
➢ 为了测试获取了缓存的Map,代码清单7-15的包与DefaultDeploymentCache的包是一致的,换言之,Map是protected的。
➢ DefaultDeploymentCache、ProcessEngineConfigurationImpl等实现类不应出现在业务代码中,尽量使用它们的接口。
由于缓存没有限制,因此部署了10次,缓存(Map)中就有10个元素,如果想限制缓存数量,可以在流程引擎的配置文件中使用以下配置:
在这里插入图片描述


import java.util.Iterator;

import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngineConfiguration;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl;

/**
 * 测试默认情况下的缓存
 * 
 * @author yangenxiong
 *
 */
public class UserLimitCache {

	public static void main(String[] args) {
		// 创建流程引擎
		ProcessEngineConfigurationImpl config =
				 (ProcessEngineConfigurationImpl) ProcessEngineConfiguration
				.createProcessEngineConfigurationFromResource("use-limit.cfg.xml");
		ProcessEngine engine = config.buildProcessEngine();
		// 得到流程存储服务实例
		RepositoryService repositoryService = engine.getRepositoryService();
		// 进行10次部署
		for (int i = 0; i < 10; i++) {
			repositoryService.createDeployment()
					.addClasspathResource("bpmn/default-cache.bpmn")
					.name("dep_" + i).key("key_" + i).deploy();
		}
		// 获取缓存
		DefaultDeploymentCache cache = (DefaultDeploymentCache) config
				.getProcessDefinitionCache();
		// 遍历缓存,输出Map中的key
		for (Iterator it = cache.cache.keySet().iterator(); it.hasNext();) {
			String key = (String) it.next();
			System.out.println(key);
		}
	}
}

自定义缓存
如果想自己实现缓存,可以新建一个Java类,实现DeploymentCache接口,该接口主要有增、删、改、查方法,用于操作缓存数据。
自定义缓存类

import java.util.HashMap;
import java.util.Map;

import org.activiti.engine.impl.persistence.deploy.DeploymentCache;

public class MyCacheBean<T> implements DeploymentCache<T> {
	
	public Map<String, T> cache;

	public MyCacheBean() {
		cache = new HashMap<String, T>();
	}
	public T get(String id) {
		return cache.get(id);
	}
	public boolean contains(String id) {
		return cache.containsKey(id);
	}
	public void add(String id, T object) {
		cache.put(id, object);
	}
	public void remove(String id) {
		cache.remove(id);
	}
	public void clear() {
		cache.clear();
	}
}

测试类

package org.crazyit.activiti;
import java.util.Iterator;

import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngineConfiguration;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl;

public class MyCacheTest {

	public static void main(String[] args) {
		// 创建流程引擎
		ProcessEngineConfigurationImpl config =
				 (ProcessEngineConfigurationImpl) ProcessEngineConfiguration
				.createProcessEngineConfigurationFromResource("my-cache.cfg.xml");
		ProcessEngine engine = config.buildProcessEngine();		
		// 得到流程存储服务实例
		RepositoryService repositoryService = engine.getRepositoryService();
		// 进行10次部署
		for (int i = 0; i < 10; i++) {
			repositoryService.createDeployment()
					.addClasspathResource("bpmn/default-cache.bpmn")
					.name("dep_" + i).key("key_" + i).deploy();
		}
		// 获取缓存
		MyCacheBean cache = (MyCacheBean) config
				.getProcessDefinitionCache();
		// 遍历缓存,输出Map中的key
		for (Iterator it = cache.cache.keySet().iterator(); it.hasNext();) {
			String key = (String) it.next();
			System.out.println(key);
		}
	}

}

流程定义权限
对于一个用户或者用户组是否能操作(查看)某个流程定义的数据,需要进行相应的流程定义权限设置。在Activiti中,并没有对流程定义的权限进行检查,而是提供一种反向的方法,让调用者去管理这些权限数据,然后提供相应的API让使用人决定哪种数据可以被查询。

设置流程定义的用户权限
在默认情况下,所有用户(用户组)均可以根据流程定义创建流程实例(启动流程),可以使用Activiti提供的API来设置启动流程的权限数据(设置启动流程的候选用户)。Activiti提供了设置流程权限数据的API,可以调用这些API来管理这些权限数据,但是,需要注意的是,Activiti本身并不会对权限进行检查,而是提供了相应的权限查询接口,让开发者决定展示何种数据给使用者,从而达到权限控制的作用。例如提供了根据用户来获取其有权限的流程定义,根据流程定义获取有权限的用户组或者用户。Activiti的这种设计,使得在开发流程权限功能时开发人员可以有更灵活的选择。
RepositoryService中提供了addCandidateStarterUser方法,给流程定义与用户绑定权限,该方法实际上是向一个中间表中加入数据,表示流程与用户之间的关系。addCandidateStarterUser方法的第一个参数为流程定义ID,第二个参数为用户的ID。

package org.crazyit.activiti;

import org.activiti.engine.IdentityService;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.identity.User;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;

/**
 * 开始流程用户权限
 * 
 * @author yangenxiong
 *
 */
public class UserCandidate {

	public static void main(String[] args) {
		// 创建流程引擎
		ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
		// 得到流程存储服务实例
		RepositoryService repositoryService = engine.getRepositoryService();
		// 得到身份服务组件
		IdentityService identityService = engine.getIdentityService();
		// 部署流程描述文件
		Deployment dep = repositoryService.createDeployment()
				.addClasspathResource("bpmn/candidateUser.bpmn").deploy();
		// 查询流程定义实体
		ProcessDefinition def = repositoryService
				.createProcessDefinitionQuery().deploymentId(dep.getId())
				.singleResult();
		// 写入用户数据
		creatUser(identityService, "user1", "angus", "young", "abc@163.com",
				"123");
		creatUser(identityService, "user2", "angus2", "young2", "abc@163.com",
				"123");
		creatUser(identityService, "user3", "angus3", "young3", "abc@163.com",
				"123");
		// 设置用户组与流程定义的关系(设置权限)
		repositoryService.addCandidateStarterUser(def.getId(), "user1");
		repositoryService.addCandidateStarterUser(def.getId(), "user2");
	}

	// 创建用户方法
	static void creatUser(IdentityService identityService, String id,
			String first, String last, String email, String passwd) {
		// 使用newUser方法创建User实例
		User user = identityService.newUser(id);
		// 设置用户的各个属性
		user.setFirstName(first);
		user.setLastName(last);
		user.setEmail(email);
		user.setPassword(passwd);
		// 使用saveUser方法保存用户
		identityService.saveUser(user);
	}
}

创建activiti.cfg.xml配置文件

<?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="jdbcUrl" value="jdbc:mysql://localhost:3306/act" />
		<property name="jdbcDriver" value="com.mysql.jdbc.Driver" />
		<property name="jdbcUsername" value="root" />
		<property name="jdbcPassword" value="root" />
		<property name="databaseSchemaUpdate" value="true"/>
	</bean>
</beans>

创建candidateUser.bpmn.xml

<?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: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="vacationProcess" name="vacation">
		<startEvent id="startevent1" name="Start"></startEvent>
		<userTask id="usertask1" name="User Task"></userTask>
		<endEvent id="endevent1" name="End"></endEvent>
		<sequenceFlow id="flow1" name="" sourceRef="startevent1"
			targetRef="usertask1"></sequenceFlow>
		<sequenceFlow id="flow2" name="" sourceRef="usertask1"
			targetRef="endevent1"></sequenceFlow>
	</process>
	<bpmndi:BPMNDiagram id="BPMNDiagram_vacationProcess">
		<bpmndi:BPMNPlane bpmnElement="vacationProcess"
			id="BPMNPlane_vacationProcess">
			<bpmndi:BPMNShape bpmnElement="startevent1"
				id="BPMNShape_startevent1">
				<omgdc:Bounds height="35" width="35" x="160" y="170"></omgdc:Bounds>
			</bpmndi:BPMNShape>
			<bpmndi:BPMNShape bpmnElement="usertask1" id="BPMNShape_usertask1">
				<omgdc:Bounds height="55" width="105" x="280" y="160"></omgdc:Bounds>
			</bpmndi:BPMNShape>
			<bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1">
				<omgdc:Bounds height="35" width="35" x="450" y="170"></omgdc:Bounds>
			</bpmndi:BPMNShape>
			<bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1">
				<omgdi:waypoint x="195" y="187"></omgdi:waypoint>
				<omgdi:waypoint x="280" y="187"></omgdi:waypoint>
			</bpmndi:BPMNEdge>
			<bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">
				<omgdi:waypoint x="385" y="187"></omgdi:waypoint>
				<omgdi:waypoint x="450" y="187"></omgdi:waypoint>
			</bpmndi:BPMNEdge>
		</bpmndi:BPMNPlane>
	</bpmndi:BPMNDiagram>
</definitions>

在这里插入图片描述 IdentityLink对象
一个IdentityLink实例表示一种身份数据与流程数据绑定的关系,此处所说的身份数据包括用户组和用户数据,流程数据包括流程定义、流程任务等数据。IdentityLink是一个接口,与其他数据库映射实体一样,其对应的实现类为IdentityLinkEntityImpl,对应的数据表为ACT_RU_IDENTITYLINK。它包含以下映射的属性。
➢ id:主键,对应ID_字段。
➢ type:数据类型,对应TYPE_字段,Activiti为该字段提供了5个值,分别为assignee、candidate、starter、participant和owner。本章中为用户或者用户组绑定流程定义时,该值为candidate,表示创建流程实例的请求者。
➢ groupId:绑定关系中的用户组ID,对应GROUP_ID_字段。
➢ userId:绑定关系中的用户ID,对应USER_ID_字段。
➢ taskId:绑定关系中的流程任务ID,对应TASK_ID_字段。
➢ processDefId:绑定关系中的流程定义ID,对应PROC_DEF_ID_字段。
在此需要注意的是,ACT_RU_IDENTITYLINK表中还有一个REV_字段,IdentityLink-EntityImpl并没有为该字段做相应的属性映射,在实体与数据表映射的配置文件中,该字段的值被设置为1。

查询权限数据
前面介绍了如何设置流程定义的权限,那么当需要使用这些权限数据时,则可以使用IdentityService中提供的获取流程角色权限数据的方法来获取这些数据,例如根据用户获取该用户有权限启动的流程定义,根据流程定义获取有权限申请的用户和用户组数据。这些获取权限数据的方法分布在各个不同的服务组件中,如果要根据流程定义获取有权限申请的角色数据,则需要使用IdentityService;如果要根据用户或者用户组得到相应的流程定义数据,则需要使用RepositoryService。

import java.util.List;

import org.activiti.engine.IdentityService;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngineConfiguration;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.identity.Group;
import org.activiti.engine.identity.User;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.task.IdentityLink;

/**
 * 查询流程定义的权限数据
 * 
 * @author yangenxiong
 *
 */
public class CandidateQuery {

	public static void main(String[] args) {
		// 创建流程引擎
		ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
		// 得到流程存储服务实例
		RepositoryService repositoryService = engine.getRepositoryService();
		// 得到身份服务组件
		IdentityService identityService = engine.getIdentityService();
		// 部署流程描述文件
		Deployment dep = repositoryService.createDeployment()
				.addClasspathResource("bpmn/candidateQuery.bpmn").deploy();
		// 添加2个用户
		creatUser(identityService, "user1", "张三", "张三", "mail1", "123");
		creatUser(identityService, "user2", "李四", "李四", "mail2", "123");
		// 添加2个用户组
		createGroup(identityService, "group1", "经理组", "manager");
		createGroup(identityService, "group2", "员工组", "employee");
		// 查询流程定义
		ProcessDefinition def = repositoryService
				.createProcessDefinitionQuery().deploymentId(dep.getId())
				.singleResult();
		// 设置权限数据
		repositoryService.addCandidateStarterGroup(def.getId(), "group1");
		repositoryService.addCandidateStarterGroup(def.getId(), "group2");
		repositoryService.addCandidateStarterUser(def.getId(), "user1");
		repositoryService.addCandidateStarterUser(def.getId(), "user2");
		// 根据用户查询用权限的流程定义
		List<ProcessDefinition> defs = repositoryService
				.createProcessDefinitionQuery().startableByUser("user1").list();
		System.out.println("用户张三有权限的流程定义为:");// 结果为1
		for (ProcessDefinition dft : defs) {
			System.out.println("   " + dft.getName());
		}
		// 根据流程定义查询用户组数据
		List<Group> groups = identityService.createGroupQuery()
				.potentialStarter(def.getId()).list();
		System.out.println("以下用户组对流程定义有权限:");
		for (Group group : groups) {
			System.out.println("   " + group.getName());
		}
		// 根据流程定义查询用户数据
		List<User> users = identityService.createUserQuery()
				.potentialStarter(def.getId()).list();
		System.out.println("以下用户对流程定义有权限:");// 结果为2
		for (User user : users) {
			System.out.println("   " + user.getFirstName());
		}
		// 根据流程定义查询全部的 IdentityLink(ACT_RU_IDENTITYLINK表) 数据
		List<IdentityLink> links = repositoryService
				.getIdentityLinksForProcessDefinition(def.getId());
		System.out.println("与流程定义相关的数据量: " + links.size());// 结果为4
	}

	// 将用户组数据保存到数据库中
	static void createGroup(IdentityService identityService, String id,
			String name, String type) {
		// 调用newGroup方法创建Group实例
		Group group = identityService.newGroup(id);
		group.setName(name);
		group.setType(type);
		identityService.saveGroup(group);
	}

	// 创建用户方法
	static void creatUser(IdentityService identityService, String id,
			String first, String last, String email, String passwd) {
		// 使用newUser方法创建User实例
		User user = identityService.newUser(id);
		// 设置用户的各个属性
		user.setFirstName(first);
		user.setLastName(last);
		user.setEmail(email);
		user.setPassword(passwd);
		// 使用saveUser方法保存用户
		identityService.saveUser(user);
	}
}

➢ ProcessDefinitionQuery的startableByUser方法:该方法用于根据用户ID查询该用户有权限启动的流程定义数据。
➢ GroupQuery的potentialStarter方法:根据流程定义ID查询有权限启动的用户组数据。
➢ UserQuery的potentialStarter方法:根据流程定义ID查询有权限启动的用户数据。
➢ RepositoryService的getIdentityLinksForProcessDefinition方法:根据流程定义ID查询与之相关的全部权限数据。

RepositoryService数据查询与删除
使用DeploymentBuilder对象将流程描述文件、流程资源等文件保存到数据库中,本节将讲述如何使用RepositoryService提供的方法管理这些资源数据,这些资源包括部署的文件、流程描述文件、流程图文件等。
查询部署资源
部署资源包括与部署相关的文件、流程描述文件、流程图等,可以使用DeploymentBuilder的addXXX方法将相关的资源文件保存到数据库中,如果需要使用这些文件,则可以调用RepositoryService的getResourceAsStream方法,只需要提供部署(Deployment)ID和资源名称,就可以返回资源的输入流对象
创建GetResource.txt文件

www
package org.crazyit.activiti;

import java.io.InputStream;

import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngineConfiguration;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Deployment;

/**
 * 查询部署资源
 * 
 * @author yangenxiong
 * 
 */
public class GetResource {

	public static void main(String[] args) throws Exception {
		// 创建流程引擎
		ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
		// 得到流程存储服务对象
		RepositoryService repositoryService = engine.getRepositoryService();
		// 部署一份txt文件
		Deployment dep = repositoryService.createDeployment()
				.addClasspathResource("artifact/GetResource.txt").deploy();
		// 查询资源文件
		InputStream is = repositoryService.getResourceAsStream(dep.getId(), 
				"artifact/GetResource.txt");
		// 读取输入流
		int count = is.available();
		byte[] contents = new byte[count];
		is.read(contents);
		String result = new String(contents);
		//输入结果
		System.out.println(result);
	}

}

查询流程文件
部署流程描述文件的时候,Activiti会向资源表中写入该文件的内容,即先将其看作一份普通的文件进行解析与数据保存,然后再解析它的文件内容,并生成相应的流程定义数据。与查询部署资源的getResourceAsStream方法一样,RepositoryService提供了一个getProcessModel方法,调用该方法只需要提供流程定义的ID即可返回流程文件的InputStream实例。
创建getProcessModel.bpmn配置文件
在这里插入图片描述
创建getProcessModel.bpmn.xml

<?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: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="vacationProcess" name="vacation">
    <startEvent id="startevent1" name="Start"></startEvent>
    <userTask id="usertask1" name="Write Vacation"></userTask>
    <endEvent id="endevent1" name="End"></endEvent>
    <sequenceFlow id="flow1" name="" sourceRef="startevent1" targetRef="usertask1"></sequenceFlow>
    <sequenceFlow id="flow2" name="" sourceRef="usertask1" targetRef="endevent1"></sequenceFlow>
  </process>
</definitions>

查询流程图
在部署一个流程的时候,可以由Activiti生成流程图,也可以由我们提供,可以使用RepositoryService的getProcessDiagram方法返回该流程图的InputStream对象。调用getProcessDiagram方法同样需要提供流程定义ID,根据流程定义数据得到部署数据ID与部署资源名称,再到资源表中查询相应的文件数据返回。
在这里插入图片描述

package org.crazyit.activiti;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;

import javax.imageio.ImageIO;

import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngineConfiguration;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;

/**
 * 查询流程图
 * 
 * @author yangenxiong
 * 
 */
public class GetProcessDiagram {

	public static void main(String[] args) throws Exception {
		// 创建流程引擎
		ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
		// 得到流程存储服务对象
		RepositoryService repositoryService = engine.getRepositoryService();
		// 部署一份流程文件与相应的流程图文件
		Deployment dep = repositoryService.createDeployment()
				.addClasspathResource("bpmn/getProcessDiagram.bpmn")
				.addClasspathResource("bpmn/getProcessDiagram.png").deploy();
		// 查询流程定义
		ProcessDefinition def = repositoryService.createProcessDefinitionQuery()
				.deploymentId(dep.getId()).singleResult();
		// 查询资源文件
		InputStream is = repositoryService.getProcessDiagram(def.getId());
		// 将输入流转换为图片对象	
		BufferedImage image = ImageIO.read(is);
		// 保存为图片文件
		File file = new File("resource/artifact/result.png");
		if (!file.exists()) file.createNewFile();
		FileOutputStream fos = new FileOutputStream(file);
		ImageIO.write(image, "png", fos);
		fos.close();
		is.close();
	}
}

查询部署资源名称

package org.crazyit.activiti;

import java.util.List;

import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngineConfiguration;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Deployment;

/**
 * 查询部署资源名称
 * 
 * @author yangenxiong
 * 
 */
public class GetResourceNames {

	public static void main(String[] args) throws Exception {
		// 创建流程引擎
		ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
		// 得到流程存储服务对象
		RepositoryService repositoryService = engine.getRepositoryService();
		// 部署一份流程文件与相应的流程图文件
		Deployment dep = repositoryService.createDeployment()
				.addClasspathResource("bpmn/GetResourceNames.bpmn")
				.addClasspathResource("bpmn/GetResourceNames.png").deploy();
		// 查询资源文件名称集合
		List<String> names = repositoryService.getDeploymentResourceNames(dep.getId());
		for (String name : names) {
			System.out.println(name);
		}
	}
}

删除部署资源
在前面章节,使用了RepositoryService的各个方法来查询部署所产生的相关资源数据。如果需要删除这些数据,则可以使用RepositoryService提供的两个删除方法,这两个方法的描述如下。
➢ deleteDeployment(String deploymentId):删除部署数据,不进行级联删除,这里所说的级联删除,是指与该部署相关的流程实例数据的删除。
➢ deleteDeployment(String deploymentId,boolean cascade):是否进行级联删除,由调用者决定。如果cascade参数为false,效果等同于deleteDeployment(String deploymentId)方法;如果cascade为true,则会删除部署相关的流程实例数据。
不管删除部署数据时是否指定级联删除,部署的相关数据均会被删除,包括身份数据(IdentityLink)、流程定义数据(ProcessDefinition)、流程资源(Resource)与部署数据(Deployment)。代码清单7-26示范了如何调用两个删除部署数据的方法。

package org.crazyit.activiti;

import java.util.List;

import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngineConfiguration;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Deployment;

/**
 * 使用DeploymentQuery的deploymentId方法
 * @author yangenxiong
 *
 */
public class DeploymentQuery {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// 创建流程引擎
		ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
		// 得到流程存储服务实例
		RepositoryService repositoryService = engine.getRepositoryService();
		// 写入5条Deployment数据
		Deployment depA = repositoryService.createDeployment().addString("a1", "a1")
				.addString("a2", "a2").addString("a3", "a3").name("a").deploy();
		Deployment depB = repositoryService.createDeployment().addString("b1", "b1")
				.addString("b2", "b2").addString("b3", "b3").name("b").deploy();
		Deployment depC = repositoryService.createDeployment().addString("c1", "c1")
				.addString("c2", "c2").addString("c3", "c3").name("c").deploy();
		Deployment depD = repositoryService.createDeployment().addString("d1", "d1")
				.addString("d2", "d2").addString("d3", "d3").name("da").deploy();
		Deployment depE = repositoryService.createDeployment().addString("e1", "e1")
				.addString("e2", "e2").addString("e3", "e3").name("eb").deploy();
		//deploymentId方法
		Deployment depAQuery = repositoryService.createDeploymentQuery()
				.deploymentId(depA.getId()).singleResult();
		System.out.println("根据id查询:" + depAQuery.getName());
		//deploymentName方法
		Deployment depBQuery = repositoryService.createDeploymentQuery()
				.deploymentName("b").singleResult();
		System.out.println("查询名称为b:" + depBQuery.getName());
		//deploymentNameLike, 模糊查询,结果集为2
		List<Deployment> depCQuery = repositoryService.createDeploymentQuery()
				.deploymentNameLike("%b%").list();
		System.out.println("模糊查询b,结果数量:" + depCQuery.size());
	}
}

DeploymentQuery对象
Activiti中的每个查询对象(XXXQuery)均有自己相应的查询方法和排序方法(详细请见第6章),本章的DeploymentQuery对象包括如下方法。
➢ deploymentId(String id):添加ID查询条件,查询ID为参数值的数据记录。
➢ deploymentName(String name):添加名称查询条件,查询Deployment名称为参数值的数据记录。
➢ deploymentNameLike(String name):添加模糊查询条件,查询Deployment名称含有参数值的数据记录。
➢ orderByDeploymentId:设置查询结果按照Deployment的ID进行排序,排序方式由asc与desc方法决定。
➢ orderByDeploymentTime:设置查询结果按照DEPLOY_TIME_字段排序。
➢ orderByDeploymentName:设置查询结果按照Deployment名称排序。

package org.crazyit.activiti;

import java.util.List;

import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngineConfiguration;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Deployment;

/**
 * 使用DeploymentQuery的deploymentId方法
 * @author yangenxiong
 *
 */
public class DeploymentQuery {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// 创建流程引擎
		ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
		// 得到流程存储服务实例
		RepositoryService repositoryService = engine.getRepositoryService();
		// 写入5条Deployment数据
		Deployment depA = repositoryService.createDeployment().addString("a1", "a1")
				.addString("a2", "a2").addString("a3", "a3").name("a").deploy();
		Deployment depB = repositoryService.createDeployment().addString("b1", "b1")
				.addString("b2", "b2").addString("b3", "b3").name("b").deploy();
		Deployment depC = repositoryService.createDeployment().addString("c1", "c1")
				.addString("c2", "c2").addString("c3", "c3").name("c").deploy();
		Deployment depD = repositoryService.createDeployment().addString("d1", "d1")
				.addString("d2", "d2").addString("d3", "d3").name("da").deploy();
		Deployment depE = repositoryService.createDeployment().addString("e1", "e1")
				.addString("e2", "e2").addString("e3", "e3").name("eb").deploy();
		//deploymentId方法
		Deployment depAQuery = repositoryService.createDeploymentQuery()
				.deploymentId(depA.getId()).singleResult();
		System.out.println("根据id查询:" + depAQuery.getName());
		//deploymentName方法
		Deployment depBQuery = repositoryService.createDeploymentQuery()
				.deploymentName("b").singleResult();
		System.out.println("查询名称为b:" + depBQuery.getName());
		//deploymentNameLike, 模糊查询,结果集为2
		List<Deployment> depCQuery = repositoryService.createDeploymentQuery()
				.deploymentNameLike("%b%").list();
		System.out.println("模糊查询b,结果数量:" + depCQuery.size());
	}

}

标签:engine,存储,activiti,流程,第七篇,org,import,repositoryService
来源: https://blog.csdn.net/weixin_43912996/article/details/112220439

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有