JBPM学习(四)--一个实例和查看流程进度图片(涉及中文乱码)

来源:互联网 发布:java 打印堆栈信息 编辑:程序博客网 时间:2024/05/22 08:07

次篇接上篇 JBPM学习(三)--引擎与5个服务

http://blog.csdn.net/lushuaiyin/article/details/8607156


这次主要学习任务还是学习api的使用,只有对常用api熟悉了,做出个完整的小例子,才算是入门。

在这个实例中,我比较关心怎么查看流程的进度。因为,你要调试的话,不知道流程走到哪一步,感觉自己就像个瞎子。

而在实现这个查看流程进度图片功能前,还要先实现整个实例的代码。所以任务还是很多的。


开始前,还是需要对流程的发布写一个管理,因为要发布新的流程。

接上篇,我已经发布一个流程,xml文件是mysecond.jpdl.xml,如下;



这个做的不是很好,因为上篇主要联系流程的发布,删除,所以和内容没什么关系。

这次,我新写了一个流程,afterwork.jpdl.xml


这个稍显复杂,作为本例的实验流程,代码如下:

<?xml version="1.0" encoding="UTF-8"?><process name="afterwork" xmlns="http://jbpm.org/4.4/jpdl">   <start g="35,194,48,48" name="start1">      <transition g="-38,-22" name="下班后" to="exclusive1"/>   </start>   <decision g="182,196,48,48" name="exclusive1">      <handler class="org.jbpm.action.AfterWorkDecisionHandler"/>       <transition g="-45,-13" name="想玩游戏" to="能否玩游戏"/>      <transition g="-36,-7" name="有学习任务" to="学习"/>   </decision>   <task g="161,66,92,52" name="能否玩游戏" assignee="#{wife}"  form="isAllowedPlayGame.action" >      <transition g="-57,-22" name="去玩游戏" to="玩游戏"/>      <transition g="-45,-22" name="去学习" to="学习" />   </task>   <state g="479,66,92,52" name="玩游戏">      <transition g="-50,-22" name="玩累了" to="睡觉"/>   </state>   <state g="335,194,92,52" name="学习">      <transition g="-30,-24" name="学了一会儿" to="exclusive2"/>   </state>   <decision expr="#{tired=='是'? '该睡觉了' : '玩会儿游戏'}" g="504,195,48,48" name="exclusive2">      <transition g="-57,-22" name="玩会儿游戏" to="玩游戏"/>      <transition g="-50,-22" name="该睡觉了" to="睡觉"/>   </decision>   <end g="743,149,48,48" name="睡觉"/></process>

写把流程发布的代码贴出来吧,这个内容和上篇差不多,不是重点。


AfterWorkAction

package org.jbpm.action;import java.io.BufferedOutputStream;import java.io.File;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.util.HashMap;import java.util.List;import java.util.Map;import java.util.Set;import org.base.MyBaseAction;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.model.ActivityCoordinates;public class AfterWorkAction  extends MyBaseAction {private static final long serialVersionUID = 1L;public String execute() throws Exception{return SUCCESS;}//删除流程public String tearDown() throws Exception {RepositoryService repositoryService=getProcessEngine().getRepositoryService();String deploymentId="";if(this.getHttpServletRequest().getParameter("deploymentId")!=null){deploymentId=(String)this.getHttpServletRequest().getParameter("deploymentId");if(!deploymentId.trim().equals("")){repositoryService.deleteDeploymentCascade(deploymentId);    System.out.println("删除流程,ID:"+deploymentId);}else{System.out.println("流程,ID为空,删除失败");}}else{System.out.println("流程,ID为空,删除失败");}        return NONE;}//发布流程mysecond.jpdl.xml  (after work1111)public String setUp() throws Exception {RepositoryService repositoryService=getProcessEngine().getRepositoryService();    deploymentId = repositoryService.createDeployment()        .addResourceFromClasspath("org/jbpm/config/mysecond.jpdl.xml")//流程定义        .addResourceFromClasspath("org/jbpm/config/mysecond.png")//流程定义图        .deploy();System.out.println("成功发布流程,ID:"+deploymentId);this.getHttpServletResponse().getWriter().println("成功发布流程,ID:"+deploymentId);    return NONE;}//发布流程afterwork.jpdl.xml  (after work)public String setUpAfterwork() throws Exception {RepositoryService repositoryService=getProcessEngine().getRepositoryService();    deploymentId = repositoryService.createDeployment()        .addResourceFromClasspath("org/jbpm/config/afterwork.jpdl.xml")//流程定义        .addResourceFromClasspath("org/jbpm/config/afterwork.png")//流程定义图        .deploy();System.out.println("成功发布流程,ID:"+deploymentId);this.getHttpServletResponse().getWriter().println("成功发布流程,ID:"+deploymentId);    return NONE;}//查询所有流程public String showAll() throws Exception {RepositoryService repositoryService=getProcessEngine().getRepositoryService();System.out.println("查询所有流程");List<ProcessDefinition> processDefinitions = repositoryService.createProcessDefinitionQuery().list();    if(processDefinitions!=null){    this.setValueToRequest("processDefinitions", processDefinitions);    }    return SUCCESS;}//启动流程(这里只是样例)public String startProcess() throws Exception {RepositoryService repositoryService=getProcessEngine().getRepositoryService();ExecutionService executionService=getProcessEngine().getExecutionService();String proId="";if(this.getHttpServletRequest().getParameter("proId")!=null){proId=(String)this.getHttpServletRequest().getParameter("proId");Map map = new HashMap();//因为我发布了2个流程afterwork和mysecond,这里为这两个流程启动实例if(proId.startsWith("afterwork")){map.put("reason", "时间充足,工作完成");map.put("wife", "mywife");}else{//mysecondmap.put("reason", "想玩游戏了");}executionService.startProcessInstanceById(proId, map);System.out.println("流程已启动。。。");}this.getHttpServletResponse().getWriter().println("流程已启动。。。");    return NONE;}//查看流程定义图片public String showImage() throws Exception {String picUrl="";RepositoryService repositoryService=getProcessEngine().getRepositoryService();String proId="";if(this.getHttpServletRequest().getParameter("proId")!=null){proId=(String)this.getHttpServletRequest().getParameter("proId");if(!proId.trim().equals("")){System.out.println("流程ID:"+proId);List<ProcessDefinition> processDefinitions = repositoryService.createProcessDefinitionQuery().processDefinitionId(proId).list();    if(processDefinitions!=null){    if(processDefinitions.size()==1){    ProcessDefinition pd=processDefinitions.get(0);    String theDeploymentId=pd.getDeploymentId();        InputStream is=repositoryService.getResourceAsStream(theDeploymentId, pd.getImageResourceName());    System.out.println("pd.getImageResourceName()####"+pd.getImageResourceName());//例如org/jbpm/config/myprocess.png    picUrl=this.copyImageToWebapps(is, pd.getImageResourceName());    this.setValueToRequest("processDefinitions", processDefinitions);    System.out.println("流程图片路径:"+picUrl);    this.getHttpServletResponse().getWriter().println(picUrl);        }    }}else{System.out.println("流程,ID为空");}}else{System.out.println("流程,ID为null");}    return NONE;}public ProcessEngine processEngine;public ProcessEngine getProcessEngine() {return processEngine;}public void setProcessEngine(ProcessEngine processEngine) {this.processEngine = processEngine;}public String deploymentId;public String getDeploymentId() {return deploymentId;}public void setDeploymentId(String deploymentId) {this.deploymentId = deploymentId;}/** * 把流程图片拷贝到webapp下,返回一个url,供页面显示(这个可以写成工具类,这里只是为了方便写在了这里) * @param is * @param imageResourceName * @return * @author lushuaiyin */public String copyImageToWebapps(InputStream is,String imageResourceName){String resUrl="";if(is==null||imageResourceName==null||imageResourceName.trim().equals("")){System.out.println("is or imageResourceName is null!");}else{//imageResourceName: org\jbpm\config\myprocess.png String rightImageResourceName=imageResourceName.substring(imageResourceName.lastIndexOf("/")+1);System.out.println("rightImageResourceName###"+rightImageResourceName);String phyBasePath=AfterWorkAction.class.getClassLoader().getResource("").getPath();File phyBaseFile=new File(phyBasePath);String phyImagePath=phyBaseFile.getParentFile().getParentFile().getPath()+"\\jsp\\jbpmtest\\images\\"+rightImageResourceName;File TargetImage=new File(phyImagePath); FileOutputStream fos=null;BufferedOutputStream bos=null;try {fos = new FileOutputStream(TargetImage);bos=new BufferedOutputStream(fos);byte[] b=new byte[1024];int len;while((len=is.read(b))!=-1){bos.write(b, 0, len);}resUrl="jsp/jbpmtest/images/"+rightImageResourceName;}catch (FileNotFoundException e) {e.printStackTrace();}catch (IOException e) {e.printStackTrace();}finally{try {if(bos!=null){bos.flush();bos.close();}if(fos!=null){fos.close();}if(is!=null){is.close();}} catch (IOException e) {e.printStackTrace();}}}return resUrl;}}

struts文件struts_jbpm_afterwork.xml

<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE struts PUBLIC"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN""http://struts.apache.org/dtds/struts-2.0.dtd"><struts><package name="afterwork" extends="base-struts-default" namespace="/afterwork">    <action name="tearDown" class="org.jbpm.action.AfterWorkAction" method="tearDown"></action><action name="setUp" class="org.jbpm.action.AfterWorkAction" method="setUp"></action><action name="setUpAfterwork" class="org.jbpm.action.AfterWorkAction" method="setUpAfterwork"></action><action name="showAll" class="org.jbpm.action.AfterWorkAction" method="showAll">   <result name="success">/jsp/jbpmtest/listAfterWork.jsp</result></action><action name="startProcess" class="org.jbpm.action.AfterWorkAction" method="startProcess"></action><action name="showImage" class="org.jbpm.action.AfterWorkAction" method="showImage"></action></package></struts>

涉及到的工具类JbpmUtil

package org.jbpm.util;import java.io.File;import java.io.InputStream;import java.util.Random;import org.apache.commons.lang.math.RandomUtils;public class JbpmUtil {public static String getProcessImageUrl(InputStream is){String url="";String baseUrl=JbpmUtil.class.getResource("/").getPath();System.out.println("baseUrl:"+baseUrl);//  /D:/ChinaDevelopmentBankJBPM/workSpace/frame/webapp/WEB-INF/classes/File classFile=new File(baseUrl);String webBaseUrl=classFile.getParentFile().getParentFile().getPath();System.out.println("webBaseUrl:"+webBaseUrl);//  D:\ChinaDevelopmentBankJBPM\workSpace\frame\webappString imageBaseUrl=webBaseUrl+"\\jsp\\jbpmtest\\images";System.out.println("imageBaseUrl:"+imageBaseUrl);//  D:\ChinaDevelopmentBankJBPM\workSpace\frame\webapp\jsp\jbpmtest\imagesif(is==null){System.out.println("InputStream为空");}else{String imgpath=imageBaseUrl+"\\"+JbpmUtil.getRandomNumber()+".jpg";File img=new File(imgpath);}return url;}public static String getRandomNumber(){String res="";Double dou=Math.random();String stra=String.valueOf(dou);res=stra.substring(stra.indexOf(".")+1);return res;}public static void main(String[] ads){JbpmUtil.getProcessImageUrl(null);System.out.println("随机数:"+JbpmUtil.getRandomNumber());}}

jsp页面:


listAfterWork.jsp

<%@ page contentType="text/html; charset=UTF-8"%><%@page import="java.util.*"%><%@page import="org.jbpm.api.ProcessDefinition"%><%@page import="java.lang.Math"%><% String path = request.getContextPath();%><% List list=null;if(request.getAttribute("processDefinitions")!=null){list=(List)request.getAttribute("processDefinitions");}%><html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><title></title><script src="<%=path%>/script/jquery-1.7.1.min.js" type="text/javascript"></script></head><body style="overflow: scroll; overflow: auto;"><input type="hidden" name="path" id="path" value='<%=path%>' ></input>    <table width="500px"  border="1" align="center">        <tr> <td align="center"><a href="<%=path%>/index.action" >返回</a> </td></tr></table>      <table width="500px"  border="1" align="center">        <tr> <td align="center">流程名字:<input type="text"  id="proname" value='' ></input></td></tr><tr> <td align="center"><h1><a href="javascript:void(0)" onclick="query()">查询</a></h1></td></tr><tr> <td align="center"><input type="button" onclick="setUpProcess()"  value='发布流程:mysecond' ></input></td></tr><tr> <td align="center"><input type="button" onclick="setUpProcessAfterwork()"  value='发布流程:afterwork' ></input></td></tr></table> <table width="500px"  border="1" align="center">        <tr> <th align="center">流程id</th><th align="center">流程名字</th><th align="center">key</th> <th align="center">version</th><th align="center">操作</th><th align="center">操作</th> <th align="center">操作</th></tr><% if(list!=null){for(int i=0;i<list.size();i++){ProcessDefinition process=(ProcessDefinition)list.get(i);if(process!=null){String proid="";String proname="";String key="";int version;String deploymentId="";if(process.getId()!=null){proid=process.getId();}if(process.getName()!=null){proname=process.getName();}if(process.getKey()!=null){key=process.getKey();}version=process.getVersion();if(process.getDeploymentId()!=null){deploymentId=process.getDeploymentId();}%><tr> <td><%=proid%></td> <td><%=proname%></td> <td><%=key%></td> <td><%=version%></td> <td><input type="button" onclick="delprocess('<%=deploymentId%>')"  value='删除流程' ></input></td> <td><input type="button" onclick="showImage('<%=proid%>')"  value='查看图片' ></input></td> <td><input type="button" onclick="startProcess('<%=proid%>')"  value='启动流程实例' ></input></td></tr><%}}}%></table><table width="410px"  border="1" align="center">        <tr>          <td style="width:100%;height:100%;align:center">             <img id="processImageUrl"  alt="流程定义图片" src="<%=path%>/jsp/jbpmtest/images/suolong.jpg?randomStr=<%=Math.random()%>'" style="width:100%;align:center" />          </td></tr></table></body></html> <script type="text/javascript">function query(){var proname=document.getElementById("proname").value;var urlpath="<%=path%>/afterwork/showAll.action?proname="+proname+"&randomStr="+Math.random();window.location.href=urlpath;}function delprocess(id){var urlpath="<%=path%>"+"/afterwork/tearDown.action";$.ajax({   type:"POST",   url:urlpath,   data: "deploymentId="+id+"&randomStr="+Math.random(),   success: function(msg){   alert("成功删除!");     window.location.reload();   }});}function setUpProcess(){var urlpath="<%=path%>"+"/afterwork/setUp.action";$.ajax({   type:"POST",   url:urlpath,   data: "randomStr="+Math.random(),   success: function(msg){   alert(msg);     window.location.reload();   }});}function setUpProcessAfterwork(){var urlpath="<%=path%>"+"/afterwork/setUpAfterwork.action";$.ajax({   type:"POST",   url:urlpath,   data: "randomStr="+Math.random(),   success: function(msg){   alert(msg);     window.location.reload();   }});}function startProcess(id){var urlpath="<%=path%>/afterwork/startProcess.action?proId="+id+"&randomStr="+Math.random();$.ajax({   type:"POST",   url:urlpath,   success: function(msg){   alert(msg);   }});}function showImage(proId){var urlpath="<%=path%>"+"/afterwork/showImage.action";$.ajax({   type:"POST",   url:urlpath,   data: "proId="+proId+"&randomStr="+Math.random(),   success: function(msg){   var url="<%=path%>"+"/"+msg+"?randomStr="+Math.random();   document.getElementById("processImageUrl").src=url;   }});}</script>

流程中控制类 AfterWorkDecisionHandler

package org.jbpm.action;import org.jbpm.api.jpdl.DecisionHandler;import org.jbpm.api.model.OpenExecution;public class AfterWorkDecisionHandler implements DecisionHandler{public String decide(OpenExecution oe) {// TODO Auto-generated method stubString reason = (String)oe.getVariable("reason");    if(reason==null) {      return "有学习任务";      }else if(reason.trim().equals("时间充足,工作完成")){    return "想玩游戏";    }else if(reason.trim().equals("时间充足,工作未完成")){    return "有学习任务";    }else{    return "有学习任务";    }}}


------------------------------------------------------------------------------------------------

下面是流程的一个实例,处理一个任务。包括任务的查询。

TaskWorkAction

package org.jbpm.action;import java.io.BufferedOutputStream;import java.io.File;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.util.HashMap;import java.util.List;import java.util.Map;import java.util.Set;import org.base.MyBaseAction;import org.jbpm.api.ExecutionService;import org.jbpm.api.HistoryService;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.history.HistoryTask;import org.jbpm.api.model.ActivityCoordinates;import org.jbpm.api.task.Task;public class TaskWorkAction  extends MyBaseAction {private static final long serialVersionUID = 1L;public String execute() throws Exception{return SUCCESS;}//查看某用户的任务列表public String showTaskList() throws Exception {RepositoryService repositoryService=getProcessEngine().getRepositoryService();TaskService taskService=getProcessEngine().getTaskService();HistoryService historyService=getProcessEngine().getHistoryService();String personname="";List<Task> taskList=null;List<HistoryTask> myHistoryTaskList=null;if(this.getHttpServletRequest().getParameter("personname")!=null){personname=(String)this.getHttpServletRequest().getParameter("personname");taskList=taskService.findPersonalTasks(personname);if(taskList!=null){    this.setValueToRequest("taskList", taskList);    System.out.println(personname+"的待办任务,"+taskList.size()+"个");    }myHistoryTaskList=historyService.createHistoryTaskQuery().assignee(personname).list();if(myHistoryTaskList!=null){    this.setValueToRequest("myHistoryTaskList", myHistoryTaskList);    System.out.println(personname+"的历史任务,"+myHistoryTaskList.size()+"个");    }}    return SUCCESS;}//查看任务详细public String showDetail() throws Exception {RepositoryService repositoryService=getProcessEngine().getRepositoryService();TaskService taskService=getProcessEngine().getTaskService();String taskid="";Task task=null;if(this.getHttpServletRequest().getParameter("taskid")!=null){taskid=(String)this.getHttpServletRequest().getParameter("taskid");task=taskService.getTask(taskid);if(task!=null){    this.setValueToRequest("task", task);    System.out.println("查看任务详细id:"+task.getId());    }}    return SUCCESS;}//task  能否玩游戏 决策public String isAllowedPlayGame() throws Exception {RepositoryService repositoryService=getProcessEngine().getRepositoryService();TaskService taskService=getProcessEngine().getTaskService();String taskid="";String isapproved="";if(this.getHttpServletRequest().getParameter("taskid")!=null){taskid=(String)this.getHttpServletRequest().getParameter("taskid");if(this.getHttpServletRequest().getParameter("isapproved")!=null){isapproved=(String)this.getHttpServletRequest().getParameter("isapproved");isapproved=(isapproved==null||isapproved.trim().equals(""))?"no":isapproved;}Task task=taskService.getTask(taskid);Map nextMap=new HashMap();//提交到下个节点的信息,供下个节点判断使用if(isapproved.equals("yes")){nextMap.put("hasApproved", "yes");nextMap.put("approvedByWho", "mywife");taskService.completeTask(taskid, "去玩游戏", nextMap);}else{nextMap.put("hasApproved", "no");nextMap.put("notApprovedByWho", "mywife");nextMap.put("notApprovedReason", "toolate");taskService.completeTask(taskid, "去学习", nextMap);}}    return SUCCESS;}//查看流程进度,图片显示public String showTaskImage() throws Exception {String picUrl="";RepositoryService repositoryService=getProcessEngine().getRepositoryService();ExecutionService executionService=getProcessEngine().getExecutionService();String executionId="";if(this.getHttpServletRequest().getParameter("executionId")!=null){executionId=(String)this.getHttpServletRequest().getParameter("executionId");if(!executionId.trim().equals("")){System.out.println("流程executionId:"+executionId);//String processDefinitionId=executionService.findExecutionById(executionId).getProcessDefinitionId();List<ProcessDefinition> processDefinitions = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).list();    if(processDefinitions!=null){    if(processDefinitions.size()==1){    ProcessDefinition pd=processDefinitions.get(0);    String theDeploymentId=pd.getDeploymentId();        ProcessInstance processInstance=executionService.findProcessInstanceById(executionId);        InputStream is=repositoryService.getResourceAsStream(theDeploymentId, pd.getImageResourceName());    System.out.println("pd.getImageResourceName()####"+pd.getImageResourceName());//例如org/jbpm/config/myprocess.png    picUrl=this.copyImageToWebapps(is, pd.getImageResourceName());//    this.setValueToRequest("processDefinitions", processDefinitions);    System.out.println("流程定义图片路径:"+picUrl);    this.getHttpServletRequest().setAttribute("picUrl", picUrl);        if(processInstance!=null){    Set<String> activityName=processInstance.findActiveActivityNames();    ActivityCoordinates ac=repositoryService.getActivityCoordinates(processInstance.getProcessDefinitionId(), activityName.iterator().next());    this.getHttpServletRequest().setAttribute("ac", ac);    System.out.println("流程图片位置信息已查询到");    }        }    }    }else{System.out.println("流程,ID为空");}}else{System.out.println("流程,ID为null");}this.getHttpServletResponse().getWriter().println(picUrl);    return SUCCESS;}//public String showTaskImagessssss() throws Exception {//String picUrl="";//RepositoryService repositoryService=getProcessEngine().getRepositoryService();//ExecutionService executionService=getProcessEngine().getExecutionService();////String proId="";//String order="";//if(this.getHttpServletRequest().getParameter("proId")!=null){//proId=(String)this.getHttpServletRequest().getParameter("proId");//if(this.getHttpServletRequest().getParameter("order")!=null){//order=(String)this.getHttpServletRequest().getParameter("order");//}//if(!proId.trim().equals("")){//System.out.println("流程ID:"+proId);//////在这里对流程进行一个识别,如果是我们刚才定义的mysecond流程,就继续////在xml文件中<process name="mysecond" ,这个name属性就是流程的id前半部分,后半部分会加上数字。例如mysecond-1//if(proId.startsWith("mysecond")){//System.out.println("继续流程:"+proId);////List<ProcessDefinition> processDefinitions = repositoryService//.createProcessDefinitionQuery()//.processDefinitionId(proId)//.list();//    if(processDefinitions!=null){//    if(processDefinitions.size()==1){//    ProcessDefinition pd=processDefinitions.get(0);//    String theDeploymentId=pd.getDeploymentId();//    //    InputStream is=repositoryService.getResourceAsStream(theDeploymentId, pd.getImageResourceName());//    System.out.println("pd.getImageResourceName()####"+pd.getImageResourceName());//例如org/jbpm/config/myprocess.png//    picUrl=this.copyImageToWebapps(is, pd.getImageResourceName());//    this.setValueToRequest("processDefinitions", processDefinitions);//    System.out.println("流程图片路径:"+picUrl);//    this.getHttpServletRequest().setAttribute("picUrl", picUrl);//    //    Map map = new HashMap();//    if(order.trim().equals("play")){//    map.put("reason", "想玩游戏");//    }else{//    map.put("reason", "有学习任务");//    }//    //    ProcessInstance processInstance=executionService.startProcessInstanceById(proId, map);//    //    if(processInstance!=null){//    Set<String> activityName=processInstance.findActiveActivityNames();//    ActivityCoordinates ac=repositoryService.getActivityCoordinates(processInstance.getProcessDefinitionId(), activityName.iterator().next());//    this.getHttpServletRequest().setAttribute("ac", ac);//    System.out.println("流程图片位置信息已查询到");//    }//    //    }//    }//}//}else{//System.out.println("流程,ID为空");//}//}else{//System.out.println("流程,ID为null");//}////this.getHttpServletResponse().getWriter().println("执行完毕!");//    return SUCCESS;//}public ProcessEngine processEngine;public ProcessEngine getProcessEngine() {return processEngine;}public void setProcessEngine(ProcessEngine processEngine) {this.processEngine = processEngine;}/** * 把流程图片拷贝到webapp下,返回一个url,供页面显示(这个可以写成工具类,这里只是为了方便写在了这里) * @param is * @param imageResourceName * @return * @author lushuaiyin */public String copyImageToWebapps(InputStream is,String imageResourceName){String resUrl="";if(is==null||imageResourceName==null||imageResourceName.trim().equals("")){System.out.println("is or imageResourceName is null!");}else{//imageResourceName: org\jbpm\config\myprocess.png String rightImageResourceName=imageResourceName.substring(imageResourceName.lastIndexOf("/")+1);System.out.println("rightImageResourceName###"+rightImageResourceName);String phyBasePath=TaskWorkAction.class.getClassLoader().getResource("").getPath();File phyBaseFile=new File(phyBasePath);String phyImagePath=phyBaseFile.getParentFile().getParentFile().getPath()+"\\jsp\\jbpmtest\\images\\"+rightImageResourceName;File TargetImage=new File(phyImagePath); FileOutputStream fos=null;BufferedOutputStream bos=null;try {fos = new FileOutputStream(TargetImage);bos=new BufferedOutputStream(fos);byte[] b=new byte[1024];int len;while((len=is.read(b))!=-1){bos.write(b, 0, len);}resUrl="jsp/jbpmtest/images/"+rightImageResourceName;}catch (FileNotFoundException e) {e.printStackTrace();}catch (IOException e) {e.printStackTrace();}finally{try {if(bos!=null){bos.flush();bos.close();}if(fos!=null){fos.close();}if(is!=null){is.close();}} catch (IOException e) {e.printStackTrace();}}}return resUrl;}}


struts跳转struts_jbpm_task.xml

<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE struts PUBLIC"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN""http://struts.apache.org/dtds/struts-2.0.dtd"><struts><package name="task" extends="base-struts-default" namespace="/task"><action name="showTaskList" class="org.jbpm.action.TaskWorkAction" method="showTaskList">   <result name="success">/jsp/jbpmtest/taskList.jsp</result></action><action name="showDetail" class="org.jbpm.action.TaskWorkAction" method="showDetail">    <result name="success">/jsp/jbpmtest/taskdetail.jsp</result></action><action name="isAllowedPlayGame" class="org.jbpm.action.TaskWorkAction" method="isAllowedPlayGame"></action><action name="showTaskImage" class="org.jbpm.action.TaskWorkAction" method="showTaskImage">    <result name="success">/jsp/jbpmtest/image.jsp</result></action></package></struts>

jsp页面:


taskList.jsp

<%@ page contentType="text/html; charset=UTF-8"%><%@page import="java.util.*"%><%@page import="java.text.*"%><%@page import="org.jbpm.api.*"%><%@page import="org.jbpm.api.task.*"%><%@page import="org.jbpm.api.history.*"%><%@page import="java.lang.Math"%><% String path = request.getContextPath();%><% List taskList=null;List<HistoryTask> myHistoryTaskList=null;if(request.getAttribute("taskList")!=null){taskList=(List)request.getAttribute("taskList");}if(request.getAttribute("myHistoryTaskList")!=null){myHistoryTaskList=(List)request.getAttribute("myHistoryTaskList");}%><html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><title></title><script src="<%=path%>/script/jquery-1.7.1.min.js" type="text/javascript"></script></head><body style="overflow: scroll; overflow: auto;"><input type="hidden" name="path" id="path" value='<%=path%>' ></input>     <table width="700px"  border="1" align="center">        <tr> <td align="center"><a href="<%=path%>/index.action" >返回</a> </td></tr></table>      <table width="700px"  border="1" align="center">        <tr> <td align="center">请输入要查询待办任务的人的账号:<input type="text"  id="personname" value='mywife' ></input></td></tr><tr> <td align="center"><h1><a href="javascript:void(0)" onclick="querytask()">查询</a></h1></td></tr></table> <table width="700px"  border="1" align="center">        <tr> <th align="center">任务id</th><th align="center">任务名字</th><th align="center">任务活动节点名</th> <th align="center">操作</th><th align="center">操作</th></tr><% if(taskList!=null){for(int i=0;i<taskList.size();i++){Task task=(Task)taskList.get(i);if(task!=null){String id="",name="",formResourceName="",executionId="",activityName="";if(task.getId()!=null){id=task.getId();}if(task.getName()!=null){name=task.getName();}if(task.getActivityName()!=null){activityName=task.getActivityName();}if(task.getFormResourceName()!=null){formResourceName=task.getFormResourceName();}if(task.getExecutionId()!=null){executionId=task.getExecutionId();}%><tr> <td><%=id%></td> <td><%=name%></td> <td><%=activityName%></td> <td><input type="button" onclick="showDetail('<%=id%>','<%=formResourceName%>')"  value='查看详细信息' ></input></td> <td><input type="button" onclick="showTaskImage('<%=executionId%>')"  value='查看流程进度图片' ></input></td> </tr><%}}}%></table><table width="700px"  border="1" align="center">   <tr> <th align="center" colspan="8">历史任务</th></tr>        <tr> <th align="center">任务id</th><th align="center">任务executionId</th><th align="center">代理人</th><th align="center">任务状态</th> <th align="center">开始时间</th><th align="center">结束时间</th><th align="center">任务结果</th><th align="center">操作</th></tr><% if(myHistoryTaskList!=null){for(int i=0;i<myHistoryTaskList.size();i++){HistoryTask historyTask=(HistoryTask)myHistoryTaskList.get(i);if(historyTask!=null){String id="",executionId="",assignee="",state="",createTime="";String endTime="",outcome="";if(historyTask.getId()!=null){id=historyTask.getId();}if(historyTask.getExecutionId()!=null){executionId=historyTask.getExecutionId();}if(historyTask.getAssignee()!=null){assignee=historyTask.getAssignee();}if(historyTask.getState()!=null){state=historyTask.getState();}if(historyTask.getCreateTime()!=null){Date date=historyTask.getCreateTime();SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");createTime=sdf.format(date);}if(historyTask.getEndTime()!=null){Date date=historyTask.getEndTime();SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");endTime=sdf.format(date);}if(historyTask.getOutcome()!=null){outcome=historyTask.getOutcome();}%><tr> <td><%=id%></td> <td><%=executionId%></td> <td><%=assignee%></td> <td><%=state%></td> <td><%=createTime%></td> <td><%=endTime%></td> <td><%=outcome%></td> <td><input type="button" onclick="showTaskImage('<%=executionId%>')"  value='查看流程进度图片' ></input></td> </tr><%}}}%></table></body></html> <script type="text/javascript">//查询待办任务列表和历史任务列表function querytask(){var personname=document.getElementById("personname").value;var urlpath="<%=path%>/task/showTaskList.action?personname="+personname+"&randomStr="+Math.random();window.location.href=urlpath;}//查看任务详细信息function showDetail(id){var urlpath="<%=path%>"+"/task/showDetail.action?taskid="+id+"&randomStr="+Math.random();window.location.href=urlpath;}//查看任务进度图片(实际流程进度)function showTaskImage(executionId){var urlpath="<%=path%>"+"/task/showTaskImage.action?executionId="+executionId+"&randomStr="+Math.random();window.open (urlpath, '流程任务图片', 'height=400, width=500, top=0, left=0, toolbar=yes, menubar=yes, scrollbars=auto, resizable=yes,location=yes, status=yes'); }</script>


taskdetail.jsp

<%@ page contentType="text/html; charset=UTF-8"%><%@page import="java.util.*"%><%@page import="java.text.*"%><%@page import="org.jbpm.api.*"%><%@page import="org.jbpm.api.task.Task"%><%@page import="java.lang.Math"%><% String path = request.getContextPath();%><% Task task=null;if(request.getAttribute("task")!=null){task=(Task)request.getAttribute("task");}%><html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><title></title><script src="<%=path%>/script/jquery-1.7.1.min.js" type="text/javascript"></script></head><body style="overflow: scroll; overflow: auto;"><input type="hidden" name="path" id="path" value='<%=path%>' ></input>    <table width="700px"  border="1" align="center">        <tr> <td align="center"><a href="<%=path%>/index.action" >返回</a> </td></tr></table>       <table width="700px"  border="1" align="center">        <tr> <th align="center">任务id</th><th align="center">任务名字</th><th align="center">创建时间</th> <th align="center">活动名称</th><th align="center">代理人</th><th align="center">描述</th> <th align="center">定义的提交url</th><th align="center">操作</th><th align="center">操作</th></tr><%    if(task!=null){String id="";String name="";String createTime="",activityName="",assignee="",description="",formResourceName="";if(task.getId()!=null){id=task.getId();}if(task.getName()!=null){name=task.getName();}if(task.getCreateTime()!=null){Date date=task.getCreateTime();SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");createTime=sdf.format(date);}if(task.getActivityName()!=null){activityName=task.getActivityName();}if(task.getAssignee()!=null){assignee=task.getAssignee();}if(task.getDescription()!=null){description=task.getDescription();}if(task.getFormResourceName()!=null){formResourceName=task.getFormResourceName();}%><tr> <td><%=id%></td> <td><%=name%></td> <td><%=createTime%></td> <td><%=activityName%></td> <td><%=assignee%></td> <td><%=description%></td> <td><%=formResourceName%></td>  <td><a href="javascript:void(0)" onclick="approve('<%=id%>')" >同意玩会游戏</a></td> <td><a href="javascript:void(0)" onclick="notApprove('<%=id%>')" >必须先完成学习任务</a></td></tr><%}%></table></body></html> <script type="text/javascript">function approve(id){var urlpath="<%=path%>"+"/task/isAllowedPlayGame.action";$.ajax({   type:"POST",   url:urlpath,   data: "taskid="+id+"&isapproved=yes"+"&randomStr="+Math.random(),   success: function(msg){   alert(msg);   }});}function notApprove(id){var urlpath="<%=path%>"+"/task/isAllowedPlayGame.action";$.ajax({   type:"POST",   url:urlpath,   data: "taskid="+id+"&isapproved=no"+"&randomStr="+Math.random(),   success: function(msg){   alert(msg);   }});}</script>


查看流程进度的图片的页面

image.jsp

<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%><%@ page import="java.util.*,org.jbpm.api.*,org.jbpm.api.task.*,org.jbpm.api.model.*" %><%@page import="java.lang.Math"%><% String path = request.getContextPath();%><%String picUrl="";if(request.getAttribute("picUrl")!=null){picUrl=(String)request.getAttribute("picUrl");}ActivityCoordinates ac=null;int img_x=0,img_y=0,img_width=0,img_height=0;if(request.getAttribute("ac")!=null){ac=(ActivityCoordinates)request.getAttribute("ac");img_x=ac.getX();img_y=ac.getY();img_width=ac.getWidth();img_height=ac.getHeight();}%><html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><title>查看流程图</title></head><body style="background-color:green;"><img  id="processimg"  src="<%=path%>/<%=picUrl%>?randomStr=<%=Math.random()%>'"  style="position:absolute;left:0px;top:0px;"/> <div style="z-index:100;position:absolute;border:3px solid red;left:<%=img_x%>px;top:<%=img_y%>px;width:<%=img_width%>px;height:<%=img_height%>px;"></div><br><input type="button" value="返回" onclick="javascript:history.back(-1);" /></body></html><script>function funcload(){    var img=document.getElementById("processimg");document.body.style.height=img.height;    document.body.style.width=img.width;    if((typeof img)!="undefined"){     //浏览器窗口的内部高度// alert(document.body.clientWidth+"--"+document.body.clientHeight);    // alert(window.screenTop+"--"+window.screen.availHeight);// alert(document.body.offsetWidth+"--"+document.body.offsetHeight);     window.resizeTo(img.width+38,img.height+window.screenTop+15);    }}window.onload=funcload;</script>


###########################################################################

下面是操作过程的截图效果:

1,点击发布流程afterwork按钮后,再点击查看查看图片按钮,再点击启动流程实例按钮:



2,在任务查看页面,查询登陆账号是“mywife”的人的任务。


3,点击查看流程进度图片(2个按钮都可以)


可见,流程已经走到“能否玩游戏”这个节点了(被红色方框包围的节点是当前流程节点)


4,在任务列表页面,我们点击查看详细信息按钮


注意,这里既然把详细信息列出,在实际应用中一般也是审批走流程的页面,所以我把审批,即通过还是不通过的决策操作也放在了

这个页面(列表后面2个操作决定这个任务走流程的那个节点)。

这里我点击了最后一个按钮“必须先完成学习任务”。


5,再回到任务列表页面:


这时候,你发现待办任务列表(就是上面那个table)已经没数据了。因为,那个任务已经完成了。在历史任务列表里,还会看到。

我再点击查看流程进度图片按钮。


6,流程进度图片



这时候发现流程已经走到节点“学习”了。说明,刚才的决策已经起作用了。

可以断定,例子成功了。


在实际的开发中,我们需要慢慢熟悉jbpm的api和表关系。

因为jbpm的实质就是操作数据库那十几张表。所有的流程无非就是增加了可视化的xml映射。

所有的流程就是对那十几张表的操作。如果能把表结构和表关系搞明白的话,我们完全可以自己写sql来实现流程。

把jbpm的api就可以扔到一边了。



############################补充#########################

在画流程定义xml文件时,我们可能需要用中文。在我的例子中,大多都是中文。

在实验时遇到一个问题,就是写入到数据库的中文是乱码(中文节点的名字在数据库中都是问号)。


开始以为是我的文件编码有问题,检查了一下都是统一的utf-8编码,(在请求响应中也是)。

那这个中文乱码就可能是数据库编码的问题。

查看mysql编码sql

show variables like 'character%';


要改变mysql的编码,我们最好在mysql客户端中修改参数。

sql

/* 下面的sql实际上修改的是参数character_set_database */alter database mydb character set utf8;  set character_set_client=utf8;set character_set_connection=utf8;set character_set_database=utf8;set character_set_results=utf8;set character_set_server=utf8;
如上,操作完成后,我尝试结果还是问号乱码。

我怀疑没有吧mysql的字符编码改成功。

在网上找到另外一种方式,修改mysql的my.ini文件

有2个修改的地方:

[client]port=3306[mysql]#default-character-set=latin1default-character-set=utf8#################[mysqld]port=3306basedir="D:/MySql/"datadir="D:/MySql/data/Data/"#default-character-set=latin1default-character-set=utf8
mysql默认的是latin1编码,改成utf8。


再次尝试,还是问号乱码。


后来在网上看到一个信息:

http://www.qiandl.com/commSense-366-show_comm_content.html
jbpm4.4启动流程实例数据库有乱码


在ssh或者ssh与Jbpm框架整合,在配置连接数据库时,一定要指定编码,尽管Mysql数据库已经指定编码为
Utf-8了,项目及页面编码也是utf-8了,也必须要指定数据库连接编码,防止在页面中中文显示正常,保存到
数据库前正常,直接在数据库表中插入中文正常,在页面中读取数据中文正常,但是保存中文时,数据库显示
乱码,从而页面读取时也会乱码
即指定:
jdbc:mysql://localhost:3306/sloa?characterEncoding=UTF-8
在数据库的后面加上:
?characterEncoding=UTF-8
就指定了数据按照utf-8的编码保存到Mysql数据库。


这样才能保证中文无乱码
如果没有指定,则Jbpm启动流程实例时,jbpm要把相关的流程实例信息写入表
 jbpm4_execution
打开该,会发现ActivityName的中文乱码为问号等。
所以在整合时,一定要注意数据库连接的Url上加入编码。

#############################

我用spring配置的链接,找上面的方法修改了我的配置文件

#mysqljdbc.driverClassName=com.mysql.jdbc.Driver#jdbc.url=jdbc:mysql://127.0.0.1:3306/mydbjdbc.url=jdbc:mysql://127.0.0.1:3306/mydb?characterEncoding=UTF-8jdbc.username=rootjdbc.password=roothibernate.dialect=org.hibernate.dialect.MySQLInnoDBDialect

这样修改后,中文的乱码就没有了。看来mysql的编码还是挺复杂,链接时的编码,存储的编码。。。

不用不知道,不过还是没想明白,mysql这样设计的目的是什么。

不管怎么样,乱码问题解决了。