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

次篇接上篇 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{//mysecond
				map.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\webapp
		String imageBaseUrl=webBaseUrl+"\\jsp\\jbpmtest\\images";
		System.out.println("imageBaseUrl:"+imageBaseUrl);//  D:\ChinaDevelopmentBankJBPM\workSpace\frame\webapp\jsp\jbpmtest\images
		if(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)" οnclick="query()">查询</a></h1></td>
		</tr>
		
		<tr>
			 <td align="center"><input type="button" οnclick="setUpProcess()"  value='发布流程:mysecond' ></input></td>
		</tr>
		<tr>
			 <td align="center"><input type="button" οnclick="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" οnclick="delprocess('<%=deploymentId%>')"  value='删除流程' ></input></td>
					 <td><input type="button" οnclick="showImage('<%=proid%>')"  value='查看图片' ></input></td>
					 <td><input type="button" οnclick="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 stub
		String 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)" οnclick="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" οnclick="showDetail('<%=id%>','<%=formResourceName%>')"  value='查看详细信息' ></input></td>
					 <td><input type="button" οnclick="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" οnclick="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)" οnclick="approve('<%=id%>')" >同意玩会游戏</a></td>
					 <td><a href="javascript:void(0)" οnclick="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="返回" οnclick="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.οnlοad=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=latin1
default-character-set=utf8

#################
[mysqld]
port=3306
basedir="D:/MySql/"
datadir="D:/MySql/data/Data/"
#default-character-set=latin1
default-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配置的链接,找上面的方法修改了我的配置文件

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

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

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

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





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值