普通表单——流程启动
来源:互联网 发布:知有儿童挑促织 编辑:程序博客网 时间:2024/05/03 15:30
leave.bpmn中有定义流程启动
<startEvent id="startevent1" name="Start" activiti:initiator="applyUserId"></startEvent>
menu.jsp中
<a rel="oa/leave/apply">请假申请(普通)</a>
然后对应控制层
@Controller@RequestMapping(value = "/oa/leave")public class LeaveController { @RequestMapping(value = {"apply", ""}) public String createForm(Model model) { model.addAttribute("leave", new Leave()); return "/oa/leave/leaveApply"; }}
再到流程启动页面leaveApply.jsp
<form:form id="inputForm" action="${ctx}/oa/leave/start" method="post" class="form-horizontal"><fieldset><legend><small>请假申请</small></legend><table border="1"><tr><td>请假类型:</td><td><select id="leaveType" name="leaveType"><option>公休</option><option>病假</option><option>调休</option><option>事假</option><option>婚假</option></select></td></tr><tr><td>开始时间:</td><td><input type="text" id="startTime" name="startTime" /></td></tr><tr><td>结束时间:</td><td><input type="text" id="endTime" name="endTime" /></td></tr><tr><td>请假原因:</td><td><textarea name="reason"></textarea></td></tr><tr><td> </td><td><button type="submit">申请</button></td></tr></table></fieldset></form:form>
输入表单值,点击申请按钮,/oa/leave/start
/** * 启动请假流程 * * @param leave */ @RequestMapping(value = "start", method = RequestMethod.POST) public String startWorkflow(Leave leave, RedirectAttributes redirectAttributes, HttpSession session) { try { User user = UserUtil.getUserFromSession(session); // 用户未登录不能操作,实际应用使用权限框架实现,例如Spring Security、Shiro等 if (user == null || StringUtils.isBlank(user.getId())) { return "redirect:/login?timeout=true"; } leave.setUserId(user.getId()); Map<String, Object> variables = new HashMap<String, Object>(); ProcessInstance processInstance = workflowService.startWorkflow(leave, variables); redirectAttributes.addFlashAttribute("message", "流程已启动,流程ID:" + processInstance.getId()); } catch (ActivitiException e) { if (e.getMessage().indexOf("no processes deployed with key") != -1) { logger.warn("没有部署流程!", e); redirectAttributes.addFlashAttribute("error", "没有部署流程,请在[工作流]->[流程管理]页面点击<重新部署流程>"); } else { logger.error("启动请假流程失败:", e); redirectAttributes.addFlashAttribute("error", "系统内部错误!"); } } catch (Exception e) { logger.error("启动请假流程失败:", e); redirectAttributes.addFlashAttribute("error", "系统内部错误!"); } return "redirect:/oa/leave/apply"; }
这里Map<String, Object> variables可以保存流程启动变量,当然我们是希望这些变量在流程各个节点间都可以共享,后面会介绍怎么取流程实例。
在WorkflowService中,有具体的流程启动方法,这个方法保存leave对象,启动流程,返回流程实例
/** * 启动流程 * * @param entity */ public ProcessInstance startWorkflow(Leave entity, Map<String, Object> variables) { leaveManager.saveLeave(entity); logger.debug("save entity: {}", entity); String businessKey = entity.getId().toString(); ProcessInstance processInstance = null; try { // 用来设置启动流程的人员ID,引擎会自动把用户ID保存到activiti:initiator中 identityService.setAuthenticatedUserId(entity.getUserId()); processInstance = runtimeService.startProcessInstanceByKey("leave", businessKey, variables); String processInstanceId = processInstance.getId(); entity.setProcessInstanceId(processInstanceId); logger.debug("start process of {key={}, bkey={}, pid={}, variables={}}", new Object[]{"leave", businessKey, processInstanceId, variables}); } finally { identityService.setAuthenticatedUserId(null); } return processInstance; }执行启动流程后,打印日志:
save entity: me.kafeitu.demo.activiti.entity.oa.Leave@1b9b6ad
--- starting StartProcessInstanceCmd --------------------------------------------------------
--- starting GetNextIdBlockCmd --------------------------------------------------------
Running command with propagation REQUIRES_NEW
Preparing: select * from ACT_GE_PROPERTY where NAME_ = ? Parameters: next.dbid(String)
--- GetNextIdBlockCmd finished --------------------------------------------------------
insert ProcessInstance[12]
Preparing: insert into ACT_RU_EXECUTION (ID_, REV_, PROC_INST_ID_, BUSINESS_KEY_, PROC_DEF_ID_, ACT_ID_, IS_ACTIVE_, IS_CONCURRENT_, IS_SCOPE_,IS_EVENT_SCOPE_, PARENT_ID_, SUPER_EXEC_, SUSPENSION_STATE_, CACHED_ENT_STATE_, TENANT_ID_, NAME_) values ( ?, 1, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? ) Parameters: 12(String), 12(String), 2(String), leave:1:20(String), deptLeaderAudit(String), true(Boolean), false(Boolean), true(Boolean), false(Boolean), null, null, 1(Integer), 2(Integer), (String), null
insert VariableInstanceEntity[id=13, name=applyUserId, type=string, textValue=kafeitu]
Preparing: insert into ACT_RU_VARIABLE (ID_, REV_, TYPE_, NAME_, PROC_INST_ID_, EXECUTION_ID_, TASK_ID_, BYTEARRAY_ID_, DOUBLE_, LONG_ , TEXT_, TEXT2_) values ( ?, 1, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? ) Parameters: 13(String), string(String), applyUserId(String), 12(String), 12(String), null, null, null, null, kafeitu(String), null
insert HistoricVariableInstanceEntity[id=13, name=applyUserId, revision=0, type=string, textValue=kafeitu]
Preparing: insert into ACT_HI_VARINST (ID_, PROC_INST_ID_, EXECUTION_ID_, TASK_ID_, NAME_, REV_, VAR_TYPE_, BYTEARRAY_ID_, DOUBLE_, LONG_ , TEXT_, TEXT2_, CREATE_TIME_, LAST_UPDATED_TIME_) values ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? ) Parameters: 13(String), 12(String), 12(String), null, applyUserId(String), 0(Integer), string(String), null, null, null, kafeitu(String), null, 2015-05-05 15:27:45.127(Timestamp), 2015-05-05 15:27:45.127(Timestamp)
insert IdentityLinkEntity[id=14, type=starter, userId=kafeitu, processInstanceId=12]
Preparing: insert into ACT_RU_IDENTITYLINK (ID_, REV_, TYPE_, USER_ID_, GROUP_ID_, TASK_ID_, PROC_INST_ID_, PROC_DEF_ID_) values (?, 1, ?, ?, ?, ?, ?, ?) Parameters: 14(String), starter(String), kafeitu(String), null, null, 12(String), null
insert org.activiti.engine.impl.persistence.entity.HistoricIdentityLinkEntity@f2818d
Preparing: insert into ACT_HI_IDENTITYLINK (ID_, TYPE_, USER_ID_, GROUP_ID_, TASK_ID_, PROC_INST_ID_) values (?, ?, ?, ?, ?, ?) Parameters: 14(String), starter(String), kafeitu(String), null, null, 12(String)
insert HistoricProcessInstanceEntity[superProcessInstanceId=null]
Preparing: insert into ACT_HI_PROCINST ( ID_, PROC_INST_ID_, BUSINESS_KEY_, PROC_DEF_ID_, START_TIME_, END_TIME_, DURATION_, START_USER_ID_, START_ACT_ID_, END_ACT_ID_, SUPER_PROCESS_INSTANCE_ID_, DELETE_REASON_, TENANT_ID_, NAME_ ) values ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? ) Parameters: 12(String), 12(String), 2(String), leave:1:20(String), 2015-05-05 15:27:45.206(Timestamp), null, null, kafeitu(String), startevent1(String), null, null, null, (String), null
insert HistoricActivityInstanceEntity[activityId=startevent1, activityName=Start]
Preparing: insert into ACT_HI_ACTINST ( ID_, PROC_DEF_ID_, PROC_INST_ID_, EXECUTION_ID_, ACT_ID_, TASK_ID_, CALL_PROC_INST_ID_, ACT_NAME_, ACT_TYPE_, ASSIGNEE_, START_TIME_, END_TIME_, DURATION_, TENANT_ID_ ) values ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? ) Parameters: 15(String), leave:1:20(String), 12(String), 12(String), startevent1(String), null, null, Start(String), startEvent(String), null, 2015-05-05 15:27:45.206(Timestamp), 2015-05-05 15:27:45.268(Timestamp), 62(Long), (String)
insert HistoricActivityInstanceEntity[activityId=deptLeaderAudit, activityName=部门领导审批]
Preparing: insert into ACT_HI_ACTINST ( ID_, PROC_DEF_ID_, PROC_INST_ID_, EXECUTION_ID_, ACT_ID_, TASK_ID_, CALL_PROC_INST_ID_, ACT_NAME_, ACT_TYPE_, ASSIGNEE_, START_TIME_, END_TIME_, DURATION_, TENANT_ID_ ) values ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? ) Parameters: 16(String), leave:1:20(String), 12(String), 12(String), deptLeaderAudit(String), 17(String), null, 部门领导审批(String), userTask(String), null, 2015-05-05 15:27:45.268(Timestamp), null, null, (String)
insert Task[id=17, name=部门领导审批]
Preparing: insert into ACT_RU_TASK (ID_, REV_, NAME_, PARENT_TASK_ID_, DESCRIPTION_, PRIORITY_, CREATE_TIME_, OWNER_, ASSIGNEE_, DELEGATION_, EXECUTION_ID_, PROC_INST_ID_, PROC_DEF_ID_, TASK_DEF_KEY_, DUE_DATE_, CATEGORY_, SUSPENSION_STATE_, TENANT_ID_, FORM_KEY_) values (?, 1, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? ) Parameters: 17(String), 部门领导审批(String), null, null, 50(Integer), 2015-05-05 15:27:45.268(Timestamp), null, null, null, 12(String), 12(String), leave:1:20(String), deptLeaderAudit(String), null, null, 1(Integer), (String), null
insert org.activiti.engine.impl.persistence.entity.HistoricTaskInstanceEntity@1177565
Preparing: insert into ACT_HI_TASKINST ( ID_, PROC_DEF_ID_, PROC_INST_ID_, EXECUTION_ID_, NAME_, PARENT_TASK_ID_, DESCRIPTION_, OWNER_, ASSIGNEE_, START_TIME_, CLAIM_TIME_, END_TIME_, DURATION_, DELETE_REASON_, TASK_DEF_KEY_, FORM_KEY_, PRIORITY_, DUE_DATE_, CATEGORY_, TENANT_ID_ ) values ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? ) Parameters: 17(String), leave:1:20(String), 12(String), 12(String), 部门领导审批(String), null, null, null, null, 2015-05-05 15:27:45.268(Timestamp), null, null, null, null, deptLeaderAudit(String), null, 50(Integer), null, null, (String)
insert IdentityLinkEntity[id=18, type=candidate, groupId=deptLeader, taskId=17]
Preparing: insert into ACT_RU_IDENTITYLINK (ID_, REV_, TYPE_, USER_ID_, GROUP_ID_, TASK_ID_, PROC_INST_ID_, PROC_DEF_ID_) values (?, 1, ?, ?, ?, ?, ?, ?) Parameters: 18(String), candidate(String), null, deptLeader(String), 17(String), null, null
insert org.activiti.engine.impl.persistence.entity.HistoricIdentityLinkEntity@11c4ef6
Preparing: insert into ACT_HI_IDENTITYLINK (ID_, TYPE_, USER_ID_, GROUP_ID_, TASK_ID_, PROC_INST_ID_) values (?, ?, ?, ?, ?, ?) Parameters: 18(String), candidate(String), null, deptLeader(String), 17(String), null
--- StartProcessInstanceCmd finished --------------------------------------------------------
start process of {key=leave, bkey=2, pid=12, variables={}}
可以看到,
每次启动流程实例,首先会去ACT_GE_PROPERTY表取next.dbid,即流程实例ID;
启动流程的核心的部分就是往ACT_RU_*表中添加当前运行流程实例信息,往ACT_HI_*表中记录流程实例历史数据,当前流程实例和流程任务同步添加到运行表和历史表中。
ACT_RU_EXECUTION表记录运行中流程实例,ACT_RU_TASK表记录运行中的流程实例当前任务,
当流程跳转时,ACT_RU_EXECUTION表中记录是更新的(update),ACT_RU_TASK表中记录是先新增(insert)新任务后删除(delete)旧任务。
ps:
关于流程变量,流程启动时会在act_ru_variable和act_hi_varinst表中都记录变量,记录流程发起人(对应bpmn中的activiti:initiator)的NAME_为applyUserId,TEXT_为流程启动用户,比如:kafeitu;
刚才也提到我们代码中可以设置其它流程变量,修改代码
Map<String, Object> variables = new HashMap<String, Object>();variables.put("testKey", "testValue");然后测试启动一个新的流程,发现act_ru_variable和act_hi_varinst表中确实各多了一条记录
然后编写测试用例
/** * 测试获取流程变量 * @throws Exception */@Testpublic void testGetVariable(){String pid = "2524";Map<String, Object> variables = taskService.getVariables(pid);Set<String> keySet = variables.keySet();for(String key : keySet){System.out.println(key);}}打印日志如:
--- starting GetTaskVariablesCmd --------------------------------------------------------
Running command with propagation REQUIRED
Preparing: select * from ACT_RU_TASK where ID_ = ?
Parameters: 2524(String)
Total: 1
Preparing: select * from ACT_RU_VARIABLE where TASK_ID_ = ?
Parameters: 2524(String)
Total: 0
Preparing: select * from ACT_RU_EXECUTION where ID_ = ?
Parameters: 2512(String)
Total: 1
[
Preparing: select * from ACT_RU_VARIABLE where EXECUTION_ID_ = ? and TASK_ID_ is null
Parameters: 2512(String)
Total: 3
--- GetTaskVariablesCmd finished --------------------------------------------------------
输出:
applyUserId
testKey
deptLeaderPass
可见这些变量都不是作为某个任务的变量存储在数据库中的,而是和整个流程实例关联。
- 普通表单——流程启动
- 普通表单——任务列表
- Android—launcher 启动流程
- 内核启动流程—走马观花
- 关于在表单中启动其它流程的方法
- activiti 动态表单+easyui 实现启动流程功能(一)
- activiti 动态表单+easyui 实现启动流程功能(二)
- activiti 动态表单+easyui 实现启动流程功能(三)
- U-boot启动流程——eloader
- Android启动流程——Home Launcher
- Ejabberd源码学习——启动流程
- ActivityManagerService分析——AMS启动流程
- Qualcomm Simlock——启动检测流程
- SpringBoot——run启动流程
- IT运维管理——流程与表单定义
- nginx源码分析—启动流程
- nginx源码分析—启动流程
- uboot 启动流程分析(二) — 第二阶段
- Meteor Shower 广搜
- linux下RAID磁盘阵列说明
- java获得内部类对象的方法
- 应届大学毕业生户口迁移须知
- JSTL表达式在项目中的使用
- 普通表单——流程启动
- hdu 2955 Robberies
- 网站优化投票策略仅仅是外链制作吗?
- 【ImageLoader】Android-Universal-Image-Loader 图片异步加载类库的使用(超详细配置)
- WPF 4.5 和 CSharp (2.1) XAML中的属性和事件
- CountDownLatch线程同步助手
- 基于概率论的分类方法:朴素贝叶斯
- 欧拉角与万向节死锁
- IOC容器概述