部署流程定义
部署流程定义的流程:
1. 先获取流程引擎对象: 在创建时会自动加载 classpath 下的 activiti.cfg.xml
2. 首先获得默认的流程引擎, 通过流程引擎获取了一个 RepositoryService 对象 (仓库对象)
3. 由仓库的服务对象产生一个部署对象配置对象, 用来封装部署操作的相关配置.
4. 这是一个链式编程, 在部署配置对象中设置显示名, 上传流程定义规则文件
5. 向数据库表中存放流程定义的规则信息.
部署流程定义加载资源文件有两种方式
1, 从 classpath 路径加载文件
- deploymentBuilder.addClasspathResource("diagrams/hello.bpmn");
- deploymentBuilder.addClasspathResource("diagrams/hello.png");
2, 使用 zip 的输入流用作部署流程定义
- InputStream in = this.getClass().getClassLoader().getResourceAsStream("diagrams/hello.zip");
- ZipInputStream zipInputStream = new ZipInputStream(in);
- deploymentBuilder.addZipInputStream(zipInputStream);
注: 打 zip 包的时候, 不要有文件夹, 直接对 bpmn 和 png 文件打包
示例:
- @Test
- public void testDeploy() {
- /**
- * RepositoryService 是 Activiti 的仓库服务类, 流程定义和部署对象相关的 Service
- * 所谓的仓库指流程定义文档的两个文件: bpmn 文件和流程图片
- */
- RepositoryService repositoryService = processEngine.getRepositoryService();
- // 创建一个部署对象 DeploymentBuilder, 用来定义流程部署的相关参数
- DeploymentBuilder deploymentBuilder = repositoryService.createDeployment();
- // 添加部署的名称
- deploymentBuilder.name("流程定义");
- // 第一种方式: 添加 hello.bpmn 和 hello.png
- // deploymentBuilder.addClasspathResource("diagrams/hello.bpmn");
- // deploymentBuilder.addClasspathResource("diagrams/hello.png");
- //// 第二种方式: 通用 zip 文件
- InputStream in = this.getClass().getClassLoader().getResourceAsStream("diagrams/hello.zip");
- ZipInputStream zipInputStream = new ZipInputStream(in);
- deploymentBuilder.addZipInputStream(zipInputStream);
- // 部署流程定义
- Deployment deployment = deploymentBuilder.deploy();
- System.out.println("部署 ID:" + deployment.getId());// 1
- System.out.println("部署名称:" + deployment.getName());// activiti 入门程序
- }
部署流程定义操作的数据表
1,act_re_deployment (部署对象表)
存放流程定义的显示名和部署时间, 每部署一次增加一条记录
2, act_re_procdef(流程定义表)
存放流程定义的属性信息, 部署每个新的流程定义都会在这张表中增加一条记录.
注意: 当流程定义的 key 相同的情况下, 使用的是版本升级
3, act_ge_bytearray(资源文件表)
存储流程定义相关的部署信息. 即流程定义文档的存放地. 每部署一次就会增加两条记录, 一条是关于 bpmn 规则文件的, 一条是图片的 (如果部署时只指定了 bpmn 一个文件, activiti 会在部署时解析 bpmn 文件内容自动生成流程图). 两个文件不是很大, 都是以二进制形
式存储在数据库中.
4,act_ge_property(主键生成策略表)
查看流程定义
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 是一个自动生成的唯一的数字, 由 act_ge_property 表生成的 next.dbid 维护
8. 重复部署一次, deploymentId 的值以一定的形式变化
示例:
- /** 查询流程定义 */
- @Test
- public void processDefinitionQueryTest() {
- RepositoryService service = processEngine.getRepositoryService();
- /**
- * 创建一个流程定义的查询
- * .list(); 返回一个集合 .singleResult();// 返回惟一结果集
- * .count();// 返回结果集数量
- * .listPage(firstResult, maxResults);// 分页查询
- */
- ProcessDefinitionQuery pdq = service.createProcessDefinitionQuery();
- // pdq.deploymentId(deploymentId)// 使用部署对象 ID 查询
- // pdq.processDefinitionId(processDefinitionId)// 使用流程定义 ID 查询
- // pdq.processDefinitionKey(processDefinitionKey)// 使用流程定义的 key 查询
- // pdq.processDefinitionNameLike(processDefinitionNameLike)// 使用流程定义的名称模糊查询
- pdq.orderByProcessDefinitionVersion().asc();// 按照版本的升序排列
- // pdq.orderByProcessDefinitionName().desc()// 按照流程定义的名称降序排列
- List list = pdq.list();
- if (list != null && list.size()> 0) {
- for (ProcessDefinition pd : list) {
- // 流程定义的 key + 版本 + 随机生成数
- System.out.println("流程定义 ID:" + pd.getId());
- // 对应 hello.bpmn 文件中的 name 属性值
- System.out.println("流程定义的名称:" + pd.getName());
- // 对应 hello.bpmn 文件中的 id 属性值
- System.out.println("流程定义的 key:" + pd.getKey());
- // 当流程定义的 key 值相同的相同下, 版本升级, 默认 1
- System.out.println("流程定义的版本:" + pd.getVersion());
- System.out.println("资源名称 bpmn 文件:" + pd.getResourceName());
- System.out.println("资源名称 png 文件:" + pd.getDiagramResourceName());
- System.out.println("部署对象 ID:" + pd.getDeploymentId());
- System.out.println("############################");
- }
- }
- }
删除流程定义
因为删除的是流程定义, 而流程定义的部署是属于仓库服务的, 所以应该先得到 RepositoryService
如果该流程定义下没有正在运行的流程, 则可以用普通删除. 如果是有关联的信息, 用级联删除. 项目开发中使用级联删除的情况比较多, 删除操作一般只开放给超级管理员使用.
示例:
- /** 删除流程定义 */
- @Test
- public void deleteProcessDefinition() {
- // 使用部署 ID, 完成删除
- String deploymentId = "15001";
- // 不带级联的删除 只能删除没有启动的流程, 如果流程启动, 就会抛出异常
- // processEngine.getRepositoryService().deleteDeployment(deploymentId);
- /**
- * 级联删除 不管流程是否启动, 都能可以删除
- */
- processEngine.getRepositoryService().deleteDeployment(deploymentId, true);
- System.out.println("删除成功!");
- }
获取流程定义文档的资源 (查看流程图附件)
查询出流程定义文档. 主要查的是图片, 用于显示流程用.
1,deploymentId 为流程部署 ID
2,resourceName 为 act_ge_bytearray 表中 NAME_ 列的值
3, 使用 repositoryService 的 getDeploymentResourceNames 方法可以获取指定部署下得所有文件的名称
4, 使用 repositoryService 的 getResourceAsStream 方法传入部署 ID 和资源图片名称可以获取部署下指定名称文件的输入流
5, 最后的有关 IO 流的操作, 使用 FileUtils 工具的 copyInputStreamToFile 方法完成流程流程到文件的拷贝, 将资源文件以流的形式输出到指定文件夹下
示例:
- /** 查看流程图 */
- @Test
- public void viewPic() throws IOException {
- RepositoryService service = processEngine.getRepositoryService();
- /** 将生成图片放到文件夹下 */
- String deploymentId = "1";
- // 获取图片资源名称
- List list = service.getDeploymentResourceNames(deploymentId);
- // 定义图片资源的名称
- String resourceName = "";
- if (list != null && list.size()> 0) {
- for (String name : list) {
- if (name.indexOf(".png")>= 0) {
- resourceName = name;
- }
- }
- }
- // 获取图片的输入流
- InputStream in = service.getResourceAsStream(deploymentId, resourceName);
- // 将图片生成到 D 盘的目录下
- File file = new File("D:/" + resourceName);
- // 将输入流的图片写到 D 盘下
- FileUtils.copyInputStreamToFile(in, file);
- }
查询最新版本的流程定义
查询的思路:
1, 使用流程定义的版本升序排列
2, 创建 LinkedHashMap<String, ProcessDefinition>, 对相同 key 的进行覆盖
- /*** 查询最新版本的流程定义 */
- @Test
- public void findLastVersionProcessDefinition() {
- List list = processEngine.getRepositoryService()
- .createProcessDefinitionQuery()//
- .orderByProcessDefinitionVersion().asc()// 使用流程定义的版本升序排列
- .list();
- /**
- * Map
- * map 集合的 key: 流程定义的 key
- * map 集合的 value: 流程定义的对象
- * map 集合的特点: 当 map 集合 key 值相同的情况下, 后一次的值将替换前一次的值
- */
- Map map = new LinkedHashMap();
- if (list != null && list.size()> 0) {
- for (ProcessDefinition pd : list) {
- map.put(pd.getKey(), pd);
- }
- }
- List pdList = new ArrayList(map.values());
- if (pdList != null && pdList.size()> 0) {
- for (ProcessDefinition pd : pdList) {
- System.out.println("流程定义 ID:" + pd.getId());
- System.out.println("流程定义的名称:" + pd.getName());
- System.out.println("流程定义的 key:" + pd.getKey());
- System.out.println("流程定义的版本:" + pd.getVersion());
- System.out.println("资源名称 bpmn 文件:" + pd.getResourceName());
- System.out.println("资源名称 png 文件:" + pd.getDiagramResourceName());
- System.out.println("部署对象 ID:" + pd.getDeploymentId());
- System.out.println("#########################################");
- }
- }
- }
删除 key 相同的所有不同版本的流程定义
思路: 把所有相同 key 的流程定义查出来, 然后遍历删除
- /** 删除流程定义 (删除 key 相同的所有不同版本的流程定义)*/
- @Test
- public void deleteProcessDefinitionByKey() {
- // 流程定义的 key
- String processDefinitionKey = "hello";
- // 先使用流程定义的 key 查询流程定义, 查询出所有的版本
- List 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);
- }
- }
- }
来源: http://www.bubuko.com/infodetail-2562501.html