次篇接上篇 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这样设计的目的是什么。
不管怎么样,乱码问题解决了。