在上一篇文章中我們已經基本上實現了一個請假流程定義的發佈和刪除操作,並且我們已經將jbpm4的流程定義集成到了web服務中。下面我們將要做如下幾件事:
1)在web應用中實現請假流程的發起;
2)針對不同用戶的登錄,我們顯示不同的代辦任務以實現用戶完成自己的task。
(再次聲明:這只是我的個人學習筆記,主要是通過看了family168網--臨遠的視頻教程,感謝原作。)
具體操作如下:
1、web應用程序的整體文件架構
圖5-1 程序的整體文件架構
這裏簡要作如下說明:
1)對於程序的src目錄下的文件主要是請假流程leave.jpdl.xml的流程定義文件和jbpm4的註冊文件;
2)在src目錄下爲了通過編譯我們導入了jbpm4.4的第三方庫文件;
3)在WebContent目錄下的文件主要是web應用中運行時使用的jsp文件,此處我們爲了實現程序視圖和邏輯處理的分離將相應的操作放在特定的jsp文件中實現;
4)在WebContent/WEB-INF/lib目錄下我們導入了jbpm4.4運行時所需要的第三方庫文件;
具體程序的實現細節以及每個jsp文件的作用我們將在後面詳細給出。
2、流程定義的改動
流程定義源文件:leave.jpdl.xml文件的源碼如下
- <?xml version="1.0" encoding="UTF-8"?>
- <process name="leave" xmlns="http://jbpm.org/4.4/jpdl">
- <start g="136,49,48,48" name="start1">
- <transition to="申請"/>
- </start>
- <!-- #{owner}的作用是實現變量存儲申請人,從而達到誰申請誰就能獲得代辦任務列表 -->
- <task assignee="#{owner}" form="request.jsp" g="112,143,92,52" name="申請">
- <transition to="經理審批"/>
- </task>
- <task assignee="manager" form="manager.jsp" g="113,247,92,52" name="經理審批">
- <transition g="-79,-22" name="批准" to="exclusive1"/>
- <transition g="47,270;48,169:-45,-22" name="駁回" to="申請"/>
- </task>
- <decision expr="#{day > 3 ? '老闆審批' : '結束'}" g="131,354,48,48" name="exclusive1">
- <transition g="273,375:-69,-22" name="老闆審批" to="老闆審批"/>
- <transition g="-50,-22" name="結束" to="end1"/>
- </decision>
- <task assignee="boss" form="boss.jsp" g="228,401,92,52" name="老闆審批">
- <transition g="275,473:" to="end1"/>
- </task>
- <end g="135,450,48,48" name="end1"/>
- </process>
這裏注意的是我們將第一個task節點的任務分配給#{owner}變量,從而實現了不同用戶的動態登錄都可以申請請假,而我們的“經理審批”task節點則分配給了manager用戶,"老闆審批"task節點則分配給了boss用戶,這些操作都可以在圖形界面的property中設置。
另外需要說明的是對於任務的完成人我們並不需要顯示的在程序中保存,jbpm會自動保存。
流程定義的圖形界面如下:
圖5-2 流程定義圖形界面
3、index.jsp的設計和實現
index.jsp是整個web應用程序的主界面,其代碼如下:
- <%@ page language="java" contentType="text/html; charset=UTF-8"
- pageEncoding="UTF-8"%>
- <!-- 檢測用戶是否已經登錄 -->
- <%@include file="checkLogin.jsp" %>
- <%@page import="java.util.*,org.jbpm.api.*,org.jbpm.api.task.*"%>
- <!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>Index</title>
- </head>
- <body>
- <%
- //獲得processEngine流程引擎
- ProcessEngine processEngine=Configuration.getProcessEngine();
- //獲得RepositoryService對象
- //三個作用:1、流程發佈定義 2、管理流程定義 3、刪除流程定義
- RepositoryService repositoryService=processEngine.getRepositoryService();
- //獲得ExecutionService對象
- ExecutionService executionService=processEngine.getExecutionService();
- //獲得TaskService對象
- TaskService taskService=processEngine.getTaskService();
- //獲得登錄用戶名
- String username=(String)session.getAttribute("username");
- //獲得觸發連接並處理
- /*String action=request.getParameter("action");
- if("deploy".equals(action))
- {
- //部署流程定義
- repositoryService.createDeployment().addResourceFromClasspath("leave.jpdl.xml").deploy();
- }else if("remove".equals(action))
- {
- //刪除已部署的流程定義
- repositoryService.deleteDeploymentCascade(request.getParameter("id"));
- }*/
- //獲得流程定義
- List<ProcessDefinition> list =repositoryService.createProcessDefinitionQuery().list();
- %>
- <!-- 部署流程定義對應連接 -->
- <a href="deploy.jsp">發佈新流程</a> | [username:<%=username%>] | <a href="login.jsp">登錄</a><br>
- <table border="1" width="100%">
- <caption>流程定義</caption>
- <thead>
- <tr>
- <td>id</td>
- <td>name</td>
- <td>version</td>
- <td>action</td>
- </tr>
- </thead>
- <%
- //for循環顯示流程部署
- for (ProcessDefinition pd: list)
- {
- %>
- <tr>
- <td><%=pd.getId() %></td>
- <td> <%=pd.getName() %></td>
- <td><%=pd.getVersion() %></td>
- <td><a href="remove.jsp?id=<%=pd.getDeploymentId()%>">remove</a>
- |
- <a href="start.jsp?id=<%=pd.getId()%>">start</a></td>
- </tr>
- <%
- }
- %>
- </table>
- <%
- //for循環顯示流程實例列表
- List <ProcessInstance> piList = executionService.createProcessInstanceQuery().list();
- %>
- <table border="1" width="100%">
- <caption>流程實例</caption>
- <thead>
- <tr>
- <td>id</td>
- <td>activity</td>
- <td>state</td>
- <td>detail</td>
- </tr>
- </thead>
- <%
- for (ProcessInstance pi:piList)
- {
- %>
- <tr>
- <td><%=pi.getId() %></td>
- <td><%=pi.findActiveActivityNames() %></td>
- <td><%=pi.getState() %></td>
- <td><a href="view.jsp?id=<%=pi.getId() %>">view</a></td>
- </tr>
- <%
- }
- %>
- </table>
- <%
- List<Task> taskList = taskService.findPersonalTasks(username);
- %>
- <table border="1" width="100%">
- <caption>代辦任務</caption>
- <thead>
- <tr>
- <td>id</td>
- <td>name</td>
- <td> </td>
- </tr>
- </thead>
- <%
- for (Task task:taskList)
- {
- %>
- <tr>
- <td><%=task.getId() %></td>
- <td><%=task.getActivityName() %></td>
- <!-- 獲取jpdl中所註冊的task業務處理的jsp頁面鏈接並顯示 -->
- <td><a href="<%=task.getFormResourceName()%>?id=<%=task.getId() %>">view</a></td>
- </tr>
- <%
- }
- %>
- </table>
- </body>
- </html>
index.jsp主要由5部分構成,分別加以說明:
1)獲得jbpm4流程定義、管理等操作的基本對象;
2)定義連接,調用deploy.jsp實現流程的發佈,定義連接,調用login.sjp實現用戶登錄;
3)通過List<ProcessDefinition> list =repositoryService.createProcessDefinitionQuery().list();獲得當前流程定義並以表格的形式顯示出來;
4)通過List <ProcessInstance> piList = executionService.createProcessInstanceQuery().list();獲得當前已經發起的流程定義並以表格方式顯示出來;
5)通過List<Task> taskList = taskService.findPersonalTasks(username); 獲得當前登錄用戶的待處理任務並顯示,同時顯示在leave.jpdl.xml中註冊的相應任務接點處理所對應的就是jsp頁面鏈接。例如:
對於:“經理審批” 節點
<task assignee="manager" form="manager.jsp" g="113,247,92,52" name="經理審批">
我們通過
<td><a href="<%=task.getFormResourceName()%>?id=<%=task.getId() %>">view</a></td>
來顯示manager.jsp頁面的鏈接。
另注:我認爲jbpm自動保存任務的完成者也是通過此處完成的。
4、相關jsp源碼
login.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>Insert title here</title>
- </head>
- <body>
- <fieldset>
- <legend>登錄</legend>
- <form action="doLogin.jsp" method="post">
- 用戶名:<input type="text" name="username" value=""/><br/>
- <input type="submit">
- </form>
- </fieldset>
- </body>
- </html>
doLogin.jsp
- <%
- session.setAttribute("username", request.getParameter("username"));
- response.sendRedirect("index.jsp");
- %>
checkLogin.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>Insert title here</title>
- </head>
- <body>
- <% if (session.getAttribute("username") == null) {
- response.sendRedirect("login.jsp");
- }%>
- </body>
- </html>
注:以上三個jsp頁面主要實現用戶登錄的相應功能。
deploy.jsp
- <%@ page language="java" contentType="text/html; charset=UTF-8"
- pageEncoding="UTF-8"%>
- <%@ page import="java.util.*,org.jbpm.api.*,java.util.zip.*" %>
- <!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>Insert title here</title>
- </head>
- <body>
- <%
- ProcessEngine processEngine=Configuration.getProcessEngine();
- RepositoryService repositoryService=processEngine.getRepositoryService();
- repositoryService.createDeployment().addResourceFromClasspath("leave.jpdl.xml").deploy();
- //ZipInputStream zis = new ZipInputStream(this.getClass()
- // .getResourceAsStream("/leave.zip"));
- //repositoryService.createDeployment()
- // .addResourcesFromZipInputStream(zis).deploy();
- response.sendRedirect("index.jsp");
- %>
- </body>
- </html>
注:此處實現了流程定義的發佈
request.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>Insert title here</title>
- </head>
- <body>
- <fieldset>
- <legend>申請</legend>
- <form action="submit.jsp" method="post">
- <input type="hidden" name="taskId" value="${param.id}">
- 申請人:<input type="text" name="owner" value="${sessionScope['username']}"/><br/>
- 請假時間:<input type="text" name="day" value=""/><br/>
- 請假原因:<textarea name="reason"></textarea><br/>
- <input type="submit"/>
- </form>
- </fieldset>
- </body>
- </html>
submit.jsp
- <%@ page language="java" contentType="text/html; charset=UTF-8"
- pageEncoding="UTF-8"%>
- <%@ page import="java.util.*,org.jbpm.api.*" %>
- <!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>Insert title here</title>
- </head>
- <body>
- <%
- ProcessEngine processEngine = Configuration.getProcessEngine();
- TaskService taskService = processEngine.getTaskService();
- String taskId = request.getParameter("taskId");
- String owner = request.getParameter("owner");
- int day = Integer.parseInt(request.getParameter("day"));
- String reason = request.getParameter("reason");
- //將用戶請求的時間和原因作爲流程變量傳遞流程
- Map map = new HashMap();
- map.put("day", day);
- map.put("reason", reason);
- taskService.completeTask(taskId, map);
- response.sendRedirect("index.jsp");
- %>
- </body>
- </html>
注:這兩個jsp頁面實現了普通用戶申請請假的功能。值得說明的是在submit.jsp中的如下兩句代碼:
- Map map = new HashMap();
- map.put("day", day);
- map.put("reason", reason);
- taskService.completeTask(taskId, map);
將用戶申請的請假天數和請假原因作爲流程變量保存在數據庫中,同時實現了對"申請"節點task任務的完成。
manager.jsp
- <%@ page language="java" contentType="text/html; charset=UTF-8"
- pageEncoding="UTF-8"%>
- <%@page import="org.jbpm.api.*,org.jbpm.api.task.*" %>
- <%
- ProcessEngine processEngine = Configuration.getProcessEngine();
- TaskService taskService = processEngine.getTaskService();
- String taskId = request.getParameter("id");
- Task task = taskService.getTask(taskId);
- %>
- <!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>Insert title here</title>
- </head>
- <body>
- <fieldset>
- <legend>經理審批</legend>
- <form action="submit_manager.jsp">
- <input type="hidden" name="taskId" value="${param.id}">
- 申請人:<%=taskService.getVariable(taskId, "owner") %><br/>
- 請假時間:<%=taskService.getVariable(taskId, "day") %><br/>
- 請假原因:<%=taskService.getVariable(taskId, "reason") %><br/>
- <input name="result" type="submit" value="批准"/><input name="result" type="submit" value="駁回"/>
- </form>
- </fieldset>
- </body>
- </html>
- <%@ page language="java" contentType="text/html; charset=UTF-8"
- pageEncoding="UTF-8"%>
- <%@ page import="java.util.*,org.jbpm.api.*" %>
- <!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>Insert title here</title>
- </head>
- <body>
- <%
- ProcessEngine processEngine = Configuration.getProcessEngine();
- TaskService taskService = processEngine.getTaskService();
- String taskId = request.getParameter("taskId");
- String result = request.getParameter("result");
- result = new String(result.getBytes("ISO-8859-1"), "UTF-8");
- taskService.completeTask(taskId, result);
- response.sendRedirect("index.jsp");
- %>
- </body>
- </html>
注:這兩個頁面實現了“經理審批”節點的task,此處要說明的對於流程圖中批准和駁回的實現,我們主要是使用taskService.completeTask(tsaskId,result);函數來實現,此處的result並不是流程變量而是我們所要選擇的流程路徑。對於TaskService.completeTask函數我這裏做如下不規範說明:
該函數包含三個參數,一個必備參數:taskId,即流程ID;兩個可選參數:流程變量參數Map類型和後繼路徑選擇參數String類型(應該與流程定義中的路徑transaction名相同)。
boss.jsp
- <%@ page language="java" contentType="text/html; charset=UTF-8"
- pageEncoding="UTF-8"%>
- <%@page import="org.jbpm.api.*,org.jbpm.api.task.*" %>
- <%
- ProcessEngine processEngine = Configuration.getProcessEngine();
- TaskService taskService = processEngine.getTaskService();
- String taskId = request.getParameter("id");
- Task task = taskService.getTask(taskId);
- %>
- <!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>Insert title here</title>
- </head>
- <body>
- <fieldset>
- <legend>老闆審批</legend>
- <form action="submit_boss.jsp">
- <input type="hidden" name="taskId" value="${param.id}">
- 申請人:<%=taskService.getVariable(taskId, "owner") %><br/>
- 請假時間:<%=taskService.getVariable(taskId, "day") %><br/>
- 請假原因:<%=taskService.getVariable(taskId, "reason") %><br/>
- <input name="result" type="submit" value="提交審批內容"/>
- </form>
- </fieldset>
- </body>
- </html>
submit_boss.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>Insert title here</title>
- </head>
- <body>
- <%@page import="java.util.*,org.jbpm.api.*"%>
- <%
- ProcessEngine processEngine = Configuration.getProcessEngine();
- TaskService taskService = processEngine.getTaskService();
- String taskId = request.getParameter("taskId");
- taskService.completeTask(taskId);
- response.sendRedirect("index.jsp");
- %>
- </body>
- </html>
至此爲止請假流程web應用的最基本的功能已經實現。
5、程序運行結果