目录
- 1、流程定义列表
- 2、部署流程资源
- 3、读取流程资源
- 4、删除部署的流程
- 5、读取流程启动表单
- 6、根据表单启动流程
- 7、获取待办任务
- 8、签收任务
- 9、读取任务表单
- 10、完成任务
- 11、保存审批意见
- 12、读取审批意见
- 13、更改任务属性
- 14、添加任务参与人
- 15、删除任务参与人
- 16、添加候选人、候选组
- 17、删除参与人、候选人及候选组
- 18、添加子任务
- 19、查询子任务及上级任务
- 20、查询历史任务
- 21、保存文件类型附件
- 22、保存URL类型附件
- 23、下载附件
- 24、删除附件
- 25、查询用户参与过的流程
- 26、查询已经结束的流程实例
- 27、查询历史流程实例相关信息
- 28、删除历史流程实例
- 29、流程跟踪
- 30、用户及组管理
- 31、作业控制
- 32、流程定义管理
1、流程定义列表
@RequestMapping(value = "/process-list")
public ModelAndView processList() {
ModelAndView mav = new ModelAndView("chapter5/process-list");
List<ProcessDefinition> processDefinitionList = repositoryService.createProcessDefinitionQuery().list();
mav.addObject("processDefinitionList", processDefinitionList);
return mav;
}
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<%@ include file="/common/global.jsp"%>
<%@ include file="/common/meta.jsp" %>
<%@ include file="/common/include-base-styles.jsp" %>
<title>已部署流程定义列表</title>
<script src="${ctx }/js/common/jquery.js" type="text/javascript"></script>
</head>
<body>
<c:if test="${not empty message}">
<div id="message" class="alert alert-success">${message}</div>
<!-- 自动隐藏提示信息 -->
<script type="text/javascript">
setTimeout(function() {
$('#message').hide('slow');
}, 5000);
</script>
</c:if>
<fieldset id="deployFieldset">
<legend>部署流程资源</legend>
<form action="${ctx }/chapter5/deploy" method="post" enctype="multipart/form-data" style="margin-top:1em;">
<input type="file" name="file" />
<input type="submit" value="Submit" class="btn" />
</form>
<hr class="soften" />
</fieldset>
<table width="100%" class="table table-bordered table-hover table-condensed">
<thead>
<tr>
<th>流程定义ID</th>
<th>部署ID</th>
<th>流程定义名称</th>
<th>流程定义KEY</th>
<th>版本号</th>
<th>XML资源名称</th>
<th>图片资源名称</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<c:forEach items="${processDefinitionList }" var="pd">
<tr>
<td>${pd.id }</td>
<td>${pd.deploymentId }</td>
<td>${pd.name }</td>
<td>${pd.key }</td>
<td>${pd.version }</td>
<td><a target="_blank" href='${ctx }/chapter5/read-resource?pdid=${pd.id }&resourceName=${pd.resourceName }'>${pd.resourceName }</a></td>
<td><a target="_blank" href='${ctx }/chapter5/read-resource?pdid=${pd.id }&resourceName=${pd.diagramResourceName }'>${pd.diagramResourceName }</a></td>
<td>
<a class="btn" href='${ctx }/chapter5/delete-deployment?deploymentId=${pd.deploymentId }'><i class="icon-trash"></i>删除</a>
<a class="btn" href='${ctx }/chapter6/getform/start/${pd.id }'><i class="icon-play"></i>启动</a>
</td>
</tr>
</c:forEach>
</tbody>
</table>
</body>
</html>
2、部署流程资源
@RequestMapping(value = "/deploy")
public String deploy(@RequestParam(value = "file", required = true) MultipartFile file) {
// 获取上传的文件名
String fileName = file.getOriginalFilename();
try {
// 得到输入流(字节流)对象
InputStream fileInputStream = file.getInputStream();
// 文件的扩展名
String extension = FilenameUtils.getExtension(fileName);
// zip或者bar类型的文件用ZipInputStream方式部署
DeploymentBuilder deployment = repositoryService.createDeployment();
if (extension.equals("zip") || extension.equals("bar")) {
ZipInputStream zip = new ZipInputStream(fileInputStream);
deployment.addZipInputStream(zip);
} else {
// 其他类型的文件直接部署
deployment.addInputStream(fileName, fileInputStream);
}
deployment.deploy();
} catch (Exception e) {
logger.error("error on deploy process, because of file input stream");
}
return "redirect:process-list";
}
3、读取流程资源
/**
* 读取流程资源
*
* @param processDefinitionId 流程定义ID
* @param resourceName 资源名称
*/
@RequestMapping(value = "/read-resource")
public void readResource(@RequestParam("pdid") String processDefinitionId, @RequestParam("resourceName") String resourceName, HttpServletResponse response)
throws Exception {
ProcessDefinitionQuery pdq = repositoryService.createProcessDefinitionQuery();
ProcessDefinition pd = pdq.processDefinitionId(processDefinitionId).singleResult();
// 通过接口读取
InputStream resourceAsStream = repositoryService.getResourceAsStream(pd.getDeploymentId(), resourceName);
// 输出资源内容到相应对象
byte[] b = new byte[1024];
int len = -1;
while ((len = resourceAsStream.read(b, 0, 1024)) != -1) {
response.getOutputStream().write(b, 0, len);
}
}
4、删除部署的流程
/**
* 删除部署的流程,级联删除流程实例
*
* @param deploymentId 流程部署ID
*/
@RequestMapping(value = "/delete-deployment")
public String deleteProcessDefinition(@RequestParam("deploymentId") String deploymentId) {
repositoryService.deleteDeployment(deploymentId, true);
return "redirect:process-list";
}
5、读取流程启动表单
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page import="org.activiti.engine.form.*, org.apache.commons.lang3.*" %>
<!DOCTYPE html>
<html>
<head>
<%@ include file="/common/global.jsp"%>
<%@ include file="/common/meta.jsp" %>
<%@ include file="/common/include-base-styles.jsp" %>
<title>启动流程</title>
<script type="text/javascript" src="${ctx }/js/common/jquery.js"></script>
<script type="text/javascript" src="${ctx }/js/common/bootstrap.min.js"></script>
<script type="text/javascript" src="${ctx }/js/common/bootstrap-datepicker.js"></script>
<script type="text/javascript">
$(function() {
$('.datepicker').datepicker();
});
</script>
</head>
<body>
<h3>启动流程—
<c:if test="${hasStartFormKey}">
[${processDefinition.name}],版本号:${processDefinition.version}
</c:if>
<c:if test="${!hasStartFormKey}">
[${startFormData.processDefinition.name}],版本号:${startFormData.processDefinition.version}
</c:if>
</h3>
<hr/>
<form action="${ctx }/chapter6/process-instance/start/${processDefinitionId}" class="form-horizontal" method="post">
<c:if test="${hasStartFormKey}">
${startFormData}
</c:if>
<c:if test="${!hasStartFormKey}">
<c:forEach items="${startFormData.formProperties}" var="fp">
<c:set var="fpo" value="${fp}"/>
<%
// 把需要获取的属性读取并设置到pageContext域
FormType type = ((FormProperty)pageContext.getAttribute("fpo")).getType();
String[] keys = {"datePattern"};
for (String key: keys) {
pageContext.setAttribute(key, ObjectUtils.toString(type.getInformation(key)));
}
%>
<div class="control-group">
<%-- 文本或者数字类型 --%>
<c:if test="${fp.type.name == 'string' || fp.type.name == 'long'}">
<label class="control-label" for="${fp.id}">${fp.name}:</label>
<div class="controls">
<input type="text" id="${fp.id}" name="${fp.id}" data-type="${fp.type.name}" value="" />
</div>
</c:if>
<%-- 日期 --%>
<c:if test="${fp.type.name == 'date'}">
<label class="control-label" for="${fp.id}">${fp.name}:</label>
<div class="controls">
<input type="text" id="${fp.id}" name="${fp.id}" class="datepicker" data-type="${fp.type.name}" data-date-format="${fn:toLowerCase(datePattern)}" />
</div>
</c:if>
<%-- Javascript --%>
<c:if test="${fp.type.name == 'javascript'}">
<script type="text/javascript">${fp.value};</script>
</c:if>
</div>
</c:forEach>
</c:if>
<%-- 按钮区域 --%>
<div class="control-group">
<div class="controls">
<a href="javascript:history.back();" class="btn"><i class="icon-backward"></i>返回列表</a>
<button type="submit" class="btn"><i class="icon-play"></i>启动流程</button>
</div>
</div>
</form>
</body>
</html>
@RequestMapping(value = "getform/start/{processDefinitionId}")
public ModelAndView readStartForm(@PathVariable("processDefinitionId") String processDefinitionId) throws Exception {
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult();
boolean hasStartFormKey = processDefinition.hasStartFormKey();
// 根据是否有formkey属性判断使用哪个展示层
String viewName = "chapter6/start-process-form";
ModelAndView mav = new ModelAndView(viewName);
// 判断是否有formkey属性
if (hasStartFormKey) {
Object renderedStartForm = formService.getRenderedStartForm(processDefinitionId);
mav.addObject("startFormData", renderedStartForm);
mav.addObject("processDefinition", processDefinition);
} else { // 动态表单字段
StartFormData startFormData = formService.getStartFormData(processDefinitionId);
mav.addObject("startFormData", startFormData);
}
mav.addObject("hasStartFormKey", hasStartFormKey);
mav.addObject("processDefinitionId", processDefinitionId);
return mav;
}
6、根据表单启动流程
@RequestMapping(value = "process-instance/start/{processDefinitionId}")
public String startProcessInstance(@PathVariable("processDefinitionId") String pdid, HttpServletRequest request, RedirectAttributes redirectAttributes) {
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(pdid).singleResult();
boolean hasStartFormKey = processDefinition.hasStartFormKey();
Map<String, String> formValues = new HashMap<String, String>();
if (hasStartFormKey) { // formkey表单
Map<String, String[]> parameterMap = request.getParameterMap();
Set<Entry<String, String[]>> entrySet = parameterMap.entrySet();
for (Entry<String, String[]> entry : entrySet) {
String key = entry.getKey();
formValues.put(key, entry.getValue()[0]);
}
} else { // 动态表单
// 先读取表单字段在根据表单字段的ID读取请求参数值
StartFormData formData = formService.getStartFormData(pdid);
// 从请求中获取表单字段的值
List<FormProperty> formProperties = formData.getFormProperties();
for (FormProperty formProperty : formProperties) {
String value = request.getParameter(formProperty.getId());
formValues.put(formProperty.getId(), value);
}
}
// 获取当前登录的用户
User user = UserUtil.getUserFromSession(request.getSession());
// 用户未登录不能操作,实际应用使用权限框架实现,例如Spring Security、Shiro等
if (user == null || StringUtils.isBlank(user.getId())) {
return "redirect:/login?timeout=true";
}
identityService.setAuthenticatedUserId(user.getId());
// 提交表单字段并启动一个新的流程实例
ProcessInstance processInstance = formService.submitStartFormData(pdid, formValues);
logger.debug("start a processinstance: {}", processInstance);
redirectAttributes.addFlashAttribute("message", "流程已启动,实例ID:" + processInstance.getId());
return "redirect:/chapter5/process-list";
}
7、获取待办任务
@RequestMapping(value = "task/list")
public ModelAndView todoTasks(HttpSession session) throws Exception {
String viewName = "chapter6/task-list";
ModelAndView mav = new ModelAndView(viewName);
User user = UserUtil.getUserFromSession(session);
// 读取直接分配给当前人或者已经签收的任务
List<Task> doingTasks = taskService.createTaskQuery().taskAssignee(user.getId()).list();
// 等待签收的任务
List<Task> waitingClaimTasks = taskService.createTaskQuery().taskCandidateUser(user.getId()).list();
// 合并两种任务
List<Task> allTasks = new ArrayList<Task>();
allTasks.addAll(doingTasks);
allTasks.addAll(waitingClaimTasks);
// 5.16版本可以使用一下代码待办查询
// List<Task> tasks = taskService.createTaskQuery().taskCandidateOrAssigned(user.getId()).list();
mav.addObject("tasks", allTasks);
return mav;
}
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<%@ include file="/common/global.jsp"%>
<%@ include file="/common/meta.jsp" %>
<%@ include file="/common/include-base-styles.jsp" %>
<title>待办任务列表--chapter6</title>
<script src="${ctx }/js/common/jquery.js" type="text/javascript"></script>
</head>
<body>
<c:if test="${not empty message}">
<div id="message" class="alert alert-success">${message}</div>
<!-- 自动隐藏提示信息 -->
<script type="text/javascript">
setTimeout(function() {
$('#message').hide('slow');
}, 5000);
</script>
</c:if>
<table width="100%" class="table table-bordered table-hover table-condensed">
<thead>
<tr>
<th>任务ID</th>
<th>任务名称</th>
<th>流程实例ID</th>
<th>流程定义ID</th>
<th>任务创建时间</th>
<th>办理人</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<c:forEach items="${tasks }" var="task">
<tr>
<td>${task.id }</td>
<td>${task.name }</td>
<td>${task.processInstanceId }</td>
<td>${task.processDefinitionId }</td>
<td>${task.createTime }</td>
<td>${task.assignee }</td>
<td>
<c:if test="${empty task.assignee }">
<a class="btn" href="claim/${task.id}"><i class="icon-eye-open"></i>签收</a>
</c:if>
<c:if test="${not empty task.assignee }">
<a class="btn" href="getform/${task.id}"><i class="icon-user"></i>办理</a>
</c:if>
</td>
</tr>
</c:forEach>
</tbody>
</table>
</body>
</html>
8、签收任务
@RequestMapping(value = "task/claim/{id}")
public String claim(@PathVariable("id") String taskId, HttpSession session, RedirectAttributes redirectAttributes) {
String userId = UserUtil.getUserFromSession(session).getId();
taskService.claim(taskId, userId);
redirectAttributes.addFlashAttribute("message", "任务已签收");
return "redirect:/chapter6/task/list";
}
9、读取任务表单
@RequestMapping(value = "task/getform/{taskId}")
public ModelAndView readTaskForm(@PathVariable("taskId") String taskId) throws Exception {
String viewName = "chapter6/task-form";
ModelAndView mav = new ModelAndView(viewName);
TaskFormData taskFormData = formService.getTaskFormData(taskId);
if (taskFormData.getFormKey() != null) {
Object renderedTaskForm = formService.getRenderedTaskForm(taskId);
Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
mav.addObject("task", task);
mav.addObject("taskFormData", renderedTaskForm);
mav.addObject("hasFormKey", true);
} else {
mav.addObject("taskFormData", taskFormData);
}
return mav;
}
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page import="org.activiti.engine.form.*, org.apache.commons.lang3.*" %>
<!DOCTYPE html>
<html>
<head>
<%@ include file="/common/global.jsp"%>
<%@ include file="/common/meta.jsp" %>
<%@ include file="/common/include-base-styles.jsp" %>
<title>任务办理</title>
<script type="text/javascript" src="${ctx }/js/common/jquery.js"></script>
<script type="text/javascript" src="${ctx }/js/common/bootstrap.min.js"></script>
<script type="text/javascript" src="${ctx }/js/common/bootstrap-datepicker.js"></script>
<script type="text/javascript">
$(function() {
$('.datepicker').datepicker();
});
</script>
</head>
<body>
<h3>任务办理—[${hasFormKey ? task.name : taskFormData.task.name}],流程定义ID:[${hasFormKey ? task.processDefinitionId : taskFormData.task.processDefinitionId}]</h3>
<hr/>
<form action="${ctx }/chapter6/task/complete/${hasFormKey ? task.id : taskFormData.task.id}" class="form-horizontal" method="post">
<c:if test="${hasFormKey}">
${taskFormData}
</c:if>
<c:if test="${!hasFormKey}">
<c:forEach items="${taskFormData.formProperties}" var="fp">
<c:set var="fpo" value="${fp}"/>
<c:set var="disabled" value="${fp.writable ? '' : 'disabled'}" />
<c:set var="readonly" value="${fp.writable ? '' : 'readonly'}" />
<c:set var="required" value="${fp.required ? 'required' : ''}" />
<%
// 把需要获取的属性读取并设置到pageContext域
FormType type = ((FormProperty)pageContext.getAttribute("fpo")).getType();
String[] keys = {"datePattern", "values"};
for (String key: keys) {
pageContext.setAttribute(key, type.getInformation(key));
}
%>
<div class="control-group">
<%-- 文本或者数字类型 --%>
<c:if test="${fp.type.name == 'string' || fp.type.name == 'long'}">
<label class="control-label" for="${fp.id}">${fp.name}:</label>
<div class="controls">
<input type="text" id="${fp.id}" name="${fp.id}" data-type="${fp.type.name}" value="${fp.value}" ${readonly} ${required} />
</div>
</c:if>
<%-- 日期 --%>
<c:if test="${fp.type.name == 'date'}">
<label class="control-label" for="${fp.id}">${fp.name}:</label>
<div class="controls">
<input type="text" id="${fp.id}" name="${fp.id}" class="datepicker" value="${fp.value}" data-type="${fp.type.name}" data-date-format="${fn:toLowerCase(datePattern)}" ${readonly} ${required}/>
</div>
</c:if>
<%-- 下拉框 --%>
<c:if test="${fp.type.name == 'enum'}">
<label class="control-label" for="${fp.id}">${fp.name}:</label>
<div class="controls">
<select name="${fp.id}" id="${fp.id}" ${disabled} ${required}>
<c:forEach items="${values}" var="item">
<option value="${item.key}" <c:if test="${item.value == fp.value}">selected</c:if>>${item.value}</option>
</c:forEach>
</select>
</div>
</c:if>
<%-- Javascript --%>
<c:if test="${fp.type.name == 'javascript'}">
<script type="text/javascript">${fp.value};</script>
</c:if>
</div>
</c:forEach>
</c:if>
<%-- 按钮区域 --%>
<div class="control-group">
<div class="controls">
<a href="javascript:history.back();" class="btn"><i class="icon-backward"></i>返回列表</a>
<button type="submit" class="btn"><i class="icon-ok"></i>完成任务</button>
</div>
</div>
</form>
</body>
</html>
10、完成任务
@RequestMapping(value = "task/complete/{taskId}")
public String completeTask(@PathVariable("taskId") String taskId, HttpServletRequest request) throws Exception {
TaskFormData taskFormData = formService.getTaskFormData(taskId);
String formKey = taskFormData.getFormKey();
// 从请求中获取表单字段的值
List<FormProperty> formProperties = taskFormData.getFormProperties();
Map<String, String> formValues = new HashMap<String, String>();
if (StringUtils.isNotBlank(formKey)) { // formkey表单
Map<String, String[]> parameterMap = request.getParameterMap();
Set<Entry<String, String[]>> entrySet = parameterMap.entrySet();
for (Entry<String, String[]> entry : entrySet) {
String key = entry.getKey();
formValues.put(key, entry.getValue()[0]);
}
} else { // 动态表单
for (FormProperty formProperty : formProperties) {
if (formProperty.isWritable()) {
String value = request.getParameter(formProperty.getId());
formValues.put(formProperty.getId(), value);
}
}
}
formService.submitTaskFormData(taskId, formValues);
return TASK_LIST;
}
11、保存审批意见
@RequestMapping(value = "save", method = RequestMethod.POST)
@ResponseBody
public Boolean addComment(@RequestParam("taskId") String taskId, @RequestParam("processInstanceId") String processInstanceId,
@RequestParam("message") String message, HttpSession session) {
//设置当前人,引擎会把当前人作为意见的所属人
identityService.setAuthenticatedUserId(UserUtil.getUserFromSession(session).getId());
//调用保存意见的方法
taskService.addComment(taskId, processInstanceId, message);
return true;
}
12、读取审批意见
@RequestMapping(value = "list/{processInstanceId}")
@ResponseBody
public Map<String, Object> list(@PathVariable("processInstanceId") String processInstanceId) {
Map<String, Object> result = new HashMap<String, Object>();
//根据流程实例ID读取意见
List<Comment> taskComments = taskService.getProcessInstanceComments(processInstanceId);
List<HistoricTaskInstance> list = historyService.createHistoricTaskInstanceQuery().processInstanceId(processInstanceId).list();
Map<String, String> taskNames = new HashMap<String, String>();
for (HistoricTaskInstance historicTaskInstance : list) {
//读取历史任务以键值对形式保存任务ID和名称
taskNames.put(historicTaskInstance.getId(), historicTaskInstance.getName());
}
result.put("comments", taskComments);
result.put("taskNames", taskNames);
return result;
}
13、更改任务属性

14、添加任务参与人

15、删除任务参与人


16、添加候选人、候选组

17、删除参与人、候选人及候选组

18、添加子任务

19、查询子任务及上级任务

20、查询历史任务

21、保存文件类型附件
@RequestMapping(value = "new/file")
public String newFile(@RequestParam("taskId") String taskId, @RequestParam(value = "processInstanceId", required = false) String processInstanceId,
@RequestParam("attachmentName") String attachmentName, @RequestParam(value = "attachmentDescription", required = false) String attachmentDescription,
@RequestParam("file") MultipartFile file, HttpSession session) {
try {
//获取文件扩展名
String attachmentType = file.getContentType() + ";" + FilenameUtils.getExtension(file.getOriginalFilename());
identityService.setAuthenticatedUserId(UserUtil.getUserFromSession(session).getId());
Attachment attachment = taskService.createAttachment(attachmentType, taskId, processInstanceId, attachmentName, attachmentDescription,
file.getInputStream());
taskService.saveAttachment(attachment);
} catch (IOException e) {
e.printStackTrace();
}
return "redirect:/chapter6/task/getform/" + taskId;
}
22、保存URL类型附件
@RequestMapping(value = "new/url")
public String newUrl(@RequestParam("taskId") String taskId, @RequestParam(value = "processInstanceId", required = false) String processInstanceId,
@RequestParam("attachmentName") String attachmentName, @RequestParam(value = "attachmentDescription", required = false) String attachmentDescription,
@RequestParam("url") String url, HttpSession session) {
String attachmentType = "url";
identityService.setAuthenticatedUserId(UserUtil.getUserFromSession(session).getId());
/*Attachment attachment = */
taskService.createAttachment(attachmentType, taskId, processInstanceId, attachmentName, attachmentDescription, url);
/*
* 如果要更新附件内容,先读取附件对象,然后设置属性(只能更新name和description),最后保存附件对象
*/
// taskService.saveAttachment(attachment);
return "redirect:/chapter6/task/getform/" + taskId;
}
23、下载附件
@RequestMapping(value = "download/{attachmentId}")
public void downloadFile(@PathVariable("attachmentId") String attachmentId, HttpServletResponse response) throws IOException {
//查询附件对象
Attachment attachment = taskService.getAttachment(attachmentId);
//读取附件的二进制流
InputStream attachmentContent = taskService.getAttachmentContent(attachmentId);
//根据规则获取文件的类型
String contentType = StringUtils.substringBefore(attachment.getType(), ";");
response.addHeader("Content-Type", contentType + ";charset=UTF-8");
//根据规则获取文件的扩展名
String extensionFileName = StringUtils.substringAfter(attachment.getType(), ";");
//下载
String fileName = attachment.getName() + "." + extensionFileName;
response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
IOUtils.copy(new BufferedInputStream(attachmentContent), response.getOutputStream());
}
24、删除附件
@RequestMapping(value = "delete/{attachmentId}")
@ResponseBody
public String delete(@PathVariable("attachmentId") String attachmentId) {
taskService.deleteAttachment(attachmentId);
return "true";
}
25、查询用户参与过的流程
@RequestMapping("execution/list")
public ModelAndView list(HttpServletRequest request) {
ModelAndView mav = new ModelAndView("chapter13/execution-list");
/* 标准查询
List<ProcessInstance> processInstanceList = runtimeService.createProcessInstanceQuery().list();
List<Execution> list = runtimeService.createExecutionQuery().list();
mav.addObject("list", list);
*/
User user = UserUtil.getUserFromSession(request.getSession());
Page<Execution> page = new Page<Execution>(PageUtil.PAGE_SIZE);
int[] pageParams = PageUtil.init(page, request);
NativeExecutionQuery nativeExecutionQuery = runtimeService.createNativeExecutionQuery();
// native query
String sql = "select distinct * from (select RES.* from ACT_RU_EXECUTION RES left join ACT_HI_TASKINST ART on ART.PROC_INST_ID_ = RES.PROC_INST_ID_ "
+ " left join ACT_HI_PROCINST AHP on AHP.PROC_INST_ID_ = RES.PROC_INST_ID_ "
+ " where SUSPENSION_STATE_ = '1' and (ART.ASSIGNEE_ = #{userId} or AHP.START_USER_ID_ = #{userId}) "
+ " and ACT_ID_ is not null and IS_ACTIVE_ = 'TRUE' order by ART.START_TIME_ desc)";
nativeExecutionQuery.parameter("userId", user.getId());
List<Execution> executionList = nativeExecutionQuery.sql(sql).listPage(pageParams[0], pageParams[1]);
// 查询流程定义对象
Map<String, ProcessDefinition> definitionMap = new HashMap<String, ProcessDefinition>();
// 任务的英文-中文对照
Map<String, Task> taskMap = new HashMap<String, Task>();
// 每个Execution的当前活动ID,可能为多个
Map<String, List<String>> currentActivityMap = new HashMap<String, List<String>>();
// 设置每个Execution对象的当前活动节点
for (Execution execution : executionList) {
ExecutionEntity executionEntity = (ExecutionEntity) execution;
String processInstanceId = executionEntity.getProcessInstanceId();
String processDefinitionId = executionEntity.getProcessDefinitionId();
// 缓存ProcessDefinition对象到Map集合
definitionCache(definitionMap, processDefinitionId);
// 查询当前流程的所有处于活动状态的活动ID,如果并行的活动则会有多个
List<String> activeActivityIds = runtimeService.getActiveActivityIds(execution.getId());
currentActivityMap.put(execution.getId(), activeActivityIds);
for (String activityId : activeActivityIds) {
// 查询处于活动状态的任务
Task task = taskService.createTaskQuery().taskDefinitionKey(activityId).executionId(execution.getId()).singleResult();
// 调用活动
if (task == null) {
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
.superProcessInstanceId(processInstanceId).singleResult();
if (processInstance != null) {
task = taskService.createTaskQuery().processInstanceId(processInstance.getProcessInstanceId()).singleResult();
definitionCache(definitionMap, processInstance.getProcessDefinitionId());
}
}
taskMap.put(activityId, task);
}
}
mav.addObject("taskMap", taskMap);
mav.addObject("definitions", definitionMap);
mav.addObject("currentActivityMap", currentActivityMap);
page.setResult(executionList);
page.setTotalCount(nativeExecutionQuery.sql("select count(*) from (" + sql + ")").count());
mav.addObject("page", page);
return mav;
}
/**
* 流程定义对象缓存
*
* @param definitionMap
* @param processDefinitionId
*/
private void definitionCache(Map<String, ProcessDefinition> definitionMap, String processDefinitionId) {
if (definitionMap.get(processDefinitionId) == null) {
ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();
processDefinitionQuery.processDefinitionId(processDefinitionId);
ProcessDefinition processDefinition = processDefinitionQuery.singleResult();
// 放入缓存
definitionMap.put(processDefinitionId, processDefinition);
}
}
26、查询已经结束的流程实例
@RequestMapping(value = "finished/list")
public ModelAndView finishedProcessInstanceList(HttpServletRequest request) {
ModelAndView mav = new ModelAndView("chapter13/finished-process");
Page<HistoricProcessInstance> page = new Page<HistoricProcessInstance>(PageUtil.PAGE_SIZE);
int[] pageParams = PageUtil.init(page, request);
HistoricProcessInstanceQuery historicProcessInstanceQuery = historyService.createHistoricProcessInstanceQuery().finished();
List<HistoricProcessInstance> historicProcessInstances = historicProcessInstanceQuery.listPage(pageParams[0], pageParams[1]);
// 查询流程定义对象
Map<String, ProcessDefinition> definitionMap = new HashMap<String, ProcessDefinition>();
for (HistoricProcessInstance historicProcessInstance : historicProcessInstances) {
definitionCache(definitionMap, historicProcessInstance.getProcessDefinitionId());
}
page.setResult(historicProcessInstances);
page.setTotalCount(historicProcessInstanceQuery.count());
mav.addObject("page", page);
mav.addObject("definitions", definitionMap);
return mav;
}
27、查询历史流程实例相关信息
@RequestMapping(value = "finished/view/{processInstanceId}")
public ModelAndView historyDatas(@PathVariable("processInstanceId") String processInstanceId) {
ModelAndView mav = new ModelAndView("chapter13/view-finished-process");
List<HistoricActivityInstance> activityInstances = historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).list();
// 查询历史流程实例
HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
.processInstanceId(processInstanceId).singleResult();
// 查询流程有关的变量
List<HistoricVariableInstance> variableInstances = historyService.createHistoricVariableInstanceQuery()
.processInstanceId(processInstanceId).list();
List<HistoricDetail> formProperties = historyService.createHistoricDetailQuery().processInstanceId(processInstanceId).formProperties().list();
// 查询流程定义对象
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
.processDefinitionId(historicProcessInstance.getProcessDefinitionId()).singleResult();
mav.addObject("historicProcessInstance", historicProcessInstance);
mav.addObject("variableInstances", variableInstances);
mav.addObject("activities", activityInstances);
mav.addObject("formProperties", formProperties);
mav.addObject("processDefinition", processDefinition);
return mav;
}
28、删除历史流程实例
@RequestMapping(value = "finished/delete/{processInstanceId}")
public String deleteProcessInstance(@PathVariable("processInstanceId") String processInstanceId,
RedirectAttributes redirectAttributes) {
redirectAttributes.addFlashAttribute("message", "ID为" + processInstanceId + "的历史流程已删除!");
historyService.deleteHistoricProcessInstance(processInstanceId);
return "redirect:/chapter13/history/process/finished/manager";
}
29、流程跟踪
@Controller
@RequestMapping(value = "/chapter13/process")
public class TraceProcessController {
protected Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
TaskService taskService;
@Autowired
HistoryService historyService;
@Autowired
RuntimeService runtimeService;
@Autowired
RepositoryService repositoryService;
@Autowired
protected IdentityService identityService;
@Autowired
ProcessEngineConfiguration processEngineConfiguration;
/**
* 读取流程资源
*/
@RequestMapping(value = "trace/data/auto/{executionId}")
public void readResource(@PathVariable("executionId") String executionId, HttpServletResponse response)
throws Exception {
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(executionId).singleResult();
BpmnModel bpmnModel = repositoryService.getBpmnModel(processInstance.getProcessDefinitionId());
ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity) repositoryService.createProcessDefinitionQuery().processDefinitionId(processInstance.getProcessDefinitionId()).singleResult();
List<String> activeActivityIds = runtimeService.getActiveActivityIds(executionId);
ProcessDiagramGenerator diagramGenerator = processEngineConfiguration.getProcessDiagramGenerator();
List<String> highLightedFlows = getHighLightedFlows(processDefinition, processInstance.getId());
InputStream imageStream =diagramGenerator.generateDiagram(bpmnModel, "png", activeActivityIds, highLightedFlows);
// 输出资源内容到相应对象
byte[] b = new byte[1024];
int len;
while ((len = imageStream.read(b, 0, 1024)) != -1) {
response.getOutputStream().write(b, 0, len);
}
}
private List<String> getHighLightedFlows(ProcessDefinitionEntity processDefinition, String processInstanceId) {
List<String> highLightedFlows = new ArrayList<String>();
List<HistoricActivityInstance> historicActivityInstances = historyService
.createHistoricActivityInstanceQuery()
.processInstanceId(processInstanceId)
.orderByHistoricActivityInstanceStartTime().asc().list();
List<String> historicActivityInstanceList = new ArrayList<String>();
for (HistoricActivityInstance hai : historicActivityInstances) {
historicActivityInstanceList.add(hai.getActivityId());
}
// add current activities to list
List<String> highLightedActivities = runtimeService.getActiveActivityIds(processInstanceId);
historicActivityInstanceList.addAll(highLightedActivities);
// activities and their sequence-flows
for (ActivityImpl activity : processDefinition.getActivities()) {
int index = historicActivityInstanceList.indexOf(activity.getId());
if (index >= 0 && index + 1 < historicActivityInstanceList.size()) {
List<PvmTransition> pvmTransitionList = activity
.getOutgoingTransitions();
for (PvmTransition pvmTransition : pvmTransitionList) {
String destinationFlowId = pvmTransition.getDestination().getId();
if (destinationFlowId.equals(historicActivityInstanceList.get(index + 1))) {
highLightedFlows.add(pvmTransition.getId());
}
}
}
}
return highLightedFlows;
}
/**
* 读取历史数据
*
* @return
*/
@RequestMapping(value = "trace/view/{executionId}")
public ModelAndView historyDatas(@PathVariable("executionId") String executionId) {
ModelAndView mav = new ModelAndView("chapter13/trace-process");
// 查询Execution对象
Execution execution = runtimeService.createExecutionQuery().executionId(executionId).singleResult();
// 查询所有的历史活动记录
String processInstanceId = execution.getProcessInstanceId();
List<HistoricActivityInstance> activityInstances = historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).list();
// 查询历史流程实例
HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
.processInstanceId(processInstanceId).singleResult();
// 查询流程有关的变量
List<HistoricVariableInstance> variableInstances = historyService.createHistoricVariableInstanceQuery()
.processInstanceId(processInstanceId).list();
List<HistoricDetail> formProperties = historyService.createHistoricDetailQuery().processInstanceId(processInstanceId).formProperties().list();
// 查询流程定义对象
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
.processDefinitionId(historicProcessInstance.getProcessDefinitionId()).singleResult();
// 查询运行时流程实例
ProcessInstance parentProcessInstance = runtimeService.createProcessInstanceQuery()
.subProcessInstanceId(execution.getProcessInstanceId()).singleResult();
mav.addObject("parentProcessInstance", parentProcessInstance);
mav.addObject("historicProcessInstance", historicProcessInstance);
mav.addObject("variableInstances", variableInstances);
mav.addObject("activities", activityInstances);
mav.addObject("formProperties", formProperties);
mav.addObject("processDefinition", processDefinition);
mav.addObject("executionId", executionId);
return mav;
}
/**
* 读取跟踪数据
*
* @param executionId
* @return
* @throws Exception
*/
@RequestMapping(value = "trace/data/{executionId}")
@ResponseBody
public List<Map<String, Object>> readActivityDatas(@PathVariable("executionId") String executionId) throws Exception {
ExecutionEntity executionEntity = (ExecutionEntity) runtimeService.createExecutionQuery().executionId(executionId).singleResult();
List<String> activeActivityIds = runtimeService.getActiveActivityIds(executionId);
RepositoryServiceImpl repositoryServiceImpl = (RepositoryServiceImpl) repositoryService;
ReadOnlyProcessDefinition deployedProcessDefinition = repositoryServiceImpl
.getDeployedProcessDefinition(executionEntity.getProcessDefinitionId());
ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity) deployedProcessDefinition;
List<ActivityImpl> activitiList = processDefinition.getActivities();//获得当前任务的所有节点
List<Map<String, Object>> activityInfos = new ArrayList<Map<String, Object>>();
for (ActivityImpl activity : activitiList) {
ActivityBehavior activityBehavior = activity.getActivityBehavior();
boolean currentActiviti = false;
// 当前节点
String activityId = activity.getId();
if (activeActivityIds.contains(activityId)) {
currentActiviti = true;
}
Map<String, Object> activityImageInfo = packageSingleActivitiInfo(activity, executionEntity.getId(), currentActiviti);
activityInfos.add(activityImageInfo);
// 处理子流程
if (activityBehavior instanceof SubProcessActivityBehavior) {
List<ActivityImpl> innerActivityList = activity.getActivities();
for (ActivityImpl innerActivity : innerActivityList) {
String innerActivityId = innerActivity.getId();
if (activeActivityIds.contains(innerActivityId)) {
currentActiviti = true;
} else {
currentActiviti = false;
}
activityImageInfo = packageSingleActivitiInfo(innerActivity, executionEntity.getId(), currentActiviti);
activityInfos.add(activityImageInfo);
}
}
}
return activityInfos;
}
/**
* 封装输出信息,包括:当前节点的X、Y坐标、变量信息、任务类型、任务描述
*
* @param activity
* @param currentActiviti
* @return
*/
private Map<String, Object> packageSingleActivitiInfo(ActivityImpl activity, String executionId,
boolean currentActiviti) throws Exception {
Map<String, Object> activityInfo = new HashMap<String, Object>();
activityInfo.put("currentActiviti", currentActiviti);
// 设置图形的XY坐标以及宽度、高度
setSizeAndPositonInfo(activity, activityInfo);
Map<String, Object> vars = new HashMap<String, Object>();
Map<String, Object> properties = activity.getProperties();
vars.put("任务类型", ActivityUtil.getZhActivityType(properties.get("type").toString()));
vars.put("任务名称", properties.get("name"));
// 当前节点的task
if (currentActiviti) {
setCurrentTaskInfo(executionId, activity.getId(), vars);
}
logger.debug("trace variables: {}", vars);
activityInfo.put("vars", vars);
return activityInfo;
}
/**
* 获取当前节点信息
*
* @return
*/
private void setCurrentTaskInfo(String executionId, String activityId, Map<String, Object> vars) {
Task currentTask = taskService.createTaskQuery().executionId(executionId)
.taskDefinitionKey(activityId).singleResult();
logger.debug("current task for processInstance: {}", ToStringBuilder.reflectionToString(currentTask));
if (currentTask == null) return;
String assignee = currentTask.getAssignee();
if (assignee != null) {
User assigneeUser = identityService.createUserQuery().userId(assignee).singleResult();
String userInfo = assigneeUser.getFirstName() + " " + assigneeUser.getLastName() + "/" + assigneeUser.getId();
vars.put("当前处理人", userInfo);
vars.put("创建时间", new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(currentTask.getCreateTime()));
} else {
vars.put("任务状态", "未签收");
}
}
/**
* 设置宽度、高度、坐标属性
*
* @param activity
* @param activityInfo
*/
private void setSizeAndPositonInfo(ActivityImpl activity, Map<String, Object> activityInfo) {
activityInfo.put("width", activity.getWidth());
activityInfo.put("height", activity.getHeight());
activityInfo.put("x", activity.getX());
activityInfo.put("y", activity.getY());
}
}
30、用户及组管理
@Controller
@RequestMapping("/chapter14/identity")
public class IdentityController {
@Autowired
IdentityService identityService;
/**
* 组列表
*
* @param request
* @return
*/
@RequestMapping("group/list")
public ModelAndView groupList(HttpServletRequest request) {
ModelAndView mav = new ModelAndView("chapter14/group-list");
Page<Group> page = new Page<Group>(PageUtil.PAGE_SIZE);
int[] pageParams = PageUtil.init(page, request);
GroupQuery groupQuery = identityService.createGroupQuery();
List<Group> groupList = groupQuery.listPage(pageParams[0], pageParams[1]);
page.setResult(groupList);
page.setTotalCount(groupQuery.count());
mav.addObject("page", page);
return mav;
}
/**
* 保存Group
*
* @return
*/
@RequestMapping(value = "group/save", method = RequestMethod.POST)
public String saveGroup(@RequestParam("groupId") String groupId,
@RequestParam("groupName") String groupName,
@RequestParam("type") String type,
RedirectAttributes redirectAttributes) {
Group group = identityService.createGroupQuery().groupId(groupId).singleResult();
if (group == null) {
group = identityService.newGroup(groupId);
}
group.setName(groupName);
group.setType(type);
identityService.saveGroup(group);
redirectAttributes.addFlashAttribute("message", "成功添加组[" + groupName + "]");
return "redirect:/chapter14/identity/group/list";
}
/**
* 删除Group
*/
@RequestMapping(value = "group/delete/{groupId}", method = RequestMethod.GET)
public String deleteGroup(@PathVariable("groupId") String groupId,
RedirectAttributes redirectAttributes) {
identityService.deleteGroup(groupId);
redirectAttributes.addFlashAttribute("message", "成功删除组[" + groupId + "]");
return "redirect:/chapter14/identity/group/list";
}
/**
* 用户列表
*
* @param request
* @return
*/
@RequestMapping("user/list")
public ModelAndView userList(HttpServletRequest request) {
ModelAndView mav = new ModelAndView("chapter14/user-list");
Page<User> page = new Page<User>(PageUtil.PAGE_SIZE);
int[] pageParams = PageUtil.init(page, request);
UserQuery userQuery = identityService.createUserQuery();
List<User> userList = userQuery.listPage(pageParams[0], pageParams[1]);
// 查询每个人的分组,这样的写法比较耗费性能、时间,仅供读者参考
Map<String, List<Group>> groupOfUserMap = new HashMap<String, List<Group>>();
for (User user : userList) {
List<Group> groupList = identityService.createGroupQuery().groupMember(user.getId()).list();
groupOfUserMap.put(user.getId(), groupList);
}
page.setResult(userList);
page.setTotalCount(userQuery.count());
mav.addObject("page", page);
mav.addObject("groupOfUserMap", groupOfUserMap);
// 读取所有组
List<Group> groups = identityService.createGroupQuery().list();
mav.addObject("allGroup", groups);
return mav;
}
/**
* 保存User
*
* @param redirectAttributes
* @return
*/
@RequestMapping(value = "user/save", method = RequestMethod.POST)
public String saveUser(@RequestParam("userId") String userId,
@RequestParam("firstName") String firstName,
@RequestParam("lastName") String lastName,
@RequestParam(value = "password", required = false) String password,
@RequestParam(value = "email", required = false) String email,
RedirectAttributes redirectAttributes) {
User user = identityService.createUserQuery().userId(userId).singleResult();
if (user == null) {
user = identityService.newUser(userId);
}
user.setFirstName(firstName);
user.setLastName(lastName);
user.setEmail(email);
if (StringUtils.isNotBlank(password)) {
user.setPassword(password);
}
identityService.saveUser(user);
redirectAttributes.addFlashAttribute("message", "成功添加用户[" + firstName + " " + lastName + "]");
return "redirect:/chapter14/identity/user/list";
}
/**
* 删除User
*/
@RequestMapping(value = "user/delete/{userId}", method = RequestMethod.GET)
public String deleteUser(@PathVariable("userId") String userId,
RedirectAttributes redirectAttributes) {
identityService.deleteUser(userId);
redirectAttributes.addFlashAttribute("message", "成功删除用户[" + userId + "]");
return "redirect:/chapter14/identity/user/list";
}
/**
* 为用户设置所属组
* @param userId
* @param groupIds
* @return
*/
@RequestMapping(value = "group/set", method = RequestMethod.POST)
public String groupForUser(@RequestParam("userId") String userId, @RequestParam("group") String[] groupIds) {
List<Group> groupInDb = identityService.createGroupQuery().groupMember(userId).list();
for (Group group : groupInDb) {
identityService.deleteMembership(userId, group.getId());
}
for (String group : groupIds) {
identityService.createMembership(userId, group);
}
return "redirect:/chapter14/identity/user/list";
}
}
31、作业控制
@Controller
@RequestMapping(value = "/chapter14/job")
public class JobController {
@Autowired
ManagementService managementService;
public static Map<String, String> JOB_TYPES = new HashMap<String, String>();
static {
JOB_TYPES.put("activate-processdefinition", "激活流程定义");
JOB_TYPES.put("timer-intermediate-transition", "中间定时");
JOB_TYPES.put("timer-transition", "边界定时");
JOB_TYPES.put("timer-start-event", "定时启动流程");
JOB_TYPES.put("suspend-processdefinition", "挂起流程定义");
JOB_TYPES.put("async-continuation", "异步锁");
}
/**
* Job列表
*
* @return
*/
@RequestMapping(value = "list")
public ModelAndView jobList(HttpServletRequest request) {
ModelAndView mav = new ModelAndView("chapter14/job-list");
JobQuery jobQuery = managementService.createJobQuery();
Page<Job> page = new Page<Job>(PageUtil.PAGE_SIZE);
int[] pageParams = PageUtil.init(page, request);
List<Job> jobList = jobQuery.listPage(pageParams[0], pageParams[1]);
page.setResult(jobList);
page.setTotalCount(jobQuery.count());
Map<String, String> exceptionStacktraces = new HashMap<String, String>();
for (Job job : jobList) {
if (StringUtils.isNotBlank(job.getExceptionMessage())) {
exceptionStacktraces.put(job.getId(), managementService.getJobExceptionStacktrace(job.getId()));
}
}
mav.addObject("page", page);
mav.addObject("exceptionStacktraces", exceptionStacktraces);
mav.addObject("JOB_TYPES", JOB_TYPES);
return mav;
}
/**
* 删除作业
*
* @param jobId
* @return
*/
@RequestMapping(value = "delete/{jobId}")
public String deleteJob(@PathVariable("jobId") String jobId) {
managementService.deleteJob(jobId);
return "redirect:/chapter14/job/list";
}
/**
* 执行作业
*
* @param jobId
* @return
*/
@RequestMapping(value = "execute/{jobId}")
public String executeJob(@PathVariable("jobId") String jobId) {
managementService.executeJob(jobId);
return "redirect:/chapter14/job/list";
}
/**
* 更改作业可重试次数
*
* @param jobId
* @return
*/
@RequestMapping(value = "change/retries/{jobId}")
public String changeRetries(@PathVariable("jobId") String jobId, @RequestParam("retries") int retries) {
managementService.setJobRetries(jobId, retries);
return "redirect:/chapter14/job/list";
}
/**
* 读取作业异常信息
*
* @param jobId
* @return
*/
@RequestMapping(value = "stacktrace/{jobId}")
@ResponseBody
public String getJobExceptionStacktrace(@PathVariable("jobId") String jobId) {
return managementService.getJobExceptionStacktrace(jobId);
}
}
32、流程定义管理
@Controller
@RequestMapping(value = "/chapter14/process")
public class ProcessManagerController {
@Autowired
RepositoryService repositoryService;
@Autowired
ProcessDefinitionService processDefinitionService;
/**
* 流程定义状态控制
*
* @param state active|suspend
* @param processDefinitionId 流程定义ID
* @return
*/
@RequestMapping(value = "{state}", method = RequestMethod.POST)
public String changeState(@PathVariable(value = "state") String state,
@RequestParam(value = "processDefinitionId") String processDefinitionId,
@RequestParam(value = "cascade", required = false) boolean cascadeProcessInstances,
@RequestParam(value = "effectiveDate", required = false) String strEffectiveDate) {
Date effectiveDate = null;
if (StringUtils.isNotBlank(strEffectiveDate)) {
try {
effectiveDate = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").parse(strEffectiveDate);
} catch (ParseException e) {
//e.printStackTrace();
}
}
if (StringUtils.equals("active", state)) {
repositoryService.activateProcessDefinitionById(processDefinitionId, cascadeProcessInstances, effectiveDate);
} else if (StringUtils.equals("suspend", state)) {
repositoryService.suspendProcessDefinitionById(processDefinitionId, cascadeProcessInstances, effectiveDate);
}
return "redirect:/chapter5/process-list";
}
/**
* 设置流程定义对象的候选人、候选组
* @return
*/
@RequestMapping(value = "startable/set/{processDefinitionId}", method = RequestMethod.POST)
@ResponseBody
public String addStartables(@PathVariable("processDefinitionId") String processDefinitionId,
@RequestParam(value = "users[]", required = false) String[] users, @RequestParam(value = "groups[]", required = false) String[] groups) {
processDefinitionService.setStartables(processDefinitionId, users, groups);
return "true";
}
/**
* 读取已设置的候选启动人、组
* @param processDefinitionId
* @return
*/
@RequestMapping(value = "startable/read/{processDefinitionId}", method = RequestMethod.GET)
@ResponseBody
public Map<String, List<String>> readStartableData(@PathVariable("processDefinitionId") String processDefinitionId) {
Map<String, List<String>> datas = new HashMap<String, List<String>>();
ArrayList<String> users = new ArrayList<String>();
ArrayList<String> groups = new ArrayList<String>();
List<IdentityLink> links = repositoryService.getIdentityLinksForProcessDefinition(processDefinitionId);
for (IdentityLink link : links) {
if (StringUtils.isNotBlank(link.getUserId())) {
users.add(link.getUserId());
}
if (StringUtils.isNotBlank(link.getGroupId())) {
groups.add(link.getGroupId());
}
}
datas.put("users", users);
datas.put("groups", groups);
return datas;
}
}
该博客围绕Activiti流程管理展开,涵盖流程定义、部署、资源读取与删除等操作,还涉及任务处理,如获取待办、签收、完成任务等,以及审批意见保存与读取、附件管理、历史流程查询等内容,使用Java和Spring MVC技术。
961

被折叠的 条评论
为什么被折叠?



