SpringBoot整合activiti5-外置表单
作者:互联网
所谓的外置表单方式,就是先把表单内容写好并保存为.form模板文件,然后配置流程中每个节点的Form Key属性指定这个模板文件。
创建start.form
<table border="0" cellpadding="2" cellspacing="1" style="width:100%">
<tr>
<td nowrap align="right" width="13%">费用</td>
<td width="19%"><input type='text' id='fee' name='fee' value='' /></td>
<td width="13%" align="right" nowrap>费用类型</td>
<td width="55%"><select id="type" name="type">
<option value="差旅费">差旅费</option>
<option value="书报费">书报费</option>
<option value="会议费">会议费</option>
<option value="其他费">其他费</option>
</select></td>
</tr>
<tr>
<td nowrap align="right">发生日期</td>
<td colspan="3"><input type='text' id='feedate' name='feedate' value='' onClick="WdatePicker()"/></td>
</tr>
<tr>
<td nowrap align="right" width="13%">说明</td>
<td colspan="3"><textarea id='note' name='note' rows="5" cols="50"></textarea></td>
</tr>
</table>
创建conform1.form
<table border="0" cellpadding="2" cellspacing="1" style="width:100%">
<tr>
<td nowrap align="right" width="13%">申请人</td>
<td colspan="3">${startUserId}</td>
</tr>
<tr>
<td nowrap align="right" width="13%">费用</td>
<td width="19%">${fee}</td>
<td width="13%" align="right" nowrap>费用类型</td>
<td width="55%">${type}</td>
</tr>
<tr>
<td nowrap align="right">发生日期</td>
<td colspan="3">${feedate}</td>
</tr>
<tr>
<td nowrap align="right" width="13%">说明</td>
<td colspan="3">${note}</td>
</tr>
<tr>
<td nowrap align="right" width="13%">部门领导意见</td>
<td colspan="3"><textarea id='bmyj' name='bmyj' rows="5" cols="50"></textarea></td>
</tr>
</table>
创建conform2.form
<table border="0" cellpadding="2" cellspacing="1" style="width:100%">
<tr>
<td nowrap align="right" width="13%">申请人</td>
<td colspan="3">${startUserId}</td>
</tr>
<tr>
<td nowrap align="right" width="13%">费用</td>
<td width="19%">${fee}</td>
<td width="13%" align="right" nowrap>核实费用</td>
<td width="55%"><input type='text' id='refee' name='refee' value='' /></td>
</tr>
<tr>
<td nowrap align="right">发生日期</td>
<td>${feedate}</td>
<td width="13%" align="right" nowrap>费用类型</td>
<td width="55%">${type}</td>
</tr>
<tr>
<td nowrap align="right" width="13%">说明</td>
<td colspan="3">${note}</td>
</tr>
<tr>
<td nowrap align="right" width="13%">部门领导意见</td>
<td colspan="3">${bmyj}</td>
</tr>
<tr>
<td nowrap align="right" width="13%">财务部门意见</td>
<td colspan="3"><textarea id='bzhu' name='bzhu' rows="5" cols="50"></textarea></td>
</tr>
</table>
创建conform3.form
<table border="0" cellpadding="2" cellspacing="1" style="width:100%">
<tr>
<td nowrap align="right" width="13%">费用</td>
<td width="19%">${fee}</td>
<td width="13%" align="right" nowrap>核实费用</td>
<td width="55%">${refee}</td>
</tr>
<tr>
<td nowrap align="right">发生日期</td>
<td>${feedate}</td>
<td width="13%" align="right" nowrap>费用类型</td>
<td width="55%">${type}</td>
</tr>
<tr>
<td nowrap align="right" width="13%">说明</td>
<td colspan="3">${note}</td>
</tr>
<tr>
<td nowrap align="right" width="13%">部门领导意见</td>
<td colspan="3">${bmyj}</td>
</tr>
<tr>
<td nowrap align="right" width="13%">财务部门意见</td>
<td colspan="3">${bzhu}</td>
</tr>
</table>
创建流程定义文件reimbursement-1.bpmn
并将activiti:formKey指定为对应的form
<?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-1">
<process id="reimbursement-1" name="费用报销-1" isExecutable="true">
<startEvent id="startevent1" name="Start" activiti:initiator="startUserId" activiti:formKey="start.form"></startEvent>
<userTask id="usertask1" name="部门领导审批" activiti:assignee="${startUserId}" activiti:formKey="conform1.form"></userTask>
<sequenceFlow id="flow1" sourceRef="startevent1" targetRef="usertask1"></sequenceFlow>
<userTask id="usertask2" name="财务部门审批" activiti:assignee="${startUserId}" activiti:formKey="conform2.form"></userTask>
<sequenceFlow id="flow2" sourceRef="usertask1" targetRef="usertask2"></sequenceFlow>
<userTask id="usertask3" name="申请人确认" activiti:assignee="${startUserId}" activiti:formKey="conform3.form"></userTask>
<sequenceFlow id="flow3" sourceRef="usertask2" targetRef="usertask3"></sequenceFlow>
<endEvent id="endevent1" name="End"></endEvent>
<sequenceFlow id="flow4" sourceRef="usertask3" targetRef="endevent1"></sequenceFlow>
</process>
<bpmndi:BPMNDiagram id="BPMNDiagram_reimbursement-1">
<bpmndi:BPMNPlane bpmnElement="reimbursement-1" id="BPMNPlane_reimbursement-1">
<bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1">
<omgdc:Bounds height="35.0" width="35.0" x="180.0" y="190.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="usertask1" id="BPMNShape_usertask1">
<omgdc:Bounds height="55.0" width="105.0" x="260.0" y="180.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="usertask2" id="BPMNShape_usertask2">
<omgdc:Bounds height="55.0" width="105.0" x="410.0" y="180.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="usertask3" id="BPMNShape_usertask3">
<omgdc:Bounds height="55.0" width="105.0" x="560.0" y="180.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1">
<omgdc:Bounds height="35.0" width="35.0" x="710.0" y="190.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1">
<omgdi:waypoint x="215.0" y="207.0"></omgdi:waypoint>
<omgdi:waypoint x="260.0" y="207.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">
<omgdi:waypoint x="365.0" y="207.0"></omgdi:waypoint>
<omgdi:waypoint x="410.0" y="207.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3">
<omgdi:waypoint x="515.0" y="207.0"></omgdi:waypoint>
<omgdi:waypoint x="560.0" y="207.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow4" id="BPMNEdge_flow4">
<omgdi:waypoint x="665.0" y="207.0"></omgdi:waypoint>
<omgdi:waypoint x="710.0" y="207.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>
外置表单和流程定义文件进行打包
存放在指定目录
并修改前面通过压缩包部署的代码指定文件路径
通过压缩包部署
可以看出,部署成功了。
编写控制层代码操作外置表单
package com.xquant.platform.test.activiti.controller;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.activiti.engine.FormService;
import org.activiti.engine.HistoryService;
import org.activiti.engine.IdentityService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricDetail;
import org.activiti.engine.impl.persistence.entity.HistoricProcessInstanceEntity;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.task.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping(value = "/keyform")
public class KeyformController {
@Autowired
private RepositoryService repositoryService;
@Autowired
private FormService formService;
@Autowired
private TaskService taskService;
@Autowired
private IdentityService identityService;
@Autowired
private HistoryService historyService;
@Autowired
private RuntimeService runtimeService;
@RequestMapping(value = "/add")
public String add(Model model,HttpSession session) {
if (session.getAttribute("userId") == null){
return "redirect:/login/";
}
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
.processDefinitionKey("reimbursement-1")
.latestVersion().singleResult();
Object startForm = formService.getRenderedStartForm(processDefinition.getId());
//String formkey = formService.getStartFormKey(processDefinition.getId());
model.addAttribute("formData", startForm);
return "reimbursement-1_start";
}
/**
* 提交启动流程
*/
@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);
ProcessDefinition processDefinition = repositoryService
.createProcessDefinitionQuery()
.processDefinitionKey("reimbursement-1")
.latestVersion().singleResult();
String processDefinitionId = processDefinition.getId();
try {
identityService.setAuthenticatedUserId(userId);
formService.submitStartFormData(processDefinitionId, formProperties);
} finally {
identityService.setAuthenticatedUserId(null);
}
return "redirect:/keyform/list";
}
@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).processDefinitionKey("reimbursement-1")
.active()
.orderByTaskId().desc().list();
model.addAttribute("list", tasks);
return "reimbursement-1_list";
}
/**
* 初始化启动流程,读取启动流程的表单字段来渲染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/";
}
Object taskForm = formService.getRenderedTaskForm(taskId);
String startUserId = (String) taskService.getVariable(taskId, "startUserId");
model.addAttribute("formData", taskForm);
model.addAttribute("taskId", taskId);
model.addAttribute("startUserId", startUserId);
return "reimbursement-1_edit";
}
/**
* 提交启动流程
*/
@RequestMapping(value = "/startform/save/{taskId}")
public String saveTaskForm(@PathVariable("taskId") String taskId,HttpSession session,HttpServletRequest request) {
String userId = session.getAttribute("userId") == null ? null : session.getAttribute("userId").toString();
if (userId == null){
return "redirect:/login/";
}
Map formProperties = PageData(request);
try {
identityService.setAuthenticatedUserId(userId);
formService.submitTaskFormData(taskId, formProperties);
} finally {
identityService.setAuthenticatedUserId(null);
}
return "redirect:/keyform/list";
}
@RequestMapping(value = "/hlist")
public String historylist(Model model,HttpSession session) {
String userId = session.getAttribute("userId") == null ? null : session.getAttribute("userId").toString();
if (userId == null){
return "redirect:/login/";
}
List<Map> hlist = new ArrayList<Map>();
List historylist = historyService.createHistoricProcessInstanceQuery()
.processDefinitionKey("reimbursement-1")
.startedBy(userId).list();
for (int i=0;i<historylist.size();i++){
Map<String, Object> map = new HashMap<String, Object>();
HistoricProcessInstanceEntity hpe = (HistoricProcessInstanceEntity) historylist.get(i);
map.put("id", hpe.getId());
map.put("startUserId", hpe.getStartUserId());
map.put("processInstanceId", hpe.getProcessInstanceId());
map.put("endTime", hpe.getEndTime());
map.put("startTime", hpe.getStartTime());
if (hpe.getEndTime() == null){
Task task = taskService.createTaskQuery().processInstanceId(hpe.getProcessInstanceId()).active().singleResult();
if (task != null){
map.put("name", task.getName());
}
}else{
map.put("name", "已完成");
}
hlist.add(map);
}
//获得当前用户的任务
model.addAttribute("list", hlist);
return "reimbursement_hlist";
}
@RequestMapping(value = "/hview/{pId}")
public String historyView(@PathVariable("pId") String pId,Model model,HttpSession session) {
String userId = session.getAttribute("userId") == null ? null : session.getAttribute("userId").toString();
if (userId == null){
return "redirect:/login/";
}
List<HistoricDetail> details = historyService
.createHistoricDetailQuery()
.processInstanceId(pId)
.orderByTime().asc()
.list();
model.addAttribute("list", details);
return "reimbursement_hview";
}
public Map PageData(HttpServletRequest request){
Map properties = request.getParameterMap();
Map returnMap = new HashMap();
Iterator entries = properties.entrySet().iterator();
Map.Entry entry;
String name = "";
String value = "";
while (entries.hasNext()) {
entry = (Map.Entry) entries.next();
name = (String) entry.getKey();
Object valueObj = entry.getValue();
if(null == valueObj){
value = "";
}else if(valueObj instanceof String[]){
String[] values = (String[])valueObj;
for(int i=0;i<values.length;i++){
value = values[i] + ",";
}
value = value.substring(0, value.length()-1);
}else{
value = valueObj.toString();
}
returnMap.put(name, value);
}
return returnMap;
}
}
通过http://localhost:8080/keyform/add发起访问
此时会查出外置表单
由于表单已经有了,所以jsp文件reimbursement-1_start.jsp
非常简单
<%@ 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 class="ContentBody">
<form action="start/save" method="post" name="form" id="form">
<div class="MainDiv">
<table width="90%" 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>
${formData}
</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>
输入数据之后点击保存
保存就会将数据发送到后台的控制层
用户提交完成之后,重定向并查询当前用户的任务。
通过reimbursement-1_list.jsp
渲染
<%@ 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>
</script>
</head>
<body class="ContentBody">
<form action="add" method="post" name="fom" id="fom">
<div class="MainDiv">
<table width="90%" border="0" cellpadding="0" cellspacing="0" class="CContent">
<tr>
<th class="tablestyle_title" >费用报销管理-待办工作</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="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%>keyform/startform/${var.id}">办理</a></td>
</tr>
</c:forEach>
</table></td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
</div>
</form>
</body>
</html>
点击办理,进入keyform/startform/
流程,获取外置表单
对应页面也非常简单,跟前面一样,因为主要的表单信息已经包含在外置表单当中了
<%@ 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/${ taskId}" 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>
${formData}
</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>
点击保存,又会进入到save方法,其实就是提交当前的流程了
后面的流程就基本差不多一致了。
标签:SpringBoot,userId,外置,activiti5,session,value,import,null,String 来源: https://blog.csdn.net/m0_37607945/article/details/115256505