2017.2.28 activiti实战--第五章--用户与组及部署管理(三)部署流程及资源读取
学习资料:《Activiti实战》
第五章 用户与组及部署管理(三)部署流程及资源读取
内容概览:如何利用API读取已经部署的资源,比如读取流程定义的XML文件,或流程对应的图片文件。
以下示例均基于SpringMVC。
5.3 部署流程及资源读取
5.3.1 读取已部署的processdefinition
假设现已有了一个页面,用于浏览及管理processDefinition。ID是流程定义id,DID是部署ID,名称是流程定义名称,KEY是流程定义KEY。XML和图片是流程定义的资源文件。
这个页面的访问路径是/chapter5-oa-manager/chapter5/process-list。
对应的jsp文件是webapp/WEB-INF/views/chapter5/process-list.jsp。
(1)process-list.jsp文件
完整代码与重点代码如下:
1 <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> 2 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 3 4 <html xmlns="http://www.w3.org/1999/xhtml"> 5 <head> 6 <%@ include file="/common/global.jsp"%> 7 <%@ include file="/common/meta.jsp" %> 8 <%@ include file="/common/include-base-styles.jsp" %> 9 <title>已部署流程定义列表--chapter5</title> 10 </head> 11 <body> 12 <table width="100%" class="table table-bordered table-hover table-condensed"> 13 <thead> 14 <tr> 15 <th>流程定义ID</th> 16 <th>部署ID</th> 17 <th>流程定义名称</th> 18 <th>流程定义KEY</th> 19 <th>版本号</th> 20 <th>XML资源名称</th> 21 <th>图片资源名称</th> 22 <th width="80">操作</th> 23 </tr> 24 </thead> 25 <tbody> 26 <c:forEach items="${processDefinitionList }" var="pd"> 27 <tr> 28 <td>${pd.id }</td> 29 <td>${pd.deploymentId }</td> 30 <td>${pd.name }</td> 31 <td>${pd.key }</td> 32 <td>${pd.version }</td> 33 <td>${pd.resourceName }</td> 34 <td>${pd.diagramResourceName }</td> 35 </c:forEach> 36 </tbody> 37 </table> 38 </body> 39 </html>
34 <tbody> 35 <c:forEach items="${processDefinitionList }" var="pd"> 36 <tr> 37 <td>${pd.id }</td> 38 <td>${pd.deploymentId }</td> 39 <td>${pd.name }</td> 40 <td>${pd.key }</td> 41 <td>${pd.version }</td> 42 <td>${pd.resourceName }</td> 43 <td>${pd.diagramResourceName }</td> 44 </c:forEach> 45 </tbody>
(2)DeploymentController
完整代码和重点代码如下:
1 @Controller 2 @RequestMapping(value = "/chapter5") 3 public class DeploymentController extends AbstractController { 4 5 RepositoryService repositoryService = processEngine.getRepositoryService(); 6 7 /** 8 * 流程定义列表 9 */ 10 @RequestMapping(value = "/process-list") 11 public ModelAndView processList() { 12 13 // 对应WEB-INF/views/chapter5/process-list.jsp 14 ModelAndView mav = new ModelAndView("chapter5/process-list"); 15 List<ProcessDefinition> processDefinitionList = repositoryService.createProcessDefinitionQuery().list(); 16 mav.addObject("processDefinitionList", processDefinitionList); 17 return mav; 18 } 19 }
1 ModelAndView mav = new ModelAndView("chapter5/process-list"); 2 List<ProcessDefinition> processDefinitionList = repositoryService.createProcessDefinitionQuery().list(); 3 mav.addObject("processDefinitionList", processDefinitionList); 4 return mav;
5.3.2 从客户端部署流程
上节中可以获取到已经部署的流程,展示在列表里。这一节,通过web界面或其他客户端来部署processDefinition。这里采用上传文件的方式。
(1)process-list.jsp
添加代码如下:
1 <body> 2 <fieldset id="deployFieldset"> 3 <legend>部署流程资源</legend> 4 <span class="alert alert-info"><b>支持文件格式:</b>zip、bar、bpmn、bpmn20.xml</span> 5 <form action="${ctx }/chapter5/deploy" method="post" enctype="multipart/form-data" style="margin-top:1em;"> 6 <input type="file" name="file" /> 7 <input type="submit" value="Submit" class="btn" /> 8 </form> 9 <hr class="soften" /> 10 </fieldset> 11 ... 12 </body>
(2)DeploymentController
添加方法如下:(类的路径是/chapter5,方法的路径是/deploy)
1 /** 2 * 部署流程资源 3 */ 4 @RequestMapping(value = "/deploy") 5 public String deploy(@RequestParam(value = "file", required = true) MultipartFile file) { 6 // 获取上传的文件名 7 String fileName = file.getOriginalFilename(); 8 9 try { 10 // 得到输入流(字节流)对象 11 InputStream fileInputStream = file.getInputStream(); 12 // 文件的扩展名 13 String extension = FilenameUtils.getExtension(fileName); 14 // zip或者bar类型的文件用ZipInputStream方式部署 15 DeploymentBuilder deployment = repositoryService.createDeployment(); 16 if (extension.equals("zip") || extension.equals("bar")) { 17 ZipInputStream zip = new ZipInputStream(fileInputStream); 18 deployment.addZipInputStream(zip); 19 } else { 20 // 其他类型的文件直接部署 21 deployment.addInputStream(fileName, fileInputStream); 22 } 23 deployment.deploy(); 24 } catch (Exception e) { 25 logger.error("error on deploy process, because of file input stream"); 26 } 27 28 return "redirect:process-list";// 回到列表页 29 }
5.3.3 读取流程定义的XML
现在增加一个功能,为列表中的"XML资源名称"添加一个链接,单击时,可以查看流程定义的XML文件内容。
(1)process-list.jsp
修改列的设置。
1 <!--原来的代码 2 <td>${pd.resourceName }</td> 3 --> 4 5 <!--修改如下--> 6 <td> 7 <a target="_blank" href='${ctx }/chapter5/read-resource?pdid=${pd.id }&resourceName=${pd.resourceName }'>${pd.resourceName } 9 </a> 10 </td>
(2)DeploymentController
添加方法如下:(类的路径是/chapter5,方法的路径是/read-resource)
1 /** 2 * 读取流程资源 3 * 4 * @param processDefinitionId 流程定义ID 5 * @param resourceName 资源名称 6 */ 7 @RequestMapping(value = "/read-resource") 8 public void readResource(@RequestParam("pdid") String processDefinitionId, 10 @RequestParam("resourceName") String resourceName, 11 HttpServletResponse response)throws Exception { 13 ProcessDefinitionQuery pdq = repositoryService.createProcessDefinitionQuery(); 14 ProcessDefinition pd = pdq.processDefinitionId(processDefinitionId).singleResult(); 15 16 // 通过接口读取 17 InputStream resourceAsStream = repositoryService.getResourceAsStream(pd.getDeploymentId(), resourceName); 18 19 // 输出资源内容到相应对象 20 byte[] b = new byte[1024]; 21 int len = -1; 22 while ((len = resourceAsStream.read(b, 0, 1024)) != -1) { 23 response.getOutputStream().write(b, 0, len); 24 } 25 }
(3)运行效果
点击 ,跳转到页面:
localhost:8080/chapter5-oa-manager/chapter5/read-resource?pdid=candidateUserInUserTask:1:4&resourceName=candidateUserInUserTask.bpmn
xml文件的内容被完整显示。
5.3.4 读取流程定义的图片文件
不管是bpmn还是png,对engine来说,都是资源文件。所以这里和前面的读取XML文件,所完成的功能类似。因此,二者在Controller里的方法是共用的。
所以只需修改jsp中的这句话为:注意,图片文件是diagramResource。
1 <td> 2 <a target="_blank" href='${ctx }/chapter5/read-resource?pdid=${pd.id }&resourceName=${pd.diagramResourceName }'>${pd.diagramResourceName } 4 </a> 5 </td>
5.3.5 读取流程定义图片时出现的中文乱码问题
读取XML文件和图片文件的区别:部署一个processDefinition时,bpmn文件是一定存在的,但是png文件可以没有。此时,engine会进行判定,如果没有部署时读取的资源里不包含png文件,它会自动生成同名文件。
因此会造成两个问题:坐标遗失及中文乱码。
5.3.2中读取xml内容时,显然内容中是没有坐标信息的,即engine帮我们自动生成的图片,布局的位置无法与bpmn中一模一样。同时,activiti默认的字体是Arial,在windows下默认自带宋体。所以转换时,会出现乱码。
(1)坐标遗失
解决办法:部署时,bpmn文件和图片文件打包为zip/bar同时部署。不要让activiti为我们在部署的时候才自动生成。(Eclipse插件activiti designer中进行流程绘制时,可以设置为点击保存bpmn的同时立即生成png图片。在这个插件中绘制,查看bpmn文件的xml内容时 ,可以看到坐标信息。)
(2)中文乱码
乱码解决办法1:
修改类org.activiti.engine.impl.bpmn.diagram.ProcessDiagramCanvas的其中一句代码如下:
1 //Font font = new Font("Arial",Font.BOLD,11); 2 Font font = new Font("simsun",Font.BOLD,11);//宋体是simsun
缺点:动了源代码,导致使用activiti的升级版本时,又要做同样修改。
乱码解决办法2:
在processConfiguration的配置中增加这段:
1 <bean id="processEngineConfiguration" class="..."> 2 <!--修改字体--> 3 <property name="activityFontName" value="宋体"> 4 <property name="labelFontName" value="宋体"> 5 </bean>
乱码解决办法3:
部署时,bpmn文件和图片文件打包为zip/bar同时部署。不要让activiti为我们在部署的时候才自动生成。
综上可以看到:部署时,bpmn文件和图片文件打包为zip/bar同时部署,可以同时解决这两个问题。其他一些更细微的问题,比如显示不全,也可以解决。所以,最后的结论就是,将bpmn和png一起打包部署吧。
5.3.6 删除部署
(1)process-list.jsp
添加一列,用来执行删除操作。
1 <td><a target="_blank" href='${ctx }/chapter5/delete-deployment?deploymentId=${pd.deploymentId }'>删除</a></td>
(2)DeploymentController
添加方法如下:(类的路径是/chapter5,方法的路径是/delete-deployment)
1 /** 2 * 删除部署的流程,级联删除流程实例 3 * 4 * @param deploymentId 流程部署ID 5 */ 6 @RequestMapping(value = "/delete-deployment") 7 public String deleteProcessDefinition(@RequestParam("deploymentId") String deploymentId) { 8 repositoryService.deleteDeployment(deploymentId, true);//true表示同时把与流程相关的数据也一并删除 9 return "redirect:process-list"; 10 }
本章小结
1 介绍了用户与组、部署管理两大块。 2 用户与组介绍了API的使用,及一些重要参数。 3 部署管理介绍了资源的种类,四种部署方式,如何读取已部署资源。