普通表单——流程启动

来源:互联网 发布:知有儿童挑促织 编辑:程序博客网 时间: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

可见这些变量都不是作为某个任务的变量存储在数据库中的,而是和整个流程实例关联。

1 0
原创粉丝点击