图形化查看执行位置(或者称为:查看活动坐标显示在图中的图形位置)
完成起来只需要特殊两部分:
1、发布的时候打包进png图片,显示图形位置时取出(或不打包进发布,能够拼出位置也可)
如:
InputStream in = new FileInputStream( "F:\\workspace\\jbpm\\workspace\\hello_jbpm\\src\\main\\resources\\leave.zip"); ZipInputStream zipInputStream = new ZipInputStream(in); jpdlDeployManager.processEngine.getRepositoryService().createDeployment() .addResourcesFromZipInputStream(zipInputStream).deploy();取出:
// 取出发布id中资源的io流 inputStream = repositoryService.getResourceAsStream(deploymentId, resourceName);
什么意思呢?jbpm4为我们提供一个对象ActivityCoordinates,用于描述某个活动节点相对于图形中的坐标(横坐标、纵坐标、执行任务在图形中的高度和宽度)
/** activity coordinates indicating the graphical position in the diagram. * * @see RepositoryService#getActivityCoordinates(String, String) * @author Tom Baeyens */ public interface ActivityCoordinates { int getX(); int getY(); int getWidth(); int getHeight(); }获取此对象:
/** * 获取活动坐标显示在图中的图形位置 * * @param processInstance * 流程实例 * @return */ public static ActivityCoordinates getActivityCoordinates(ProcessInstance processInstance) { // 两个参数:1个为流程定义id;另一个为流程定义图形中具体活动的名称(或者说当前活动的名称)。 return repositoryService.getActivityCoordinates(processInstance.getProcessDefinitionId(), processInstance .findActiveActivityNames().iterator().next()); }
首先是我们的业务处理类,我们进行了封装,具体查看注释
package com.partner4java.service; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import org.jbpm.api.Configuration; import org.jbpm.api.ExecutionService; import org.jbpm.api.ProcessDefinition; import org.jbpm.api.ProcessEngine; import org.jbpm.api.ProcessInstance; import org.jbpm.api.RepositoryService; import org.jbpm.api.TaskService; import org.jbpm.api.model.ActivityCoordinates; import org.jbpm.api.task.Task; /** * 图片展示执行位置服务类<br/> * 提供了两类方法:获取当前流程定义的图形和获取当前活动坐标。<br/> * 两类方法都分别有两份:一份是根据taskId获取,另一份是根据processInstanceId获取 * * @author partner4java * */ public class PicViewService { public static ProcessEngine processEngine = Configuration.getProcessEngine(); public static RepositoryService repositoryService = processEngine.getRepositoryService(); public static ExecutionService executionService = processEngine.getExecutionService(); public static TaskService taskService = processEngine.getTaskService(); /** 保存已经查询过的流程定义id对应的图片地址 */ private static ConcurrentMap<String, String> picViewNames = new ConcurrentHashMap<String, String>(); /** * 获取图片URL地址<br/> * 打包的png图片名字需与jpdl的name属性名字一致 * * @param taskId * 任务id * @return 如:"jbpm/pic/leave_1.png",相对于web根目录的位置 */ public static String getPicViewByTaskId(String taskId) { // 根据taskId获取任务 Task task = taskService.getTask(taskId); // 根据任务获取执行id String executionId = task.getExecutionId(); return getPicView(executionId); } /** * 获取图片URL地址<br/> * 打包的png图片名字需与jpdl的name属性名字一致 * * @param processInstanceId * 流程实例id * @return 如:"jbpm/pic/leave_1.png",相对于web根目录的位置 */ public static String getPicView(String processInstanceId) { // 先根据流程实例id拿到流程实例 ProcessInstance processInstance = executionService.findProcessInstanceById(processInstanceId); // 然后根据流程实例拿到流程定义id String processDefinitionId = processInstance.getProcessDefinitionId(); String fileName = doGetPivView(processDefinitionId); return fileName; } /** * 获取图片URL地址<br/> * 打包的png图片名字需与jpdl的name属性名字一致 * * @param processDefinitionId * 流程定义id * @return 如:"jbpm/pic/leave_1.png",相对于web根目录的位置 */ private static String doGetPivView(String processDefinitionId) { // 先判断一下有没有取过,如果取过直接返回缓存地址 String cachePicName = picViewNames.get(processDefinitionId); if (cachePicName != null) { return cachePicName; } // 根据流程实例id拿到流程实例 ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery() .processDefinitionId(processDefinitionId).uniqueResult(); // 根据流程实例拿到发布id(和processDefinitionId的区别一般就是没有key和横杠标识) String deploymentId = processDefinition.getDeploymentId(); // 默认和name属性的名字相同 String resourceName = processDefinition.getName() + ".png"; InputStream inputStream = null; FileOutputStream fileOutputStream = null; BufferedOutputStream out = null; String fileName = getFileName(processDefinitionId); try { // 取出发布id中资源的io流 inputStream = repositoryService.getResourceAsStream(deploymentId, resourceName); // 创建一个文件写入(这里我们做了cache),当然你也可以输出到out中response.getOutputStream().write(b, // 0, len); File file = createFile(fileName); fileOutputStream = new FileOutputStream(file); out = new BufferedOutputStream(fileOutputStream); byte[] b = new byte[1024]; int len = -1; while ((len = inputStream.read(b, 0, 1024)) > -1) { out.write(b, 0, len); } } catch (Exception e) { e.printStackTrace(); } finally { try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } finally { try { out.close(); } catch (IOException e) { e.printStackTrace(); } } } fileName = "jbpm/pic/" + processDefinitionId.replace("-", "_") + ".png"; picViewNames.put(processDefinitionId, fileName); return fileName; } /** * 创建文件目录 * * @param fileName * @return * @throws IOException */ private static File createFile(String fileName) throws IOException { File file = new File(fileName); File parentFile = file.getParentFile(); if (parentFile != null && !parentFile.exists()) { parentFile.mkdirs(); } return file; } /** * 获取文件的磁盘路径 * * @param processDefinitionId * @return */ public static String getFileName(String processDefinitionId) { URL url = PicViewService.class.getClassLoader().getResource(""); if (url != null) { String path = url.getPath(); path = path.replace("/WEB-INF/classes", ""); return path + "jbpm/pic/" + processDefinitionId.replace("-", "_") + ".png"; } return null; } /** * 获取活动坐标显示在图中的图形位置 * * @param taskId * 任务id * @return */ public static ActivityCoordinates getActivityCoordinatesByTaskId(String taskId) { // 根据taskId获取任务 Task task = taskService.getTask(taskId); // 根据任务获取执行id String executionId = task.getExecutionId(); return getActivityCoordinates(executionId); } /** * 获取活动坐标显示在图中的图形位置 * * @param processInstanceId * 流程实例id * @return */ public static ActivityCoordinates getActivityCoordinates(String processInstanceId) { ProcessInstance processInstance = executionService.findProcessInstanceById(processInstanceId); return getActivityCoordinates(processInstance); } /** * 获取活动坐标显示在图中的图形位置 * * @param processInstance * 流程实例 * @return */ public static ActivityCoordinates getActivityCoordinates(ProcessInstance processInstance) { // 两个参数:1个为流程定义id;另一个为流程定义图形中具体活动的名称(或者说当前活动的名称)。 return repositoryService.getActivityCoordinates(processInstance.getProcessDefinitionId(), processInstance .findActiveActivityNames().iterator().next()); } }
package com.partner4java.web; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.jbpm.api.model.ActivityCoordinates; import com.partner4java.service.PicViewService; /** * 以图形的形式展示工作流执行的位置<br/> * 如:http://localhost:8080/jbpm_pic/view/pic?taskid=20008或http://localhost:8080/jbpm_pic/view/pic?piid=leave.20001 * @author partner4java * */ public class PicViewServlet extends HttpServlet { private static final long serialVersionUID = -1307016588425325378L; @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String fileName = null; ActivityCoordinates activityCoordinates = null; String processInstanceId = req.getParameter("piid"); // 先根据流程实例id取 if (processInstanceId != null && !"".equals(processInstanceId)) { fileName = PicViewService.getPicView(processInstanceId); activityCoordinates = PicViewService.getActivityCoordinates(processInstanceId); } // 再根据任务id else { String taskId = req.getParameter("taskid"); if (taskId != null && !"".equals(taskId)) { fileName = PicViewService.getPicViewByTaskId(taskId); activityCoordinates = PicViewService.getActivityCoordinatesByTaskId(taskId); } } req.setAttribute("fileName", fileName); req.setAttribute("activityCoordinates", activityCoordinates); req.getRequestDispatcher("/WEB-INF/view.jsp").forward(req, resp); } }
<body> <img src="${fileName }" style="position:absolute;left:0px;top:0px;"> <div style="position:absolute;border:1px solid red;left:${activityCoordinates.x}px;top:${activityCoordinates.y}px;width:${activityCoordinates.width}px;height:${activityCoordinates.height}px;"></div> </body>效果如图:(红框标出了执行位置)
代码下载地址:http://download.csdn.net/detail/partner4java/5013331(你也可以按照servlet注释格式的地址访问,debug进代码看执行流程和涉及到的方法)