使用Java开源工作流jBPM开发一个简单的Demo

    jBPM是jboss旗下遵守LGPL许可的java开源工作流,功能比较完善,从4.0开始引入了pvm的概念,支持jPDL、BPEL等流程定义语言。由于相关资料还比较少,开发自己的一个demo还不是太容易,本文详细讲解如何做一个简单的demo程序。
    我们从 http://www.jboss.org/jbossjbpm/jbpm_downloads/下载jBPM,实际使用时发现4.0.CR1和4.1版本各有一些问题,此处把这两个版本都下载下来。开发使用4.1版本,Eclipse插件GPD(图形化设计流程)使用4.0.CR1版本的,tomcat使用6.0.18版本的,jdk要求5.0及以上,Eclipse使用eclipse-jee-galileo-win32版本的。
    下载包里面有自带的一个example,根据jBMP的文档可以部署,但这个example把工作流部分封装为RESTful Web Service,学习起来有一定难度,看了会让人一头雾水,此处就不讲了。以下讲述如何把jBPM嵌入到应用系统中去。
    1、在Eclipse中安装GPD。
    把%jbpm-4.0.CR1_HOME%/gpd下的jbpm-gpd-site.zip安装到Eclipse中,熟悉Eclipse的知道安装方法,在jBPM的文档中也有介绍。
    2、在Eclipse中建立一个动态网站的项目jBPMDemo,复制必要的jar文件到WEB-INF/lib下面。
    把%jbpm-4.1_HOME%/lib下的所有jar文件、%jbpm-4.1_HOME%/jbpm.jar复制过去。
    但juel.jar中javax/el中的类与tomcat中的有冲突,把juel.jar中的javax/el删除。
    3、配置mysql数据库。
    在mysql数据库中建立一个名为jbpmdb的数据库,在里面执行%jbpm-4.1_HOME%/install/src/db/jbpm.mysql.create.sql建立jbpm所需的数据库表。
    另外建立一个表存放业务数据:
create table ask_for_leave (
id MEDIUMINT NOT NULL AUTO_INCREMENT primary key,
apply_user varchar(50), -- 申请人
apply_time timestamp default now(), -- 申请时间
begin_leave_time timestamp, -- 假期开始时间
end_leave_time timestamp, -- 假期结束时间
leave_reason varchar(500), -- 请假理由
approve_user varchar(50), -- 审批人
approve_time timestamp, -- 审批时间
is_passed smallint, -- 是否同意,1 同意,2 驳回
approve_remark varchar(500), -- 审批备注,如驳回的原因
back_time timestamp -- 销假时间
);
    4、配置JOTM事务支持。
    把carol.properties、jta.jar、commons-logging.jar、carol.jar、connector-1_5.jar、jotm.jar、jotm_jrmp_stubs.jar、jts1_0.jar、mysql-connector-java-3.1.11-bin.jar、objectweb-datasource.jar、xapool.jar放到%tomcat_home%/lib下面。
    把howl.jar、jotm.jar、objectweb-datasource.jar、ow_carol.jar、xapool.jar放到WEB-INF/lib下面。
    在jBPLDemo的context配置数据源,代码如下:
<?xml version='1.0' encoding='utf-8'?>
<Context displayName="jBPMDemo"
         docBase="${catalina.base}/webapps/jBPMDemo" 
         path="/jBPMDemo" 
         workDir="work/Catalina/localhost/jBPMDemo" reloadable="true">
         
   <Resource name="UserTransaction"
      auth="Container"
      type="javax.transaction.UserTransaction"
      factory="org.objectweb.jotm.UserTransactionFactory"
      jotm.timeout="180" />

   <Resource name="JbpmDS" type="javax.sql.DataSource"
      factory="org.objectweb.jndi.DataSourceFactory"
      maxWait="5000"
      maxActive="300"
      maxIdle="2"
      username="root"
      password=""
      driverClassName="com.mysql.jdbc.Driver"
      url="jdbc:mysql://127.0.0.1:3306/jbpmdb"
   />     
       
</Context>
    在应用的WEB-INF/classes下建立文件jbpm.cfg.xml,内容如下:
<?xml version="1.0" encoding="UTF-8"?>

<jbpm-configuration>

  <import resource="jbpm.default.cfg.xml" />
  <import resource="jbpm.tx.hibernate.cfg.xml" />
  <import resource="jbpm.jpdl.cfg.xml" />
  <import resource="jbpm.identity.cfg.xml" />
  <import resource="jbpm.businesscalendar.cfg.xml" />
  <import resource="jbpm.jobexecutor.cfg.xml" />

</jbpm-configuration>
    在应用的WEB-INF/classes下建立文件jbpm.hibernate.cfg.xml,内容如下:
<?xml version="1.0" encoding="utf-8"?>

<!DOCTYPE hibernate-configuration PUBLIC
          "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
          "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
<session-factory>

<property name="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>
<property name="hibernate.connection.datasource">java:comp/env/JbpmDS</property>
<property name="hibernate.transaction.factory_class">org.hibernate.transaction.JTATransactionFactory</property>
<property name="hibernate.transaction.manager_lookup_class">org.hibernate.transaction.JOTMTransactionManagerLookup</property>
<property name="jta.UserTransaction">java:comp/env/UserTransaction</property>

<mapping resource="jbpm.repository.hbm.xml" />
<mapping resource="jbpm.execution.hbm.xml" />
<mapping resource="jbpm.history.hbm.xml" />
<mapping resource="jbpm.task.hbm.xml" />
<mapping resource="jbpm.identity.hbm.xml" />

</session-factory>
</hibernate-configuration>
    5、在Eclipse中GPD定义流程。
    GPD对中文的支持还有问题,要用图形界面与直接编写代码相结合的方式,最后效果如下图:
流程图
    产生的代码askForLeave.jpdl.xml放到应用的WEN-INF/classes/jpdl下面,代码如下:
<?xml version="1.0" encoding="UTF-8"?>

<process key="askForLeave" name="请假流程" version="1" xmlns="http://jbpm.org/4.0/jpdl">
   <swimlane candidate-groups="manager" name="manager"/>
   <start g="188,10,48,48" name="start1">
      <transition g="-30,-10" name="开始" to="填写请假申请"/>
   </start>
   <task assignee="#{owner}" g="167,86,92,52" name="填写请假申请">
      <transition g="-50,-11" name="提交审批" to="审批"/>
   </task>
   <task g="169,159,92,52" name="审批" swimlane="manager">
      <transition g="-76,-8" name="判断审批结果" to="exclusive1"/>
   </task>
   <task assignee="#{owner}" g="91,298,92,52" name="销假">
      <transition g="-50,-11" name="休假结束" to="end1"/>
   </task>
   <task assignee="#{owner}" g="252,295,92,52" name="查看原因">
      <transition g="-34,-10" name="请假结束" to="end2"/>
   </task>
   <end g="116,377,48,48" name="end1"/>
   <end g="275,372,48,48" name="end2"/>
   <decision g="190,227,48,48" name="exclusive1">
      <transition g="0,-15" name="拒绝" to="查看原因">
        <condition expr="#{is_passed==false}"/>
      </transition>
      <transition g="-31,-16" name="通过" to="销假"/>
   </decision>
</process>
    产生的图片askForLeave.png放到应用的askForLeave文件夹下面。
    6、建立几个java类。
demo.jbpm.DBUtil:
package demo.jbpm;

import java.sql.Connection;

import javax.naming.InitialContext;
import javax.sql.DataSource;

import javax.transaction.UserTransaction;

public class DBUtil {
    private static DataSource ds;
    /**
     * 获取数据源
     * @return
     * @throws Exception
     */
    public static DataSource getDS() throws Exception {
        if (ds == null) ds = (DataSource) new InitialContext().lookup("java:comp/env/JbpmDS");
        return ds;
    }
    
    /**
     * 获取数据库连接
     * @return
     * @throws Exception
     */
    public static Connection getConn() throws Exception {
        return getDS().getConnection();
    }
    
    /**
     * 获取事务UserTransaction
     * @return
     * @throws Exception
     */
    public static UserTransaction getUserTransaction() throws Exception {
        UserTransaction ut = (UserTransaction) new InitialContext().lookup("java:comp/env/UserTransaction");
        return ut;
    }
}
    demo.jbpm.JBPMUtil.java:
package demo.jbpm;

import org.jbpm.api.Configuration;
import org.jbpm.api.ExecutionService;
import org.jbpm.api.IdentityService;
import org.jbpm.api.ProcessEngine;
import org.jbpm.api.RepositoryService;
import org.jbpm.api.TaskService;

public class JBPMUtil {
    private static ProcessEngine pe;
    private static RepositoryService repositoryService;
    private static ExecutionService executionService;
    private static IdentityService identityService;
    private static TaskService taskService;
    
    public static void deploy(String jdplPath) {
        String deployId = getRepositoryService().createDeployment().addResourceFromClasspath(jdplPath).deploy();
        System.out.println("----------deploy id:" + deployId);
    }
    
    public static ProcessEngine getProcessEngine() {
        if (pe == null) {
            Configuration config = new Configuration();
            pe = config.buildProcessEngine();
        }
        return pe;
    }
    
    public static RepositoryService getRepositoryService() {
        if (repositoryService == null) repositoryService = getProcessEngine().getRepositoryService();
        return repositoryService;
    }
    
    public static ExecutionService getExecutionService() {
        if (executionService == null) executionService = getProcessEngine().getExecutionService();
        return executionService;
    }
    
    public static IdentityService getIdentityService() {
        if (identityService == null) identityService = getProcessEngine().getIdentityService();
        return identityService;
    }
    
    public static TaskService getTaskService() {
        if (taskService == null) taskService = getProcessEngine().getTaskService();
        return taskService;
    }
}
    demo.jbpm.AskForLeave.java:
package demo.jbpm;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.transaction.Status;
import javax.transaction.UserTransaction;

import org.jbpm.api.ProcessDefinition;
import org.jbpm.api.ProcessInstance;
import org.jbpm.api.model.ActivityCoordinates;
import org.jbpm.api.task.Task;

public class AskForLeave {
    private final static String employeeName = "王三";
    private final static String managerName = "李五";
    
    public static void deploy() {
        JBPMUtil.deploy("jpdl/askForLeave.jpdl.xml");
        JBPMUtil.getIdentityService().createUser(employeeName, "王", "三");
        JBPMUtil.getIdentityService().createUser(managerName, "李", "五");
        JBPMUtil.getIdentityService().createGroup("manager");
        JBPMUtil.getIdentityService().createMembership(managerName, "manager");
    }
    
    /**
     * 请假申请
     * @param request
     * @throws Exception
     */
    public static void apply(HttpServletRequest request) throws Exception {
        UserTransaction ut =DBUtil.getUserTransaction();
        Connection conn = DBUtil.getConn();
        boolean rollback = false;
        try {
            ut.begin();
            //*********业务部分
            //请假申请存入数据库
            Statement stmt = conn.createStatement();
            String sql = "insert into ask_for_leave(apply_user," +
                  "begin_leave_time,end_leave_time,leave_reason) values(" +
                  "'" + request.getParameter("apply_user") + "'," +
                  "'" + request.getParameter("begin_leave_time") + "'," +
                  "'" + request.getParameter("end_leave_time") + "'," +
                  "'" + request.getParameter("leave_reason") + "')";
            System.out.println("insert:" + sql);
            stmt.executeUpdate(sql, Statement.RETURN_GENERATED_KEYS);
            ResultSet rs = stmt.getGeneratedKeys();
            int id = 0;
            if (rs.next()) id = rs.getInt(1);
            System.out.println("--------------id:" + id);
            
            
            //*********工作流部分
            //新建工作流实例
            Map var = new HashMap();
            var.put("owner", employeeName);
            var.put("biz_id", id);
            ProcessInstance processInstance = JBPMUtil.getExecutionService().startProcessInstanceByKey("askForLeave", var);
            
            //执行动作
            List<Task> tasks = JBPMUtil.getTaskService().findPersonalTasks(employeeName);
            for (Task t : tasks) {
                if (processInstance.getId().equals(JBPMUtil.getExecutionService().findExecutionById(t.getExecutionId()).getProcessInstance().getId())
                        && t.getActivityName().equals("填写请假申请")) {
                    
                    JBPMUtil.getTaskService().completeTask(t.getId());
                }
                
            }
        }
        catch (Exception e) {
            rollback = true;
            e.printStackTrace();
            throw e;
        }
        finally {
            if (ut != null && ut.getStatus() != Status.STATUS_NO_TRANSACTION) {
                if (rollback) ut.rollback();
                else ut.commit();
            }
            
            if (conn != null) conn.close();
        }
    }
    
    /**
     * 获取经理的工作列表
     * @return
     * @throws Exception
     */
    public static List<Map> getManagerWorkList() throws Exception {
        List<Map> workList = new ArrayList<Map>();
        List<Task> tasks = JBPMUtil.getTaskService().findGroupTasks(managerName);
        System.out.println("---------task count:" + tasks.size());
        for (Task t : tasks) {
            String processDefinitionId = JBPMUtil.getExecutionService().findExecutionById(t.getExecutionId()).getProcessInstance().getProcessDefinitionId();
            ProcessDefinition processDefinition = JBPMUtil.getRepositoryService().createProcessDefinitionQuery().processDefinitionId(processDefinitionId).uniqueResult();
            System.out.println("---------pro name:" + JBPMUtil.getExecutionService().findExecutionById(t.getExecutionId()).getProcessInstance().getProcessDefinitionId());
            System.out.println("---------acct name:" + t.getActivityName());
            if ("请假流程".equals(processDefinition.getName())
                    && t.getActivityName().equals("审批")) {
                Map item = new HashMap();
                item.put("wfId", JBPMUtil.getExecutionService().findExecutionById(t.getExecutionId()).getProcessInstance().getId());
                item.put("wfName", "请假流程");
                item.put("taskId", t.getId());
                item.put("taskName", t.getActivityName());
                workList.add(item);
            }
        }
        return workList;
    }
    
    /**
     * 获取位置
     * @param wfId
     * @return
     */
    public static List<ActivityCoordinates> getActiveActivityCoordinates(String wfId) {
        List<ActivityCoordinates> result = new ArrayList<ActivityCoordinates>();
        ProcessInstance processInstance = JBPMUtil.getExecutionService().findProcessInstanceById(wfId);
        String processDefinitionId = processInstance.getProcessDefinitionId();
        Set<String> activities = processInstance.findActiveActivityNames();
        for (String act : activities) {
            ActivityCoordinates coor = JBPMUtil.getRepositoryService().getActivityCoordinates(processDefinitionId, act);
            result.add(coor);
        }
        
        return result;
    }
    
    /**
     * 根据请假单id获取请假单信息
     * @param id
     * @return
     * @throws Exception
     */
    public static Map getById(String id) throws Exception {
        Map form = new HashMap();
        Connection conn = DBUtil.getConn();
        
        try {
            Statement stmt = conn.createStatement();
            ResultSet rst = stmt.executeQuery("select * from ask_for_leave where id=" + id);
            if (rst.next()) {
                form.put("apply_user", rst.getString("apply_user"));
                form.put("begin_leave_time", rst.getString("begin_leave_time"));
                form.put("end_leave_time", rst.getString("end_leave_time"));
                form.put("leave_reason", rst.getString("leave_reason"));
            }
            rst.close();
            stmt.close();
        }
        catch (Exception e) {
            e.printStackTrace();
            throw e;
        }
        finally {
            
            if (conn != null) conn.close();
        }
        
        return form;
    }
    
    /**
     * 根据工作流id货物请假单id
     * @param wfId
     * @return
     * @throws Exception
     */
    public static String getBizId(String taskId) throws Exception {
        
        return JBPMUtil.getTaskService().getVariable(taskId, "biz_id").toString();
    }
    
    /**
     * 审批
     * @param request
     * @throws Exception
     */
    public static void approval(HttpServletRequest request) throws Exception {
        UserTransaction ut = DBUtil.getUserTransaction();
        Connection conn = DBUtil.getConn();
        boolean rollback = false;
        try {
            ut.begin();
            
            //*********业务部分
            //审批信息存入数据库
            Statement stmt = conn.createStatement();
            String sql = "update ask_for_leave set " +
                  "approve_user='" + managerName + "', " +
                  "approve_time=now()," +
                  "is_passed=" + request.getParameter("is_passed") + "," +
                  "approve_remark='" + request.getParameter("approve_remark") + "' " +
                  "where id=" + request.getParameter("biz_id");
            System.out.println("--------------update:" + sql);
            stmt.executeUpdate(sql);
            System.out.println("--------------update complete");
            
            //*********工作流部分
            boolean isPassed = false;
            if ("1".equals(request.getParameter("is_passed"))) isPassed = true;
            Map var = new HashMap();
            var.put("is_passed", isPassed);
            JBPMUtil.getTaskService().completeTask(request.getParameter("taskId"), var);
        }
        catch (Exception e) {
            rollback = true;
            e.printStackTrace();
            throw e;
        }
        finally {
            if (ut != null && ut.getStatus() != Status.STATUS_NO_TRANSACTION) {
                if (rollback) ut.rollback();
                else ut.commit();
            }
            
            if (conn != null) conn.close();
        }
    }
    
    /**
     * 获取员工的工作列表
     * @return
     * @throws Exception
     */
    public static List<Map> getEmployeeWorkList() throws Exception {
        List<Map> workList = new ArrayList<Map>();
        List<Task> tasks = JBPMUtil.getTaskService().findPersonalTasks(employeeName);
        System.out.println("---------task count:" + tasks.size());
        for (Task t : tasks) {
            String processDefinitionId = JBPMUtil.getExecutionService().findExecutionById(t.getExecutionId()).getProcessInstance().getProcessDefinitionId();
            ProcessDefinition processDefinition = JBPMUtil.getRepositoryService().createProcessDefinitionQuery().processDefinitionId(processDefinitionId).uniqueResult();
            System.out.println("---------pro name:" + JBPMUtil.getExecutionService().findExecutionById(t.getExecutionId()).getProcessInstance().getProcessDefinitionId());
            System.out.println("---------acct name:" + t.getActivityName());
            if ("请假流程".equals(processDefinition.getName())) {
                Map item = new HashMap();
                item.put("wfId", JBPMUtil.getExecutionService().findExecutionById(t.getExecutionId()).getProcessInstance().getId());
                item.put("wfName", "请假流程");
                item.put("taskId", t.getId());
                item.put("taskName", t.getActivityName());
                item.put("biz_id", JBPMUtil.getTaskService().getVariable(t.getId(), "biz_id"));
                workList.add(item);
            }
        }
        return workList;
    }
    
    /**
     * 申请人处理审批后的事务
     * @param request
     * @throws Exception
     */
    public static void leave(HttpServletRequest request) throws Exception {
        UserTransaction ut = DBUtil.getUserTransaction();
        Connection conn = DBUtil.getConn();
        boolean rollback = false;
        try {
            ut.begin();
            //处理休假情况
            boolean isPassed = (Boolean) JBPMUtil.getTaskService().getVariable(request.getParameter("taskId"), "is_passed");
            int bizId = (Integer) JBPMUtil.getTaskService().getVariable(request.getParameter("taskId"), "biz_id");
            if (isPassed) {
                Statement stmt = conn.createStatement();
                String sql = "update ask_for_leave set " +
                      "back_time=now() " +
                      "where id=" + bizId;
                System.out.println("--------------update:" + sql);
                stmt.executeUpdate(sql);
            }
            
            //*********工作流部分
            JBPMUtil.getTaskService().completeTask(request.getParameter("taskId"));
        }
        catch (Exception e) {
            rollback = true;
            e.printStackTrace();
            throw e;
        }
        finally {
            if (ut != null && ut.getStatus() != Status.STATUS_NO_TRANSACTION) {
                if (rollback) ut.rollback();
                else ut.commit();
            }
            
            if (conn != null) conn.close();
        }
    }
}
    7、建立jsp文件。
    askForLeave/deploy.jsp(用于部署jpdl,需要首先运行,只需要运行一次):
<%@page import="demo.jbpm.AskForLeave"%>
<%
AskForLeave.deploy();
%>
    askForLeave/apply.jsp(用于启动业务,需要第二个运行):
<%@ page language="java" contentType="text/html; charset=UTF-8"     pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>apply</title>
</head>
<body>
<form name="form1" method="POST" action="apply_result.jsp">
申请人:<input type="text" name="apply_user" value="suntao"/><br/>
假期开始时间:<input type="text" name="begin_leave_time" value="2009-08-07 09:00"/>(YYYY-MM-DD HH24:MI)<br/>
假期结束时间:<input type="text" name="end_leave_time" value="2009-08-07 18:00"/>(YYYY-MM-DD HH24:MI)<br/>
请假理由:<input type="text" name="leave_reason" value="事假"/><br/>
<input type="submit" value="提交"/><br/>
</form>
</body>
</html>
    askForLeave/apply_result.jsp(用于响应apply.jsp):
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@page import="demo.jbpm.AskForLeave"%>
<%
request.setCharacterEncoding("UTF-8");
String result = "成功";
try {
    AskForLeave.apply(request);
}
catch(Exception e) {
    result = "失败";
    e.printStackTrace();
}
%>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>apply</title>
</head>
<body>
<%=result %>
</body>
</html>
    askForLeave/managerWorkList.jsp(用于显示经理的工作列表,需要第三个运行):
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%@page import="demo.jbpm.AskForLeave"%>
<%@page import="java.util.List"%>
<%@page import="java.util.Map"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>apply</title>
</head>
<body>
<%
List<Map> workList = AskForLeave.getManagerWorkList();
%>
<table border="1">
  <tr>
    <td>工作名称</td>
    <td>工作任务</td>
    <td>处理</td>
    <td>流程图</td>
  </tr>
  <%for(int i=0;i<workList.size();i++){ %>
  <tr>
    <td><%=workList.get(i).get("wfName") %></td>
    <td><%=workList.get(i).get("taskName") %></td>
    <td><a href="approval.jsp?wfId=<%=workList.get(i).get("wfId")%>&taskId=<%=workList.get(i).get("taskId")%>">处理</a></td>
    <td><a href="viewWfGraph.jsp?wfId=<%=workList.get(i).get("wfId")%>&wfFileName=askForLeave.png">查看</a></td>
  </tr>
  <%} %>
</table>
</body>
</html>
    askForLeave/approval.jsp(用于经理审批):
<%@<page<language="java"<contentType="text/html;<charset=UTF-8"
<<<<pageEncoding="UTF-8"%>
<!DOCTYPE<html<PUBLIC<"-//W3C//DTD<HTML<4.01<Transitional//EN"<"http://www.w3.org/TR/html4/loose.dtd">
<%@page<import="demo.jbpm.AskForLeave"%>
<%@page<import="java.util.Map"%>
<html>
<head>
<meta<http-equiv="Content-Type"<content="text/html;<charset=UTF-8">
<title>apply</title>
<script<language="javascript">
function<go(is_passed)
{
<<document.getElementById("is_passed").value<=<is_passed;
<<document.getElementById("form1").submit();
}
</script>
</head>
<body>
<%
String<taskId=request.getParameter("taskId");
String<id<=<AskForLeave.getBizId(taskId);
Map<formData<=<AskForLeave.getById(id);
%>
<form<id="form1"<name="form1"<method="POST"<action="approval_result.jsp">
<input<type="hidden"<name="biz_id"<value="<%=id<%>"/>
<input<type="hidden"<name="taskId"<value="<%=taskId<%>"/>
<input<type="hidden"<id="is_passed"<name="is_passed"<value=""/>
申请人:<%=formData.get("apply_user")<%><br/>
假期开始时间:<%=formData.get("begin_leave_time")<%><br/>
假期结束时间:<%=formData.get("end_leave_time")<%><br/>
请假理由:<%=formData.get("leave_reason")<%><br/>
审批意见:<input<type="text"<name="approve_remark"<value=""/><br/>
<input<type="button"<value="同意"<οnclick="go(1)"/>  <input<type="button"<value="拒绝"<οnclick="go(2)"/><br/>
</form>
</body>
</html>
    askForLeave/approval_result.jsp(用于响应approval.jsp):
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@page import="demo.jbpm.AskForLeave"%>
<%
request.setCharacterEncoding("UTF-8");
String result = "成功";
try {
    AskForLeave.approval(request);
}
catch(Exception e) {
    result = "失败";
    e.printStackTrace();
}
%>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>apply</title>
</head>
<body>
<%=result %>
</body>
</html>
    askForLeave/employeeWorkList.jsp(用于显示员工工作列表,需要第四个运行):
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%@page import="demo.jbpm.AskForLeave"%>
<%@page import="java.util.List"%>
<%@page import="java.util.Map"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>apply</title>
</head>
<body>
<%
List<Map> workList = AskForLeave.getEmployeeWorkList();
%>
<table border="1">
  <tr>
    <td>工作名称</td>
    <td>业务id</td>
    <td>处理</td>
    <td>流程图</td>
  </tr>
  <%for(int i=0;i<workList.size();i++){ %>
  <tr>
    <%
    List<Map> actions = (List<Map>) workList.get(i).get("actions"); 
    %>
    <td><%=workList.get(i).get("wfName") %></td>
    <td><%=workList.get(i).get("biz_id") %></td>
    <td>
    <a href="leave_result.jsp?biz_id=<%=workList.get(i).get("biz_id") %>&wfId=<%=workList.get(i).get("wfId") %>&taskId=<%=workList.get(i).get("taskId") %>"><%=workList.get(i).get("taskName") %></a>
    </td>
    <td><a href="viewWfGraph.jsp?wfId=<%=workList.get(i).get("wfId")%>&wfFileName=askForLeave.png">查看</a></td>
  </tr>
  <%} %>
</table>
</body>
</html>
    askForLeave/leave_result.jsp(用于员工处理后续事务):
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@page import="demo.jbpm.AskForLeave"%>
<%
request.setCharacterEncoding("UTF-8");
String result = "成功";
try {
    AskForLeave.leave(request);
}
catch(Exception e) {
    result = "失败";
    e.printStackTrace();
}
%>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>apply</title>
</head>
<body>
<%=result %>
</body>
</html>
    8、增加图形显示流程状态。
    此处采用OSWorkflow的做法,把OSWorkflow中的wz_jsgraphics.js放到应用的js目录下。
    建立askForLeave/viewWfGraph.jsp:
<%@ page import="java.util.List" %>
<%@page import="demo.jbpm.JBPMUtil"%>
<%@page import="demo.jbpm.AskForLeave"%>
<%@page import="org.jbpm.api.model.ActivityCoordinates"%>
<%
String wfId = request.getParameter("wfId");
String wfFileName = request.getParameter("wfFileName");
List<ActivityCoordinates> coors = AskForLeave.getActiveActivityCoordinates(wfId);
%>

<div id="workflowCanvas" style="position:relative;height:566px;width:508px;">
<img src="<%=wfFileName %>" border=0/>
</div>
<script type="text/javascript" src="../js/wz_jsgraphics.js"></script>

<script type="text/javascript">
var jg = new jsGraphics("workflowCanvas");
jg.setColor("#ff0000");
jg.setStroke(3);
var xAdjust = 4;
var yAdjust = 4;
var widthAdjust = -10;
var heightAdjust = -10;
<%for (ActivityCoordinates coor : coors) {%>
jg.drawRect(parseInt("<%=coor.getX()%>") + xAdjust, parseInt("<%=coor.getY()%>") + yAdjust, parseInt("<%=coor.getWidth()%>") + widthAdjust, parseInt("<%=coor.getHeight()%>") + heightAdjust);
<%}%>
jg.paint();

</script>
    这样就做完了,运行应用程序,就可以看到效果了。值得一提的是,图形化显示流程状态的效果,如下:
 
流程效果图
  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 19
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 19
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值