图形化查看执行位置(或者称为:查看活动坐标显示在图中的图形位置)
完成起来只需要特殊两部分:
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.csdn.net/detail/partner4java/5013331(你也可以按照servlet注释格式的地址访问,debug进代码看执行流程和涉及到的方法)