jbpmconsole流程图采用的是jBPM自定义的标签,我没有研究过如何部署,因为我添加了几次没成功就放弃了,自定义标签的方法也许引用简单,但是部署麻烦,而且不够灵活,所以最好是自己从jBPM的附件表中调出图片,并自己绘制出当前节点和已经过节点.甚至可以在节点上提示审批意见,点击当前节点打开审批窗口等.
先说说jBPM的附件表,默认发布时包含了流程定义和坐标两个xml文件和一个流程截图的jpg图片,流程图显示就是构建一个action,在action中读取jpg图片并输出,然后客户端用一个img指向改action就可以了,当前节点和历史节点可以自行读取并利用div或者vml叠加到图片上.
//读取附件的内容
//获取图片的action
在图片上叠加当前节点的图层需要先获取节点的坐标和大小
可以看到用XPath xPath = new DefaultXPath("//node[@name='" + nodeName + "']");在xml中查找节点,所以jBPM的节点名称不能重名,一个有意思的现象,如果你手动修改流程定义的xml文件,让其中两个节点重名,打开流程图后发现同名其中一个节点连接都跑到另外一个节点上了,这说明jBPM是按节点名称查找xml中的第一个节点,要解决这个问题就只能自定义流程样式,用自己顶一个的属性来显示节点名称,并且自己编写流程设计器和流程图显示.
先说说jBPM的附件表,默认发布时包含了流程定义和坐标两个xml文件和一个流程截图的jpg图片,流程图显示就是构建一个action,在action中读取jpg图片并输出,然后客户端用一个img指向改action就可以了,当前节点和历史节点可以自行读取并利用div或者vml叠加到图片上.
//读取附件的内容
public byte[] getFile(String processName,int version, String fileName) throws Exception{
byte[] bytes = null;
JbpmContext jbpmContext = this.getContext();
try {
GraphSession graphSession = jbpmContext.getGraphSession();
ProcessDefinition pd = getDefinition(processName, version);
if(pd==null) throw new Exception("Process not found!");
FileDefinition fileDef = pd.getFileDefinition();
if(fileDef==null) throw new Exception("Process filedefinition not found!");
bytes = fileDef.getBytes(fileName);
} finally {
closeContext();
}
return bytes;
}
//获取图片的action
public ModelAndView handleRequest(HttpServletRequest request,
HttpServletResponse response) throws Exception {
request.setCharacterEncoding("UTF-8");
String name = request.getParameter("name");
int version = 0;
try {
version = Integer.valueOf(request.getParameter("version"));
} catch(Exception e) { }
response.setContentType("text/xml");
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Charset", "UTF-8"); //default is UTF-8
log.info("get process:" + name+"/"+version);
Service jbpmSvr = new Service();
byte[] bytes = jbpmSvr.getFile(name, version, name+".xml");
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
OutputStream out = response.getOutputStream();
IoUtil.transfer(bais,out);
out.flush();
out.close();
return null;
}
在图片上叠加当前节点的图层需要先获取节点的坐标和大小
public int[] GetTaskinstanceBox(Long piID) throws DocumentException, UnsupportedEncodingException {
JbpmContext jbpmContext=this.getContext();
Session session = getSession(jbpmContext);
try {
List<String> aryToken = getProcessToken(session, piID);
int[] ret = new int[aryToken.size()*4+2];
ProcessInstance pi = jbpmContext.getProcessInstance(piID);
FileDefinition fd = pi.getProcessDefinition().getFileDefinition();
byte[] gpdBytes = fd.getBytes("gpd.xml");
String s = new String(gpdBytes,"UTF-8");
Document document = DocumentHelper.parseText(s);
document.setXMLEncoding("UTF-8");
Element root = document.getRootElement();
ret[0] = Integer.valueOf(root.attribute("width").getValue()).intValue();
ret[1] = Integer.valueOf(root.attribute("height").getValue()).intValue();
for(int i=0;i<aryToken.size();i++){
String nodeName = aryToken.get(i);
XPath xPath = new DefaultXPath("//node[@name='" + nodeName + "']");
Element node = (Element) xPath.selectSingleNode(root);
ret[i*4+2] = Integer.valueOf(node.attribute("x").getValue()).intValue();
ret[i*4+3] = Integer.valueOf(node.attribute("y").getValue()).intValue();
ret[i*4+4] = Integer.valueOf(node.attribute("width").getValue()).intValue();
ret[i*4+5] = Integer.valueOf(node.attribute("height").getValue()).intValue();
}
return ret;
} finally {
jbpmContext.close();
}
}
可以看到用XPath xPath = new DefaultXPath("//node[@name='" + nodeName + "']");在xml中查找节点,所以jBPM的节点名称不能重名,一个有意思的现象,如果你手动修改流程定义的xml文件,让其中两个节点重名,打开流程图后发现同名其中一个节点连接都跑到另外一个节点上了,这说明jBPM是按节点名称查找xml中的第一个节点,要解决这个问题就只能自定义流程样式,用自己顶一个的属性来显示节点名称,并且自己编写流程设计器和流程图显示.