分享关于JBPM之请假流程Demo
紧接着昨天的demo完整的实现整个请假流程,大致的流程是这样的:员工提交请假申请,然后项目经理审批,如果项目经理审批通过且请假天数小于3天,则直接整个请假流程结束,如果项目经理审批通过且请假天数大于3天,则还需要总经理审批,总经理不管审批通过还是不通过,整个请假流程都结束。当然项目经理也可以审批不通过,此时员工可以再次提交请假申请,如此循环......
用jpdl.xml表示出来如图:

leave.jpdl.xml内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<process name="leave" xmlns="">
<start g="113,-2,48,48" name="start1">
<transition g="-47,-17" name="申请" to="员工申请"/>
</start>
<task assignee="#{owner}" g="100,68,92,52" name="员工申请" form="LeaveServlet?opt=toApply">
<transition g="-74,-8" name="项目经理审批" to="项目经理审批"/>
</task>
<task assignee="manager" g="100,155,92,52" name="项目经理审批" form="LeaveServlet?opt=toManagerApprove">
<transition g="-31,-6" name="批准" to="exclusive1"/>
<transition g="332,180;331,95:5,-10" name="驳回" to="员工申请"/>
</task>
<decision expr="#{day > 3 ? '总经理审批':'结束'}" g="117,226,48,48" name="exclusive1">
<transition g="341,246:-130,8" name="总经理审批" to="总经理审批"/>
<transition g="-28,-8" name="结束" to="end1"/>
</decision>
<task assignee="boss" g="298,301,92,52" name="总经理审批" form="LeaveServlet?opt=toBossApprove">
<transition g="346,384:-114,-12" name="总经理批准" to="end1"/>
</task>
<end g="118,364,48,48" name="end1"/>
</process>
其中绿色标识的部分表示将任务分配给哪个角色,这里为了简单,项目经理和总经理的角色的用户名是写死的,只有员工用户名是绑定在owner这个变量上,
其中红色部分表示该任务对应的后台处理程序地址,opt参数是为了区分执行的是哪项操作。
LeaveServlet主要用来处理流程的各种操作,如发布新流程,删除流程、显示流程定义,流程实例、待办任务列表等等。
代码如下:
package servlet;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import entity.Process;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.jbpm.api.Configuration;
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.TaskService;
import org.jbpm.api.task.Task;
/**
* @author Lanxiaowei
* @createTime 2011-12-24 下午04:09:55
*/
public class LeaveServlet extends HttpServlet {
private ProcessEngine processEngine = null;
private RepositoryService repositoryService;
private ExecutionService executionService;
private TaskService taskService;
@Override
public void init() throws ServletException {
super.init();
processEngine = Configuration.getProcessEngine();
repositoryService = processEngine.getRepositoryService();
executionService = processEngine.getExecutionService();
taskService = processEngine.getTaskService();
}
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取当前的操作标识符
String operate = request.getParameter("opt");
//从Session中取出当前用户名
String username = (String)request.getSession().getAttribute("username");
//发布新的流程定义
if("deploy".equals(operate)){
repositoryService.createDeployment().addResourceFromClasspath("leave.jpdl.xml").deploy();
} else if("delete".equals(operate)){ //删除流程定义
String id = request.getParameter("id");
if(null != id && !"".equals(id)){
try {
repositoryService.deleteDeploymentCascade(id);
} catch (Exception e) {
request.setAttribute("infor", "该流程定义已删除,请勿重复刷新!");
}
}
} else if("start".equals(operate)){ //启动流程定义
String id = request.getParameter("id");
//根据流程定义id来启动一个流程定义,并传递参数
if(null != id && !"".equals(id)){
Map map = new HashMap();
map.put("owner", username);
executionService.startProcessInstanceById(id,map);
}
} else if("apply".equals(operate)){ //处理申请
String taskId = request.getParameter("taskId");
if(null != taskId && !"".equals(taskId)){
String owner = request.getParameter("owner");
int day = Integer.parseInt(request.getParameter("day"));
String reason = request.getParameter("reason");
Map map = new HashMap();
map.put("owner", owner);
map.put("day", day);
map.put("reason", reason);
try {
taskService.setVariables(taskId,map);
taskService.completeTask(taskId);
} catch (Exception e) {
e.printStackTrace();
request.setAttribute("infor", "该流程已完成,请勿重复刷新!");
}
}
} else if("toApply".equals(operate)){ //跳至申请页面
String id = request.getParameter("id");
response.sendRedirect("apply.jsp?id=" + id);
return;
} else if("toManagerApprove".equals(operate)){ //跳至项目经理审批页面
String taskId = request.getParameter("id");
Task task = taskService.getTask(taskId);
request.setAttribute("taskId", taskId);
request.setAttribute("owner", taskService.getVariable(taskId, "owner"));
request.setAttribute("day", taskService.getVariable(taskId, "day"));
request.setAttribute("reason", taskService.getVariable(taskId, "reason"));
request.getRequestDispatcher("/managerApprove.jsp").forward(request, response);
return;
} else if("toBossApprove".equals(operate)){ //跳至总经理审批页面
String taskId = request.getParameter("id");
Task task = taskService.getTask(taskId);
request.setAttribute("taskId", taskId);
request.setAttribute("owner", taskService.getVariable(taskId, "owner"));
request.setAttribute("day", taskService.getVariable(taskId, "day"));
request.setAttribute("reason", taskService.getVariable(taskId, "reason"));
request.getRequestDispatcher("/bossApprove.jsp").forward(request, response);
return;
} else if("managerApprove".equals(operate)){ //项目经理审批
String taskId = request.getParameter("taskId");
String result = request.getParameter("result");
result = new String(result.getBytes("ISO-8859-1"),"UTF-8");
taskService.completeTask(taskId,result);
} else if("bossApprove".equals(operate)){ //总经理审批
String taskId = request.getParameter("taskId");
taskService.completeTask(taskId);
}
//流程定义列表
List<ProcessDefinition> pds = repositoryService.createProcessDefinitionQuery().list();
//流程实例列表
List<Process> pis = new ArrayList<Process>();
List<ProcessInstance> processInstances = executionService.createProcessInstanceQuery().list();
for (ProcessInstance pi : processInstances) {
Process p = new Process(pi.getId(),pi.findActiveActivityNames().toString(),pi.getState());
pis.add(p);
}
//当前用户的待办任务列表
List<Task> tks = taskService.findPersonalTasks(username);
request.setAttribute("pds", pds);
request.setAttribute("pis", pis);
request.setAttribute("tks", tks);
request.getRequestDispatcher("/index.jsp").forward(request, response);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
index.jsp页面就是流程管理界面:
效果如图:

代码如下:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ include file="/checkLogin.jsp" %>
<%@ page isELIgnored="false" %>
<%@ taglib uri="/jstl" prefix="c" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
request.setAttribute("basepath",basePath);
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>请假流程管理</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="请假流程管理">
<link rel="stylesheet" type="text/css" href="css/styles.css"/>
</head>
<body>
<script type="text/javascript">
<c:if test="${not empty infor}">
alert("${infor}");
</c:if>
</script>
<center>
<h2>请假流程管理Demo</h2>
</center>
<span>
<input type="button" value="发布新流程" onclick="window.location='${basepath}LeaveServlet?opt=deploy';"/>
</span><br/>
<span style="font-size:12px;">当前用户:<font size="2" color="red">${sessionScope['username']}</font>
<a href="javascript:void(0);" onclick="javascript:window.location='${basepath}login.jsp';return false;">重新登录</a></span>
<div id="test">
<!-- 流程定义列表begin -->
<table border="1" cellspacing="0" cellpadding="0">
<caption><strong>流程定义</strong></caption>
<tr>
<td>id</td>
<td>name</td>
<td>key</td>
<td>version</td>
<td>deploymentId</td>
<td>operation</td>
</tr>
<c:forEach items="${pds}" var="pd">
<tr>
<td>${pd.id}</td>
<td>${pd.name}</td>
<td>${pd.key}</td>
<td>${pd.version}</td>
<td>${pd.deploymentId}</td>
<td>
<a href="javascript:void(0);" onclick="javascript:window.location='${basepath}LeaveServlet?opt=delete&id=${pd.deploymentId}';return false;" >remove</a>
<a href="javascript:void(0);" onclick="javascript:window.location='${basepath}LeaveServlet?opt=start&id=${pd.id}';return false;" >start</a>
</td>
</tr>
</c:forEach>
</table>
<!-- 流程定义列表end -->
<br/>
<!-- 流程实例begin -->
<table border="1" cellspacing="0" cellpadding="0">
<caption><strong>流程实例</strong></caption>
<tr>
<td>id</td>
<td>activity</td>
<td>state</td>
</tr>
<c:forEach items="${pis}" var="pi">
<tr>
<td>${pi.id}</td>
<td>${pi.name}</td>
<td>${pi.state}</td>
</tr>
</c:forEach>
</table>
<!-- 流程实例end -->
<br/>
<!-- 待办任务begin -->
<table border="1" cellspacing="0" cellpadding="0">
<caption><strong>待办任务</strong></caption>
<tr>
<td>id</td>
<td>name</td>
<td>operation</td>
</tr>
<c:forEach items="${tks}" var="tk">
<tr>
<td>${tk.id}</td>
<td>${tk.name}</td>
<td>
<a href="javascript:void(0);" onclick="javascript:window.location='${basepath}${tk.formResourceName}&id=${tk.id}';return false;" >view</a>
</td>
</tr>
</c:forEach>
</table>
<!-- 待办任务end -->
</div>
</body>
</html>
登录页面效果如图:

简单起见,就只有一个用户名,代码如下:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ page isELIgnored="false" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
request.setAttribute("basepath",basePath);
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>用户登录</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<link rel="stylesheet" type="text/css" href="css/styles.css"/>
<script type="text/javascript" src="js/trim.js"></script>
<script type="text/javascript">
function checkForm(){
var username = document.loginForm.username;
if(username.value && username.value.length > 0 && username.value.Trim().length > 0){
return true;
}
alert("请输入用户名");
username.focus();
return false;
}
</script>
</head>
<body>
<div class="center">
<fieldset>
<legend> 用户登录 </legend>
<form name="loginForm" action="${basepath}loginServlet" method="post" onsubmit="return checkForm()">
用户名:<input type="text" name="username"/><br/>
<input type="submit" value="登录"/>
</form>
</fieldset>
</div>
</body>
</html>
用户登录后点击按钮发布新流程,界面效果如图:

流程尚未启动,所以流程实例列表和待办任务列表为空,点击 start链接启动一个流程定义后效果如图:

如图我们发现,点击start启动流程定义后,流程自动按照我们的流程定义xml文件中事先设计好的步骤从开始流转到员工申请了,而员工的待办任务也自动有了一条任务,点击view页面自动跳转到该task节点的form属性设定的后台处理程序链接地址,效果如图:

显示的员工请假申请需要填写的表单,员工填写表单,然后就自动流转到项目经理审批,

员工提交表单后,员工的待办任务就为空表明员工的任务完成,而此时流程也正确的流转到项目经理审批,我们登录项目经理的帐号查看验证:

因为我们在jpdl.xml中是把项目经理审批这个任务分配给了manager这个用户,所以我们这里直接用manager登录测试,登录后:

此时显示项目经理有一条待办任务,点击view就跳转到项目经理审批页面,这个跳转链接也是在task的form属性中绑定的:

由于表单填写的是请假一天,所以如果项目经理审批通过,则整个流程结束,如果项目经理驳回申请,则流程状态又会回到员工申请,登录用户查看测试:

项目经理驳回后流程回退到员工申请,登录员工帐号查看:

此时员工待办任务里又出现了一条员工申请待办任务,流程也正确回退到员工申请状态,当然员工继续点击view又可以重新填写表单申请请假,那流程又按刚才的步骤流转进行下去,如果请假天数大于3天,会有一个流程分支,此时还需要总经理审批,测试效果如图:

然后登录项目经理帐号:

登录后:

点击view开始审批:

点击批准后,由于请假天数大于3天,项目经理待办任务完成,进入总经理审批流程:

这个大于3天的条件控制是在jpdl.xml中通过表达式限定的:

然后用总经理帐号登录测试:

登录后:

这时候总经理点击view就进去了总经理审批页面,总经理审批通过或者不通过流程都将结束。


批准后流程实例列表为空,表明整个流程结束:

到此整个请假流程就算走通了,下一步就要准备研究如何将JBPM4.4和SSH进行整合,o(∩_∩)o !今天到此为止。
本文来源 我爱IT技术网 http://www.52ij.com/jishu/88.html 转载请保留链接。
- 评论列表(网友评论仅供网友表达个人看法,并不表明本站同意其观点或证实其描述)
-
