中文版手册, http://www.mossle.com/docs/activiti/index.html
1.待办任务管理

/** * 根据用户id分页查询任务 * @param page * @param rows * @param s_name * @param response * @return * @throws Exception */ @RequestMapping("/list") public String list(@RequestParam(value="page",required=false)String page,@RequestParam(value="rows",required=false)String rows,String s_name,String userId,HttpServletResponse response)throws Exception{ if(s_name==null){ s_name=""; } PageBean pageBean=new PageBean(Integer.parseInt(page),Integer.parseInt(rows)); List<Task> list=taskService.createTaskQuery() // 创建任务查询 .taskCandidateUser(userId) // 根据用户id查询 .taskNameLike("%"+s_name+"%") // 根据任务名称查询 .listPage(pageBean.getStart(), pageBean.getPageSize()); // 返回带分页的结果集合 //自定义任务实体 转json的时候用到,把需要的数据提取 List<MyTask> taskList=new ArrayList<MyTask>(); for(Task t:list){ MyTask myTask=new MyTask(); myTask.setId(t.getId()); myTask.setName(t.getName()); myTask.setCreateTime(t.getCreateTime()); taskList.add(myTask); } long total=taskService.createTaskQuery().taskCandidateUser(userId).taskNameLike("%"+s_name+"%").count(); // 获取总记录数 JsonConfig jsonConfig=new JsonConfig(); jsonConfig.registerJsonValueProcessor(java.util.Date.class, new DateJsonValueProcessor("yyyy-MM-dd hh:mm:ss")); JSONObject result=new JSONObject(); JSONArray jsonArray=JSONArray.fromObject(taskList,jsonConfig); result.put("rows", jsonArray); result.put("total", total); ResponseUtil.write(response, result); return null; }
查看当前流程图,因为是正在运行的任务,用taskService(比较快捷,运行表中的数据量没有历史表的多) ---task---processDefinitionId--processDefinition---图片资源文件。

/** * 查询当前流程图 代办用的 * @param taskId * @param response * @return * @throws Exception */ @RequestMapping("/showCurrentView") public ModelAndView showCurrentView(String taskId,HttpServletResponse response)throws Exception{ ModelAndView mav=new ModelAndView(); Task task=taskService.createTaskQuery() // 创建任务查询 .taskId(taskId) // 根据任务id查询 .singleResult(); String processDefinitionId=task.getProcessDefinitionId(); // 获取流程定义id ProcessDefinition processDefinition=repositoryService.createProcessDefinitionQuery() // 创建流程定义查询 .processDefinitionId(processDefinitionId) // 根据流程定义id查询 .singleResult(); mav.addObject("deploymentId",processDefinition.getDeploymentId()); // 部署id mav.addObject("diagramResourceName", processDefinition.getDiagramResourceName()); // 图片资源文件名称 ProcessDefinitionEntity processDefinitionEntity=(ProcessDefinitionEntity) repositoryService.getProcessDefinition(processDefinitionId); String processInstanceId=task.getProcessInstanceId(); // 获取流程实例id ProcessInstance pi=runtimeService.createProcessInstanceQuery() // 根据流程实例id获取流程实例 .processInstanceId(processInstanceId) .singleResult(); ActivityImpl activityImpl=processDefinitionEntity.findActivity(pi.getActivityId()); // 根据活动id获取活动实例,流程图的xml信息 mav.addObject("x", activityImpl.getX()); // x坐标 mav.addObject("y", activityImpl.getY()); // y坐标 mav.addObject("width", activityImpl.getWidth()); // 宽度 mav.addObject("height", activityImpl.getHeight()); // 高度 mav.setViewName("page/currentView"); return mav; }
重定向审核处理页面,使用formService获取form key(存在bpmn文件中) 中的跳转url.

/** * 重定向审核处理页面 * @param taskId * @param response * @return * @throws Exception */ @RequestMapping("/redirectPage") public String redirectPage(String taskId,HttpServletResponse response)throws Exception{ TaskFormData formData=formService.getTaskFormData(taskId); String url=formData.getFormKey(); JSONObject result=new JSONObject(); result.put("url", url); ResponseUtil.write(response, result); return null; }
把业务数据加载到审核页面,通过taskId 和 流程变量名称找到leaveId, 再找到leave对象

/** * 通过任务id获取请假单 * @param taskId * @param response * @return * @throws Exception */ @RequestMapping("/getLeaveByTaskId") public String getLeaveByTaskId(String taskId,HttpServletResponse response)throws Exception{ //通过taskId 和 流程变量名称找到leaveId Integer leaveId=(Integer) taskService.getVariable(taskId, "leaveId"); Leave leave=leaveService.findById(leaveId); JSONObject result=new JSONObject(); result.put("leave", JSONObject.fromObject(leave)); ResponseUtil.write(response, result); return null; }
通过taskId 加载历史审批意见(同下,这里就略过),审核处理(通过或者不通过),中间审批环节和最终审批环节有的不同,中间的要把(请假天数)流转的判断条件设置到流程变量,最终的审批完了还要更新业务状态。
注意:添加批注的时候,由于Activiti底层代码是使用:
String userId = Authentication.getAuthenticatedUserId();
CommentEntity comment = new CommentEntity();
comment.setUserId(userId);
所有需要从Session中获取当前登录人,作为该任务的办理人(审核人),对应act_hi_comment表中的User_ID的字段,不过不添加审核人,该字段为null
所以要求,添加配置执行使用Authentication.setAuthenticatedUserId();添加当前任务的审核人

/** * 班长审批 * @param taskId 任务id * @param leaveDays 请假天数 * @param comment 批注信息 * @param state 审核状态 1 通过 2 驳回 * @param response * @param session * @return * @throws Exception */ @RequestMapping("/audit_bz") public String audit_bz(String taskId,Integer leaveDays,String comment,Integer state,HttpServletResponse response,HttpSession session)throws Exception{ Task task=taskService.createTaskQuery() // 创建任务查询 .taskId(taskId) // 根据任务id查询 .singleResult(); Map<String,Object> variables=new HashMap<String,Object>(); if(state==1){ variables.put("msg", "通过"); }else{ Integer leaveId=(Integer) taskService.getVariable(taskId, "leaveId"); Leave leave=leaveService.findById(leaveId); leave.setState("审核未通过"); leaveService.update(leave); // 更新审核信息 variables.put("msg", "未通过"); } variables.put("days", leaveDays); // 设置流程变量, 请假天数的判断条件,根据天数的不同流向不同的审核人。 String processInstanceId=task.getProcessInstanceId(); // 获取流程实例id MemberShip currentMemberShip=(MemberShip) session.getAttribute("currentMemberShip"); User currentUser=currentMemberShip.getUser(); Group currentGroup=currentMemberShip.getGroup(); //用户权限认证 Authentication.setAuthenticatedUserId(currentUser.getFirstName()+currentUser.getLastName()+"["+currentGroup.getName()+"]"); // 设置用户id taskService.addComment(taskId, processInstanceId, comment); // 添加批注信息 taskService.complete(taskId, variables); // 完成任务 JSONObject result=new JSONObject(); result.put("success", true); ResponseUtil.write(response, result); return null; } /** * 领导审批 * @param taskId 任务id * @param comment 批注信息 * @param state 审核状态 1 通过 2 驳回 * @param response * @param session * @return * @throws Exception */ @RequestMapping("/audit_ld") public String audit_ld(String taskId,String comment,Integer state,HttpServletResponse response,HttpSession session)throws Exception{ Task task=taskService.createTaskQuery() // 创建任务查询 .taskId(taskId) // 根据任务id查询 .singleResult(); Integer leaveId=(Integer) taskService.getVariable(taskId, "leaveId"); Leave leave=leaveService.findById(leaveId); if(state==1){ leave.setState("审核通过"); leaveService.update(leave); // 更新审核信息,这里是最后的审批,中间环节就不要更新。 }else{ leave.setState("审核未通过"); leaveService.update(leave); // 更新审核信息 } String processInstanceId=task.getProcessInstanceId(); // 获取流程实例id MemberShip currentMemberShip=(MemberShip) session.getAttribute("currentMemberShip"); User currentUser=currentMemberShip.getUser(); Group currentGroup=currentMemberShip.getGroup(); Authentication.setAuthenticatedUserId(currentUser.getFirstName()+currentUser.getLastName()+"["+currentGroup.getName()+"]"); // 设置用户id taskService.addComment(taskId, processInstanceId, comment); // 添加批注信息 taskService.complete(taskId); // 完成任务 JSONObject result=new JSONObject(); result.put("success", true); ResponseUtil.write(response, result); return null; }
请假单流程图的xml信息, 有通过和不通过的判断条件,还要请假天数的判断条件,根据天数的不同流向不同的审核人。

<process id="studentLeaveProcess" name="Student Levae process" isExecutable="true">
<startEvent id="startevent1" name="Start"></startEvent>
<userTask id="usertask1" name="学生填写请假单" activiti:candidateGroups="xs"></userTask>
<userTask id="usertask2" name="班长审批" activiti:candidateGroups="bz" activiti:formKey="audit_bz.jsp"></userTask>
<userTask id="usertask3" name="班主任审批" activiti:candidateGroups="bzr" activiti:formKey="audit_ld.jsp"></userTask>
<userTask id="usertask4" name="系辅导员审批" activiti:candidateGroups="xfdy" activiti:formKey="audit_ld.jsp"></userTask>
<userTask id="usertask5" name="学生处审批" activiti:candidateGroups="xsc" activiti:formKey="audit_ld.jsp"></userTask>
<endEvent id="endevent1" name="End"></endEvent>
<exclusiveGateway id="exclusivegateway1" name="Exclusive Gateway" default="flow6"></exclusiveGateway>
<sequenceFlow id="flow1" sourceRef="startevent1" targetRef="usertask1"></sequenceFlow>
<sequenceFlow id="flow2" sourceRef="usertask1" targetRef="usertask2"></sequenceFlow>
<sequenceFlow id="flow3" name="通过" sourceRef="usertask2" targetRef="exclusivegateway1">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${msg=='通过'}]]></conditionExpression>
</sequenceFlow>
<sequenceFlow id="flow4" name="大于3天" sourceRef="exclusivegateway1" targetRef="usertask3">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${days<3}]]></conditionExpression>
</sequenceFlow>
<sequenceFlow id="flow5" name="3天到7天" sourceRef="exclusivegateway1" targetRef="usertask4">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${days>=3 && days<=7}]]></conditionExpression>
</sequenceFlow>
<sequenceFlow id="flow6" name="大于7天" sourceRef="exclusivegateway1" targetRef="usertask5"></sequenceFlow>
<sequenceFlow id="flow7" sourceRef="usertask3" targetRef="endevent1"></sequenceFlow>
<sequenceFlow id="flow8" sourceRef="usertask4" targetRef="endevent1"></sequenceFlow>
<sequenceFlow id="flow9" sourceRef="usertask5" targetRef="endevent1"></sequenceFlow>
<sequenceFlow id="flow10" name="未通过" sourceRef="usertask2" targetRef="endevent1">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${msg=='未通过'}]]></conditionExpression>
</sequenceFlow>
</process>
2.已办任务管理
已办但未结束,把正在运行的交给RuntimeService、TaskService管理,而历史数据交给HistoryService来管理。

/** * 流程实例未走完的历史任务 * @param page * @param rows * @param s_name * @param groupId * @param userId * @param response * @return * @throws Exception */ @RequestMapping("/unFinishedList") public String unFinishedList(@RequestParam(value="page",required=false)String page,@RequestParam(value="rows",required=false)String rows,String s_name,String groupId,String userId,HttpServletResponse response)throws Exception{ if(s_name==null){ s_name=""; } PageBean pageBean=new PageBean(Integer.parseInt(page),Integer.parseInt(rows)); List<HistoricTaskInstance> htiList=historyService.createHistoricTaskInstanceQuery() // 创建历史任务实例查询 .taskCandidateGroup(groupId) // 根据角色查询 .taskNameLike("%"+s_name+"%") // 根据任务名称查询 .list(); List<MyTask> taskList=new ArrayList<MyTask>(); for(HistoricTaskInstance hti:htiList){ //taskService 是查询正在执行的任务,不为null 表示此流程实例的任务还未完成, 后面那个判断表示当前用户的任务已经完结,在运行的查不到数据 if((taskService.createTaskQuery().processInstanceId(hti.getProcessInstanceId()).singleResult()!=null) &&(taskService.createTaskQuery().taskCandidateUser(userId).taskId(hti.getId()).list().size()==0)){ MyTask myTask=new MyTask(); myTask.setId(hti.getId()); myTask.setName(hti.getName()); myTask.setCreateTime(hti.getCreateTime()); myTask.setEndTime(hti.getEndTime()); taskList.add(myTask); } } //分页操作,截取相应页面的数据 if(taskList.size()>(pageBean.getStart()+pageBean.getPageSize())){ taskList=taskList.subList(pageBean.getStart(), pageBean.getStart()+pageBean.getPageSize()); } JsonConfig jsonConfig=new JsonConfig(); jsonConfig.registerJsonValueProcessor(java.util.Date.class, new DateJsonValueProcessor("yyyy-MM-dd hh:mm:ss")); JSONObject result=new JSONObject(); JSONArray jsonArray=JSONArray.fromObject(taskList,jsonConfig); result.put("rows", jsonArray); result.put("total", taskList.size()); ResponseUtil.write(response, result); return null; }
查看当前流程图,因为是已办任务,需要用historyService---HistoricTaskInstance----processDefinitionId--processDefinition---图片资源文

/** * 查询当前流程图 已办用到的 * @param taskId * @param response * @return * @throws Exception */ @RequestMapping("/showHisCurrentView") public ModelAndView showHisCurrentView(String taskId,HttpServletResponse response)throws Exception{ ModelAndView mav=new ModelAndView(); HistoricTaskInstance hti=historyService.createHistoricTaskInstanceQuery().taskId(taskId).singleResult(); String processDefinitionId=hti.getProcessDefinitionId(); // 获取流程定义id ProcessDefinition processDefinition=repositoryService.createProcessDefinitionQuery() // 创建流程定义查询 .processDefinitionId(processDefinitionId) // 根据流程定义id查询 .singleResult(); mav.addObject("deploymentId",processDefinition.getDeploymentId()); // 部署id mav.addObject("diagramResourceName", processDefinition.getDiagramResourceName()); // 图片资源文件名称 ProcessDefinitionEntity processDefinitionEntity=(ProcessDefinitionEntity) repositoryService.getProcessDefinition(processDefinitionId); String processInstanceId=hti.getProcessInstanceId(); // 获取流程实例id ProcessInstance pi=runtimeService.createProcessInstanceQuery() // 根据流程实例id获取流程实例 .processInstanceId(processInstanceId) .singleResult(); ActivityImpl activityImpl=processDefinitionEntity.findActivity(pi.getActivityId()); // 根据活动id获取活动实例 mav.addObject("x", activityImpl.getX()); // x坐标 mav.addObject("y", activityImpl.getY()); // y坐标 mav.addObject("width", activityImpl.getWidth()); // 宽度 mav.addObject("height", activityImpl.getHeight()); // 高度 mav.setViewName("page/currentView"); return mav; }
历史批注查询 根据任务id

/** * 历史批注查询 根据任务id * @param taskId * @param response * @return * @throws Exception */ @RequestMapping("/listHistoryComment") public String listHistoryComment(String taskId,HttpServletResponse response)throws Exception{ if(taskId==null){ return null; } HistoricTaskInstance hti=historyService.createHistoricTaskInstanceQuery().taskId(taskId).singleResult(); List<Comment> commentList=taskService.getProcessInstanceComments(hti.getProcessInstanceId()); Collections.reverse(commentList); // 集合元素反转 JsonConfig jsonConfig=new JsonConfig(); jsonConfig.registerJsonValueProcessor(java.util.Date.class, new DateJsonValueProcessor("yyyy-MM-dd hh:mm:ss")); JSONObject result=new JSONObject(); JSONArray jsonArray=JSONArray.fromObject(commentList,jsonConfig); result.put("rows", jsonArray); ResponseUtil.write(response, result); return null; }
流程执行过程列表,查询活动节点使用createHistoricActivityInstanceQuery(),如果只查历史任务就用createHistoricTaskInstanceQuery(),

/** * 根据任务id查询流程实例的具体执行过程 * @param taskId * @param response * @return * @throws Exception */ @RequestMapping("/listAction") public String listAction(String taskId,HttpServletResponse response)throws Exception{ HistoricTaskInstance hti=historyService.createHistoricTaskInstanceQuery().taskId(taskId).singleResult(); String processInstanceId=hti.getProcessInstanceId(); // 获取流程实例id List<HistoricActivityInstance> haiList=historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).list(); //如果只查历史任务就用createHistoricTaskInstanceQuery() //List<HistoricTaskInstance> htiList= historyService.createHistoricTaskInstanceQuery().processInstanceId(processInstanceId).list(); JsonConfig jsonConfig=new JsonConfig(); jsonConfig.registerJsonValueProcessor(java.util.Date.class, new DateJsonValueProcessor("yyyy-MM-dd hh:mm:ss")); JSONObject result=new JSONObject(); JSONArray jsonArray=JSONArray.fromObject(haiList,jsonConfig); result.put("rows", jsonArray); ResponseUtil.write(response, result); return null; }
3.历史任务管理

/** * 流程实例走完的历史任务 * @param page * @param rows * @param s_name * @param groupId * @param userId * @param response * @return * @throws Exception */ @RequestMapping("/finishedList") public String finishedList(@RequestParam(value="page",required=false)String page,@RequestParam(value="rows",required=false)String rows,String s_name,String groupId,HttpServletResponse response)throws Exception{ if(s_name==null){ s_name=""; } PageBean pageBean=new PageBean(Integer.parseInt(page),Integer.parseInt(rows)); List<HistoricTaskInstance> htiList=historyService.createHistoricTaskInstanceQuery() //创建历史任务实例查询 .taskCandidateGroup(groupId) // 根据角色查询 .taskNameLike("%"+s_name+"%") // 根据任务名称查询 .list(); List<MyTask> taskList=new ArrayList<MyTask>(); for(HistoricTaskInstance hti:htiList){ //==null 表示此流程实例的正在运行的任务没有了 if((taskService.createTaskQuery().processInstanceId(hti.getProcessInstanceId()).singleResult()==null)){ MyTask myTask=new MyTask(); myTask.setId(hti.getId()); myTask.setName(hti.getName()); myTask.setCreateTime(hti.getCreateTime()); myTask.setEndTime(hti.getEndTime()); taskList.add(myTask); } } if(taskList.size()>(pageBean.getStart()+pageBean.getPageSize())){ taskList=taskList.subList(pageBean.getStart(), pageBean.getStart()+pageBean.getPageSize()); } JsonConfig jsonConfig=new JsonConfig(); jsonConfig.registerJsonValueProcessor(java.util.Date.class, new DateJsonValueProcessor("yyyy-MM-dd hh:mm:ss")); JSONObject result=new JSONObject(); JSONArray jsonArray=JSONArray.fromObject(taskList,jsonConfig); result.put("rows", jsonArray); result.put("total", taskList.size()); ResponseUtil.write(response, result); return null; }
查看流程图, 通过taskId---HistoricTaskInstance----processDefinitionId----ProcessDefinition--图片资源文件

/** * 查看流程图 * @param deploymentId * @param diagramResourceName * @param response * @return * @throws Exception */ @RequestMapping("/showViewByTaskId") public String showViewByTaskId(String taskId,HttpServletResponse response)throws Exception{ HistoricTaskInstance hti=historyService.createHistoricTaskInstanceQuery().taskId(taskId).singleResult(); String processDefinitionId=hti.getProcessDefinitionId(); // 获取流程定义id ProcessDefinition pd=repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult(); InputStream inputStream=repositoryService.getResourceAsStream(pd.getDeploymentId(), pd.getDiagramResourceName()); OutputStream out=response.getOutputStream(); for(int b=-1;(b=inputStream.read())!=-1;){ out.write(b); } out.close(); inputStream.close(); return null; }
按分组查询相应任务,相应的审批页面放在form key 中