上一篇模拟了流程执行,这一篇来看下流程定义的管理。
1.设计流程定义文档
-
流程图
-
BPMN文件
BPMN 2.0根节点是definitions节点。 这个元素中,可以定义多个流程定义(不过建议每个文件只包含一个流程定义, 这样可以简化开发过程中的维护难度)。注意,definitions元素 最少也要包含xmlns 和 targetNamespace的声明。 targetNamespace可以是任意值,它用来对流程实例进行分类。
说明:流程定义文档由两部分组成:
1)bpmn文件
流程规则文件。在部署后,每次系统启动时都会被解析,把内容封装成流程定义放入项目缓存中。Activiti框架结合这个xml文件自动管理流程,流程的执行就是按照bpmn文件定义的规则执行的,bpmn文件是给系统执行用的。
2)流程图的png图片
在系统里需要展示流程的进展状况,图片是给用户看的。
2.部署流程定义(classpath路径加载)
private final ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
/**
* 功能: 部署流程定义classpath.<br/>
* date: 2014年12月16日 下午1:02:11 <br/>
*
* @author xzzhao@wisdombud.com
*/
@Test
public void deploymentProcessDefinitionByClassPath() {
Deployment deployment = processEngine.getRepositoryService()
// 与流程定义和部署相关的Service
.createDeployment()
// 创建部署对象
.name("流程定义")
// 部署名称
.addClasspathResource("diagrams/helloworld.bpmn").addClasspathResource("diagrams/helloworld.png")
.deploy(); // 部署
System.out.println("部署ID:" + deployment.getId());
System.out.println("部署名称:" + deployment.getName());
}
说明:
1)先获取流程引擎对象:在创建时会自动加载classpath下的activiti.cfg.xml。
2)通过流程引擎获取了一个RepositoryService对象(仓库服务对象)。
3)由仓库的服务对象产生一个部署对象配置对象,用来封装部署操作的相关配置。
4)在部署配置对象中设置显示名,上传流程定义规则文件。
5) 向数据库表中存放流程定义的规则信息。
添加操作设计到数据库中的三张表:
1. act_re_deployment(部署对象表)
存放流程定义的名称和部署时间,每部署一次增加一条记录。
2.act_re_procdef(流程定义表)
存放流程定义的属性信息,部署每个新的流程定义都会在这张表中增加一条记录。
注意:当流程定义的key相同的情况下,使用的是版本升级。
3.act_ge_bytearray(资源文件表)
存储流程定义相关的部署信息。即流程定义文档的存放地。每部署一次就会增加两条记录,一条是关于bpmn规则文件的,一条是图片的(如果部署时只指定了bpmn一个文件,activiti会在部署时解析bpmn文件内容自动生成流程图)。两个文件不是很大,都是以二进制形式存储在数据库中。
4. act_ge_property (主键生成策略表) (顺带提下)
这是一张主键生成策略表。
2.部署流程定义(zip格式文件)
首先将两个流程定义文档helloworld.bpmn和helloworld.png打包为zip格式的文件放到resource目录,使用zip的输入流部署流程定义。
/**
* 功能: 部署流程定义zip.<br/>
* date: 2014年12月16日 下午2:09:03 <br/>
*
* @author xzzhao@wisdombud.com
*/
@Test
public void deploymentProcessDefinitionByZip() {
InputStream in = this.getClass().getClassLoader().getResourceAsStream("diagrams/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());
}
3.查看流程定义
/**
* 功能: 流程定义的查询.<br/>
* date: 2014年12月16日 下午2:58:21 <br/>
*
* @author xzzhao@wisdombud.com
*/
@Test
public void queryProcessDefinition() {
List<ProcessDefinition> list = processEngine.getRepositoryService()// 与流程定义和部署对象相关Service
.createProcessDefinitionQuery() // 创建流程定义查询
// .deploymentId(deploymentId) 使用部署对象Id查询
// .processDefinitionId(processDefinitionId) 使用流程定义Id查询
// .processDefinitionKey(processDefinitionKey) 使用流程定义key查询
// .processDefinitionNameLike(processDefinitionNameLike)
// 使用流程定义名称模糊查询 ...
/** 排序 */
// .orderByProcessDefinitionVersion().asc() 按照版本的升序排列
// .orderByProcessDefinitionName().desc() 按照流程定义名称降序排列
// .singleResult(); 返回唯一结果集
// .count() 返回记录数
// .listPage(firstResult, maxResults) 分页查询
.list();// 返回集合
if (null != list && list.size() > 0) {
for (ProcessDefinition pd : list) {
System.out.println("流程定义ID:" + pd.getId()); // key + 版本 + 随机数
System.out.println("流程定义的名称:" + pd.getName()); // 对应bpmn文件中Name属性
System.out.println("流程定义的key:" + pd.getKey()); // 对应bpmn文件中ID属性
System.out.println("流程定义的版本:" + pd.getVersion()); // 当流程定义的key值相同下,版本升级,默认是1
System.out.println("部署对象的ID:" + pd.getDeploymentId());
System.out.println("资源文件bpmn名称:" + pd.getResourceName());
System.out.println("资源文件png名称:" + pd.getDiagramResourceName());
System.out.println("############################################");
}
}
}
说明:
1)流程定义和部署对象相关的Service都是RepositoryService。
2)创建流程定义查询对象,可以在ProcessDefinitionQuery上设置查询的相关参数。
3)调用ProcessDefinitionQuery对象的list方法,执行查询,获得符合条件的流程定义列表。
4)由运行结果可以看出Key和Name的值为:bpmn文件process节点的id和name的属性值
5)key属性被用来区别不同的流程定义。
6)带有特定key的流程定义第一次部署时,version为1。之后每次部署都会在当前最高版本号上加1。
7)Id的值的生成规则为:{processDefinitionKey}:{processDefinitionVersion}:{generated-id},这里的generated-id是一个自动生成的唯一的数字。
8)重新部署一次,deploymentId的值是由规则变化的,具体规则由act_ge_property表生成。
4.删除流程定义
/**
* 功能: 删除流程定义.<br/>
* date: 2014年12月16日 下午3:41:06 <br/>
*
* @author xzzhao@wisdombud.com
*/
@Test
public void deleteProcessDefinition() {
// 使用部署Id删除
String deploymentId = "901";
// 不带级联删除,只能删除没有启动的流程,流程启动则抛出异常
// processEngine.getRepositoryService().deleteDeployment(deploymentId);
// 级联删除,会删除该流程所有相关的信息,包括历史信息
processEngine.getRepositoryService().deleteDeployment(deploymentId, true);
System.out.println("删除成功!");
}
说明:
1)删除流程定义首先获取RepositoryService。
2)如果该流程定义下没有正在运行的流程,则可以用普通删除。如果是有关联的信息,用级联删除。实际项目开发中使用级联删除的情况比较多,删除操作一般只开放给超级管理员使用。