Activiti——管理流程定义(四)

Activiti——管理流程定义

1.设计流程定义文档

1.1.流程图


1.2.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="HelloWorldProcess" 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="250.0" y="70.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1">
        <omgdc:Bounds height="35.0" width="35.0" x="250.0" y="400.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="usertask1" id="BPMNShape_usertask1">
        <omgdc:Bounds height="55.0" width="105.0" x="215.0" y="140.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="usertask2" id="BPMNShape_usertask2">
        <omgdc:Bounds height="55.0" width="105.0" x="215.0" y="220.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="usertask3" id="BPMNShape_usertask3">
        <omgdc:Bounds height="55.0" width="105.0" x="215.0" y="296.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1">
        <omgdi:waypoint x="267.0" y="105.0"></omgdi:waypoint>
        <omgdi:waypoint x="267.0" y="140.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">
        <omgdi:waypoint x="267.0" y="195.0"></omgdi:waypoint>
        <omgdi:waypoint x="267.0" y="220.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3">
        <omgdi:waypoint x="267.0" y="275.0"></omgdi:waypoint>
        <omgdi:waypoint x="267.0" y="296.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow4" id="BPMNEdge_flow4">
        <omgdi:waypoint x="267.0" y="351.0"></omgdi:waypoint>
        <omgdi:waypoint x="267.0" y="400.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</definitions>
说明:流程定义文档有两部分组成。

1)bpmn文件

     流程规则文件。在部署后,每次系统启动时候都会被解析,把内容封装成流程定义放入项目缓存中。

Activiti框架结合这个xml文件自动管理流程,流程的执行就是按照bpmn文件定义的规则执行的,

bpmn文件是给计算机执行用的
2)展示流程图的图片

     在系统需要展示流程的进展图片,图片时给用户看的


2.部署流程定义(classpath路径加载文件)

   【代码片段】

/**
	 * 部署流程定义
	 */
	@Test
	public void deploymentProcessDefinition() {
		Deployment deployment = processEngine.getRepositoryService()// 与流程定义和部署对象相关的Service
				.createDeployment()// 创建一个部署对象
				.name("HelloWorld入门程序")// 添加部署的名称
				.addClasspathResource("diagrans/helloword.bpmn")// 从类路径(classpath)下加载文件,一次只能加载一个文件
				.addClasspathResource("diagrans/helloword.png")// 从类路径(classpath)下加载文件,一次只能加载一个文件
				.deploy();// 完成部署

		
	}
说明:

1)先获取流程引擎对象,在创建时会自动加载classpath下的activiti.cfg.xml

 ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
2)首先获得默认的流程引擎,通过流程引擎获取了一个RepositoryService对象(仓库对象)。

3)由仓库的服务对象产生一个部署对象配置对象,用来封装部署操作的相关配置。

4)这是一个链式编程,在部署配置对象中设置显示名,上传流程定义规则文件。

5)向数据库表中存放流程定义的规则信息。

6)这一步在数据库中将操作三张表:

act_re_deployment部署对象表
存放流程定义的显示名和部署时间,每部署一次增加一条记录。
act_re_procdef流程定义表
存放流程定义的属性信息,部署每个新的流程定义都会在这张表中增加一条记录
注意:当流程定义的key相同的情况下,使用的是版本升级。
act_ge_bytearray资源文件表
存储流程定义相关的部署信息。即在流程定义文档的存放地。每部署一次就会增加两条记录,一条是bpmn规则文件的,另一条是图片的(如果部署时只指定了bpmn一个文件,activiti会在部署时解析bpmn文件内容自动生成流程图),两个文件不是很大,都是二进制形式存储在数据库中。



3.部署流程定义(zip格式文件)

/**
	 * 部署流程定义(zip格式文件)
	 */
	@Test
	public void deploymentProcessDefinitionZip() {
		//加载zip资源文件
		InputStream in = this.getClass().getClassLoader().getResourceAsStream("diagrans/helloword.zip");
		ZipInputStream zipInputStream = new ZipInputStream(in);
		
		Deployment deployment = processEngine.getRepositoryService()// 与流程定义和部署对象相关的Service
				.createDeployment()// 创建一个部署对象
				.name("程序定义(ZIP)")// 添加部署的名称
				.addZipInputStream(zipInputStream)// 从类路径(classpath)下加载文件,一次只能加载一个文件 
				.deploy();// 完成部署

		System.out.println("=======打印部署对象信息========");
		System.out.println("流程ID:" + deployment.getId());// 流程ID:10001
		System.out.println("流程部署名称:" + deployment.getName());// 流程部署名称:程序定义(ZIP)
		System.out.println(deployment);// DeploymentEntity[id=10001, name=程序定义(ZIP)]

	}



3.查看流程定义

/**
	 * 查询流程定义
	 */
	@Test
	public void findProcessDefinition(){
		List<ProcessDefinition> list =processEngine.getRepositoryService()
		.createProcessDefinitionQuery()//创建流程定义查询对象
		/**指定查询条件 where条件*/
		//.deploymentId(deploymentId)//使用部署对象的ID查询
		//.processDefinitionId(processDefinitionId)//使用流程定义ID查询
		//.processDefinitionKey(processDefinitionKey)//使用流程定义的Key查询
		//.processDefinitionNameLike(processDefinitionNameLike)//使用流程定义名称进行模糊查询
		
		/**排序*/
		//.orderByProcessDefinitionVersion().asc()//安照版本的升序排列
		.orderByProcessDefinitionName().desc()//按照流程定义名称降序排列
		
		/**返回结果集*/
		.list();//返回List结果集
		//.listPage(firstResult, maxResults)//分页查询
		//.singleResult();//返回单个记录结果集
		//.count();//返回记录统计数
		
		if(list!=null && list.size()>0){
			for(ProcessDefinition processDef:list){
				System.out.println("流程定义ID:"+processDef.getId());//流程定义的key+版本+随机数
				System.out.println("流程定义名称:"+processDef.getName());//对应helloworld.bpmn文件中的name属性值
				System.out.println("流程定义的Key:"+processDef.getKey());//对应helloworld.bpmn文件中的id属性值
				System.out.println("流程定义的版本:"+processDef.getVersion());//当流程定义的key值相同的情况下,版本升级,默认1
				System.out.println("资源名称bpmn文件:"+processDef.getResourceName());
				System.out.println("资源名称png文件:"+processDef.getDiagramResourceName());
				System.out.println("部署对象ID:"+processDef.getDeploymentId());
				System.out.println("===========快乐分割线===============");
			}
		}
		
		
		
	}
说明:

1)流程定义和部署对象相关的Service都是RepositoryService.

2)创建流程定义查询对象,可以在ProcessDefinitionQuery上设置查询的相关参数

3)调用ProccessDefinitionQuery对象的list方法,执行查询,获得符合条件的流程定义列表

4)由运行结果可以看出:

    Key和Name的值为:bpmn文件 process节点的id和name属性值

<?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="HelloWorldProcess"  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>
.........

5)key属性被用来区分不同的流程定义。

6)带有特定Key的流程定义第一次部署时,version为1,之后每次部署都会在当前最高版本号上加1

7)id的值的生成规则为(processDefinitionKey):(processDefinitionVersion):(generated-id),这里的generated-id是一个

    自动生成的唯一的数字。

8)重复部署一次,deploymentid的值以一定的形式变化,规则act_ge_property表生成


5.删除流程定义

	/**
	 * 删除流程定义
	 */
	@Test
	public void deleteProcessDefinition(){
		String deploymentId = "30001";//部署流程定义ID
		processEngine.getRepositoryService()
		.deleteDeployment(deploymentId);//不带级联的删除只能删除没用启动的流程,如果流程启动就会抛出异常
		//.deleteDeployment(deploymentId, true);//级联删除(不管是有无启动的流程都能删除)
		System.out.println("删除成功!");
		
	}

说明:

1)因为删除的是流程定义,而流程定义的部署时属于仓库服务的,所以应该先得到RepositoryService

2)如果该流程定义下没有正在运行的流程,则可以用普通删除,如果是有关联的信息(启动的流程)可以使用级联删除。

项目开发中使用级联删除的情况比较多,删除操作一般只开放给超级管理员使用


6.获取流程定义文档的资源(查看流程图附件)

/**
	 * 获取流程定义文档资源
	 * @throws IOException
	 */
	@Test
	public void viewProcessPic() throws IOException {
		//流程部署ID
		String deploymentId = "40001";
		
		//图片资源名称
		String resourceName = null;
		List<String> list =processEngine.getRepositoryService()
		.getDeploymentResourceNames(deploymentId);
		if(list!=null&& list.size()>0){
			for(String val :list){
				System.out.println(val);
				if(val.endsWith(".png")){
					resourceName = val;
				}
			}
		}
		
		if(resourceName == null){
			throw new RuntimeException("resourceName is null");
		}
		
		InputStream in = processEngine.getRepositoryService()
		.getResourceAsStream(deploymentId, resourceName);
		FileUtils.copyInputStreamToFile(in, new File("F:/helloworld.png"));
	}

说明:

1)deploymentId为流程部署ID。

2)resourceName 为 act_ge_bytearry表中NAME列的值。

3)使用repositoryService的getDeploymentResourceNames 方法可以获取指定部署下的所有文件名称。

4)使用repositoryService的getResouceAsStream 方法传入部署ID和资源图片名称可以获取部署下指定名称文件的输入流。

5)最后的有关IO流的操作,使用FileUtils工具的 copyInputStreamToFile方法(apache common-io包)完成流程到文件的拷贝,

将资源文件以流的形式输出到指定文件夹下。


7.附加功能:查询最新版的流程定义

/**
	 * 附加功能:查询最新版的流程定义
	 */
	@Test
	public void findLastVersionProcessDefinition(){
		
		//方式①
		List<ProcessDefinition>	list =processEngine.getRepositoryService()
			.createProcessDefinitionQuery()
			.orderByProcessDefinitionVersion().asc()
			.list();
		
		//使用key合并,保留最新版本
		Map<String,ProcessDefinition> linkMap = new LinkedHashMap<String, ProcessDefinition>();
		if(list!=null && list.size()>0){
			for(ProcessDefinition processDef:list){
				linkMap.put(processDef.getKey(), processDef);
			}
		}
		
		List<ProcessDefinition>  outList =new ArrayList<ProcessDefinition>(linkMap.values());
		if(outList!=null && outList.size()>0){
			for(ProcessDefinition processDef:outList){
				System.out.println("流程定义ID:"+processDef.getId());//流程定义的key+版本+随机数
				System.out.println("流程定义名称:"+processDef.getName());//对应helloworld.bpmn文件中的name属性值
				System.out.println("流程定义的Key:"+processDef.getKey());//对应helloworld.bpmn文件中的id属性值
				System.out.println("流程定义的版本:"+processDef.getVersion());//当流程定义的key值相同的情况下,版本升级,默认1
				System.out.println("资源名称bpmn文件:"+processDef.getResourceName());
				System.out.println("资源名称png文件:"+processDef.getDiagramResourceName());
				System.out.println("部署对象ID:"+processDef.getDeploymentId());
				System.out.println("===========快乐分割线===============");
			}
		}
		
		
		
		//方式②	更简便的方式
		ProcessDefinition lastVersionProcessDefinition =	processEngine.getRepositoryService()
				.createProcessDefinitionQuery()
				.processDefinitionKey("helloworld")
				.latestVersion()//设置获取最后一个版本的标记
				.singleResult();
			
				if(lastVersionProcessDefinition!=null){
					System.out.println("流程定义ID:"+lastVersionProcessDefinition.getId());//流程定义的key+版本+随机数
					System.out.println("流程定义名称:"+lastVersionProcessDefinition.getName());//对应helloworld.bpmn文件中的name属性值
					System.out.println("流程定义的Key:"+lastVersionProcessDefinition.getKey());//对应helloworld.bpmn文件中的id属性值
					System.out.println("流程定义的版本:"+lastVersionProcessDefinition.getVersion());//当流程定义的key值相同的情况下,版本升级,默认1
					System.out.println("资源名称bpmn文件:"+lastVersionProcessDefinition.getResourceName());
					System.out.println("资源名称png文件:"+lastVersionProcessDefinition.getDiagramResourceName());
					System.out.println("部署对象ID:"+lastVersionProcessDefinition.getDeploymentId());
				}
			
		
	}



8.附加功能:删除流程定义(删除key相同的所有不同版本的流程定义)

/**
	 * 附加功能:删除流程定义(删除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 processDefinition : list) {
				//根据迭代的每个部署ID进行级联删除
				processEngine.getRepositoryService()
							 .deleteDeployment(processDefinition.getDeploymentId(), true);
				System.out.println("删除部署定义:" + processDefinition.getDeploymentId());
			}
		}
		System.out.println("删除成功!");

	}

9.总结

Deployment 部署对象

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

2)对应的表:

act_re_deployment  部署对象表

act_re_procdef 流程定义表

act_ge_bytearray 资源文件表

act_ge_property 主键生成策略表

ProcessDefinition 流程定义

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




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值