用户登录
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<html lang="en">
<head>
<title>Activiti学习</title>
<style type="text/css">
<!--
body {
margin-left: 0px;
margin-top: 0px;
margin-right: 0px;
margin-bottom: 0px;
}
.inputsize{ width:120px; height:18px; }
-->
</style>
<link href="<%=basePath%>css/css.css" rel="stylesheet" type="text/css" />
</head>
<body>
<form action="<%=basePath%>login/save" method="post" name="fom" id="fom">
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr>
<td height="147" background="<%=basePath%>images/top02.gif"><img src="<%=basePath%>images/top03.gif" width="776" height="147" /></td>
</tr>
</table>
<table width="562" border="0" align="center" cellpadding="0" cellspacing="0" class="right-table03">
<tr>
<td width="221"><table width="95%" border="0" cellpadding="0" cellspacing="0" class="login-text01">
<tr>
<td><table width="100%" border="0" cellpadding="0" cellspacing="0" class="login-text01">
<tr>
<td align="center"><img src="<%=basePath%>images/ico13.gif" width="107" height="97" /></td>
</tr>
<tr>
<td height="40" align="center"> </td>
</tr>
</table></td>
<td><img src="<%=basePath%>images/line01.gif" width="5" height="292" /></td>
</tr>
</table></td>
<td><table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr>
<td width="31%" height="35" class="login-text02">用户名 <br /></td>
<td width="69%"><input name="username" type="text" class="inputsize"/></td>
</tr>
<tr>
<td height="35" class="login-text02">密码 <br /></td>
<td><input name="password" type="password" class="inputsize" /></td>
</tr>
<tr>
<td height="35"> </td>
<td><input name="Submit2" type="submit" class="right-button01" value="确认登录" onClick="window.location='index.html'" />
<input name="Submit232" type="submit" class="right-button02" value="重置" /></td>
</tr>
</table></td>
</tr>
</table>
</form>
</body>
</html>
package com.xquant.platform.test.activiti.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.activiti.engine.IdentityService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
@RequestMapping(value = "/login")
public class LoginController {
@Autowired
private IdentityService identityService;
@RequestMapping(value = "/")
public String add() {
return "login";
}
@RequestMapping(value = "/out")
public String out(HttpSession session) {
session.removeAttribute("userId");
return "login";
}
@RequestMapping(value = "/save",method=RequestMethod.POST)
public String save(@RequestParam(value="username") String username, @RequestParam(value="password") String password, HttpSession session,HttpServletRequest request) {
session.removeAttribute("userId");
boolean canPass = identityService.checkPassword(username, password);
if (canPass){
session.setAttribute("userId", username);
}else{
return "redirect:/login/";
}
return "redirect:/form/list";
}
}
启动之后,用户可以通过http://localhost:8080/login/进行登录(用户必须在ACT_ID_USER表中已经存在)
BPMN以及第一个流程
创建一个流程定义文件reimbursement.bpmn
。对应文件路径如下图所示
此处将每个userTask修改了代理人为同一个admin,然后通过admin发起的话,所有的流程都可以由admin来操作了。
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.zioer.com/reimbursement">
<process id="reimbursement" name="费用报销" isExecutable="true">
<documentation>公司费用报销简易流程</documentation>
<startEvent id="startevent1" name="Start" activiti:initiator="startUserId">
<extensionElements>
<activiti:formProperty id="fee" name="费用" type="long" required="true"></activiti:formProperty>
<activiti:formProperty id="note" name="说明" type="string"></activiti:formProperty>
</extensionElements>
</startEvent>
<!-- <userTask id="departmentApprove" name="部门领导审批" activiti:assignee="lee">-->
<userTask id="departmentApprove" name="部门领导审批" activiti:assignee="admin">
<extensionElements>
<activiti:formProperty id="fee" name="费用" type="long" writable="false"></activiti:formProperty>
<activiti:formProperty id="note" name="说明" type="string" writable="false"></activiti:formProperty>
<activiti:formProperty id="bmyj" name="部门意见" type="string"></activiti:formProperty>
</extensionElements>
</userTask>
<sequenceFlow id="flow1" sourceRef="startevent1" targetRef="departmentApprove"></sequenceFlow>
<!-- <userTask id="reimburseApprove" name="财务部门审批" activiti:assignee="lobby">-->
<userTask id="reimburseApprove" name="财务部门审批" activiti:assignee="admin">
<extensionElements>
<activiti:formProperty id="fee" name="费用" type="long" writable="false"></activiti:formProperty>
<activiti:formProperty id="refee" name="核实费用" type="long" required="true"></activiti:formProperty>
<activiti:formProperty id="note" name="说明" type="string" writable="false"></activiti:formProperty>
<activiti:formProperty id="bmyj" name="部门意见" type="string" writable="false"></activiti:formProperty>
<activiti:formProperty id="bzhu" name="备注" type="string"></activiti:formProperty>
</extensionElements>
</userTask>
<sequenceFlow id="flow2" sourceRef="departmentApprove" targetRef="reimburseApprove"></sequenceFlow>
<userTask id="usertask1" name="申请人确认" activiti:assignee="${startUserId}">
<extensionElements>
<activiti:formProperty id="fee" name="费用" type="long" writable="false"></activiti:formProperty>
<activiti:formProperty id="refee" name="核实费用" type="long" writable="false"></activiti:formProperty>
<activiti:formProperty id="note" name="说明" type="string" writable="false"></activiti:formProperty>
<activiti:formProperty id="bmyj" name="部门意见" type="string" writable="false"></activiti:formProperty>
<activiti:formProperty id="bzhu" name="备注" type="string" writable="false"></activiti:formProperty>
</extensionElements>
</userTask>
<sequenceFlow id="flow3" sourceRef="reimburseApprove" targetRef="usertask1"></sequenceFlow>
<endEvent id="endevent2" name="End"></endEvent>
<sequenceFlow id="flow5" sourceRef="usertask1" targetRef="endevent2"></sequenceFlow>
</process>
<bpmndi:BPMNDiagram id="BPMNDiagram_reimbursement">
<bpmndi:BPMNPlane bpmnElement="reimbursement" id="BPMNPlane_reimbursement">
<bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1">
<omgdc:Bounds height="35.0" width="35.0" x="80.0" y="160.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="departmentApprove" id="BPMNShape_departmentApprove">
<omgdc:Bounds height="55.0" width="105.0" x="160.0" y="150.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="reimburseApprove" id="BPMNShape_reimburseApprove">
<omgdc:Bounds height="55.0" width="105.0" x="310.0" y="150.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="usertask1" id="BPMNShape_usertask1">
<omgdc:Bounds height="55.0" width="105.0" x="460.0" y="150.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="endevent2" id="BPMNShape_endevent2">
<omgdc:Bounds height="35.0" width="35.0" x="610.0" y="160.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1">
<omgdi:waypoint x="115.0" y="177.0"></omgdi:waypoint>
<omgdi:waypoint x="160.0" y="177.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">
<omgdi:waypoint x="265.0" y="177.0"></omgdi:waypoint>
<omgdi:waypoint x="310.0" y="177.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3">
<omgdi:waypoint x="415.0" y="177.0"></omgdi:waypoint>
<omgdi:waypoint x="460.0" y="177.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow5" id="BPMNEdge_flow5">
<omgdi:waypoint x="565.0" y="177.0"></omgdi:waypoint>
<omgdi:waypoint x="610.0" y="177.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>
首先点击新增流程
@RequestMapping(value = "/add")
public String add(Model model, HttpSession session) {
// 首先是安全认证 如果用户没有登录 则返回登录页面
if (session.getAttribute("userId") == null) {
return "redirect:/login/";
}
// 启动指定流程 通过latestVersion指定只获取最新版本
// 因为用户在实际使用中,可能会对同一个流程修改后再进行部署 这样就会存在多个版本
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
.processDefinitionKey("reimbursement").latestVersion().singleResult();
// 表示启动指定流程的实例 id的格式如reimbursement:1:37508
StartFormData startFormData = formService.getStartFormData(processDefinition.getId());
// 获取流程实例的FormProperty 通过activiti:formProperty定义的
List<FormProperty> formProperties = startFormData.getFormProperties();
model.addAttribute("list", formProperties);
model.addAttribute("formData", startFormData);
return "reimbursement_start";
}
然后进入到reimbursement_start.jsp当中,这里list当中包含需要填写的参数,而这些参数在前面流程定义中由activiti:formProperty
来指定的。
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<html lang="en">
<head>
<title>费用报销-新增</title>
<link rel="stylesheet" rev="stylesheet" href="<%=basePath%>css/style.css" type="text/css" media="all" />
<script type="text/javascript" src="<%=basePath%>js/My97DatePicker/WdatePicker.js"></script>
<script language=JavaScript>
function save(){
document.getElementById("form").submit();
}
</script>
</head>
<body>
<form action="start/save" method="post" name="form" id="form">
<div class="MainDiv">
<table width="60%" border="0" cellpadding="0" cellspacing="0" class="CContent">
<tr>
<th class="tablestyle_title" >费用报销-新增</th>
</tr>
<tr>
<td class="CPanel">
<table border="0" cellpadding="0" cellspacing="0" style="width:100%">
<TR>
<TD width="100%">
<fieldset style="height:100%;">
<legend>内容填写</legend>
<table border="0" cellpadding="2" cellspacing="1" style="width:100%">
<c:forEach items="${list}" var="var" varStatus="vs">
<tr>
<c:if test="${ var.getType().getName() =='string' || var.getType().getName() =='long'}">
<td nowrap align="right" width="13%">${var.getName()}</td>
<td><input type='text' id='${var.getId()}' name='${var.getId()}' value='${var.getValue()}' /></td>
</c:if>
</tr>
</c:forEach>
</table>
</fieldset>
</TD>
</TR>
</TABLE>
</td>
</tr>
<tr>
<TD colspan="2" align="center" height="50px">
<input type="button" name="Submit" value="保存" class="button" onclick="save();"/>
<input type="button" name="Submit2" value="返回" class="button" onclick="window.history.go(-1);"/>
</TD>
</tr>
</table>
</div>
</form>
</body>
</html>
jsp中会遍历FormProperty列表并进行渲染,渲染之后的结果如下所示
用户填写,并保存
/**
* 提交启动流程
*/
@RequestMapping(value = "/start/save")
public String saveStartForm(Model model, HttpServletRequest request, HttpSession session) {
String userId = session.getAttribute("userId") == null ? null : session.getAttribute("userId").toString();
if (userId == null) {
return "redirect:/login/";
}
// 用于获取页面传递的值
Map formProperties = pageData(request);
ProcessInstance processInstance = null;
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
.processDefinitionKey("reimbursement").latestVersion().singleResult();
String processDefinitionId = processDefinition.getId();
try {
// 设置流程发起人
identityService.setAuthenticatedUserId(userId);
// 启动Activiti内置Form流程
processInstance = formService.submitStartFormData(processDefinitionId, formProperties);
} finally {
identityService.setAuthenticatedUserId(null);
}
// 重定向 到列表页面
return "redirect:/form/list";
}
启动任务,并提交,这里比较关键的是设置提交人以及提交的参数
然后查询当前用户待处理的任务,由于我们将代理人都设置为了admin。所以可以查出刚才提交的任务
@RequestMapping(value = "/list")
public String list(Model model, HttpSession session) {
String userId = session.getAttribute("userId") == null ? null : session.getAttribute("userId").toString();
if (userId == null) {
return "redirect:/login/";
}
List<Task> tasks = new ArrayList<Task>();
//获得当前用户的待办以及分配的任务
tasks = taskService.createTaskQuery().taskCandidateOrAssigned(userId).active().orderByTaskId().desc().list();
model.addAttribute("list", tasks);
return "reimbursement_list";
}
将任务通过reimbursement_list来进行渲染
<%@ page language="java" import="java.util.*" contentType="text/html; charset=utf8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://"
+ request.getServerName() + ":" + request.getServerPort()
+ path + "/";
%>
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf8" />
<title>Zioer-Activiti示例</title>
<link rel="stylesheet" rev="stylesheet" href="<%=basePath%>css/style.css" type="text/css" media="all" />
<script language=JavaScript>
function link(){
document.location.href="add";
}
function link2(){
document.location.href="<%=basePath%>/login/out";
}
</script>
</head>
<body class="ContentBody">
<form action="add" method="post" name="fom" id="fom">
<div class="MainDiv">
<table width="60%" border="0" cellpadding="0" cellspacing="0" class="CContent">
<tr>
<th class="tablestyle_title" >Activiti示例-待办工作</th>
</tr>
<tr>
<td class="CPanel">
<table id="subtree1" style="DISPLAY: " width="100%" border="0" cellspacing="0" cellpadding="0">
<tr>
<td><table width="95%" border="0" align="center" cellpadding="0" cellspacing="0">
<tr>
<td height="20">
<span class="newfont07">
<input name="Submit1" type="button" class="right-button08" value="新增流程" onclick="link();"/>
</span>
<span class="newfont07">
<input name="Submit1" type="button" class="right-button08" value="退出" onclick="link2();"/>
</span>
</td>
</tr>
<tr>
<td height="40" class="font42">
<table width="100%" border="0" cellpadding="4" cellspacing="1" bgcolor="#FFFFEE" class="newfont03">
<tr class="CTitle" >
<td height="22" colspan="5" align="center" style="font-size:16px">当前用户办理工作列表</td>
</tr>
<tr bgcolor="#EEEEEE">
<td width="10%" height="30">任务ID</td>
<td width="20%">当前节点</td>
<td width="20%">办理人</td>
<td width="36%">创建时间</td>
<td width="17%">操作</td>
</tr>
<c:forEach items="${list}" var="var" varStatus="vs">
<tr <c:if test="${vs.count%2==0}">bgcolor="#AAAABB"</c:if> align="left" >
<td >${var.id}</td>
<td height="30">${var.name}</td>
<td >${var.assignee}</td>
<td ><fmt:formatDate value="${var.createTime}" type="both"/></td>
<td ><a href="<%=basePath%>form/startform/${var.id}">办理</a></td>
</tr>
</c:forEach>
</table></td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
</div>
</form>
</body>
</html>
点击任务的操作按钮(办理),会将任务ID传送到后台,获取对应的表格信息
/**
* 初始化启动流程,读取启动流程的表单字段来渲染start form
*/
@RequestMapping(value = "/startform/{taskId}")
public String StartTaskForm(@PathVariable("taskId") String taskId, Model model, HttpSession session) throws Exception {
String userId = session.getAttribute("userId") == null ? null : session.getAttribute("userId").toString();
if (userId == null) {
return "redirect:/login/";
}
// 获取指定任务的taskFormData taskId会随着任务进行而变化
TaskFormData taskFormData = formService.getTaskFormData(taskId);
// 然后再获取FormProperty
List<FormProperty> formProperties = taskFormData.getFormProperties();
String startUserId = (String) taskService.getVariable(taskId, "startUserId");
model.addAttribute("formData", taskFormData);
model.addAttribute("startUserId", startUserId);
model.addAttribute("list", formProperties);
return "reimbursement_edit";
}
接下来再通过jsp页面(reimbursement_edit)渲染
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<html lang="en">
<head>
<title>费用报销-审批</title>
<link rel="stylesheet" rev="stylesheet" href="<%=basePath%>css/style.css" type="text/css" media="all" />
<script type="text/javascript" src="<%=basePath%>js/My97DatePicker/WdatePicker.js"></script>
<script language=JavaScript>
function save(){
document.getElementById("form").submit();
}
</script>
</head>
<body>
<form action="save/${ formData.getTask().getId()}" method="post" name="form" id="form">
<div class="MainDiv">
<table width="60%" border="0" cellpadding="0" cellspacing="0" class="CContent">
<tr>
<th class="tablestyle_title" >费用报销-审批</th>
</tr>
<tr>
<td class="CPanel">
<table border="0" cellpadding="0" cellspacing="0" style="width:100%">
<TR>
<TD width="100%">
<fieldset style="height:100%;">
<legend>内容填写</legend>
<table border="0" cellpadding="2" cellspacing="1" style="width:100%">
<tr>
<td nowrap align="right" width="13%">申请人</td>
<td>${startUserId}</td>
</tr>
<c:forEach items="${list}" var="var" varStatus="vs">
<tr>
<c:if test="${ var.getType().getName() =='string' || var.getType().getName() =='long' || var.getType().getName() ==null}">
<c:choose>
<c:when test="${ var.isWritable()}">
<td nowrap align="right" width="13%">${var.getName()}</td>
<td><input type='text' id='${var.getId()}' name='${var.getId()}' value='${var.getValue()}' /></td>
</c:when>
<c:otherwise>
<td nowrap align="right" width="13%">${var.getName()}</td>
<td>${var.getValue()}</td>
</c:otherwise>
</c:choose>
</c:if>
</tr>
</c:forEach>
</table>
</fieldset>
</TD>
</TR>
</TABLE>
</td>
</tr>
<tr>
<TD colspan="2" align="center" height="50px">
<input type="button" name="Submit" value="保存" class="button" onclick="save();"/>
<input type="button" name="Submit2" value="返回" class="button" onclick="window.history.go(-1);"/>
</TD>
</tr>
</table>
</div>
</form>
</body>
</html>
注意区分可写与不可写,这些都是在流程定义时定义好的
输入部门意见之后保存,又会进入任务提交
然后又是列表需要处理的任务
接下来又是财务审批,点击办理,将任务ID(42548)传递到后台查询表格参数并渲染
填写参数完成之后,再保存,又会进入到任务完成流程(当前任务Id=42548),
审批完成之后又会进入到当前用户待处理流程列表,可以看到任务ID已经由42548变为了42554了。
继续点击办理,然后提交,查询任务列表…,直到流程结束。