图形化查看执行位置(或者称为:查看活动坐标显示在图中的图形位置)
完成起来只需要特殊两部分:
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);
2、取出当前活动坐标
什么意思呢?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());
- }
- }
有了服务类,然后是我们的servlet:
- 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);
- }
- }
最后是我们的jsp:
- <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.youkuaiyun.com/detail/partner4java/5013331(你也可以按照servlet注释格式的地址访问,debug进代码看执行流程和涉及到的方法)