activiti流程
package cn.demo.service.impl; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.zip.ZipInputStream; import org.activiti.engine.FormService; import org.activiti.engine.HistoryService; import org.activiti.engine.RepositoryService; import org.activiti.engine.RuntimeService; import org.activiti.engine.TaskService; import org.activiti.engine.form.TaskFormData; import org.activiti.engine.history.HistoricProcessInstance; import org.activiti.engine.history.HistoricVariableInstance; import org.activiti.engine.impl.identity.Authentication; import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity; import org.activiti.engine.impl.pvm.PvmTransition; import org.activiti.engine.impl.pvm.process.ActivityImpl; import org.activiti.engine.repository.Deployment; import org.activiti.engine.repository.ProcessDefinition; import org.activiti.engine.runtime.ProcessInstance; import org.activiti.engine.task.Comment; import org.activiti.engine.task.Task; import org.apache.commons.lang.StringUtils; import cn.itcast.ssh.dao.ILeaveBillDao; import cn.itcast.ssh.domain.LeaveBill; import cn.itcast.ssh.service.IWorkflowService; import cn.itcast.ssh.utils.SessionContext; import cn.itcast.ssh.web.form.WorkflowBean; public class WorkflowServiceImpl implements IWorkflowService { /**请假申请Dao*/ private ILeaveBillDao leaveBillDao; private RepositoryService repositoryService; private RuntimeService runtimeService; private TaskService taskService; private FormService formService; private HistoryService historyService; public void setLeaveBillDao(ILeaveBillDao leaveBillDao) { this.leaveBillDao = leaveBillDao; } public void setHistoryService(HistoryService historyService) { this.historyService = historyService; } public void setFormService(FormService formService) { this.formService = formService; } public void setRuntimeService(RuntimeService runtimeService) { this.runtimeService = runtimeService; } public void setTaskService(TaskService taskService) { this.taskService = taskService; } public void setRepositoryService(RepositoryService repositoryService) { this.repositoryService = repositoryService; } /**部署流程定义*/ @Override public void saveNewDeploye(File file, String filename) { try { //2:将File类型的文件转化成ZipInputStream流 ZipInputStream zipInputStream = new ZipInputStream(new FileInputStream(file)); repositoryService.createDeployment()//创建部署对象 .name(filename)//添加部署名称 .addZipInputStream(zipInputStream)// .deploy();//完成部署 } catch (Exception e) { e.printStackTrace(); } } /**查询部署对象信息,对应表(act_re_deployment)*/ @Override public List<Deployment> findDeploymentList() { List<Deployment> list = repositoryService.createDeploymentQuery()//创建部署对象查询 .orderByDeploymenTime().asc()// .list(); return list; } /**查询流程定义的信息,对应表(act_re_procdef)*/ @Override public List<ProcessDefinition> findProcessDefinitionList() { List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery()//创建流程定义查询 .orderByProcessDefinitionVersion().asc()// .list(); return list; } /**使用部署对象ID和资源图片名称,获取图片的输入流*/ @Override public InputStream findImageInputStream(String deploymentId, String imageName) { return repositoryService.getResourceAsStream(deploymentId, imageName); } /**使用部署对象ID,删除流程定义*/ @Override public void deleteProcessDefinitionByDeploymentId(String deploymentId) { repositoryService.deleteDeployment(deploymentId, true); } /**更新请假状态,启动流程实例,让启动的流程实例关联业务*/ @Override public void saveStartProcess(WorkflowBean workflowBean) { //1:获取请假单ID,使用请假单ID,查询请假单的对象LeaveBill Long id = workflowBean.getId(); LeaveBill leaveBill = leaveBillDao.findLeaveBillById(id); //2:更新请假单的请假状态从0变成1(初始录入-->审核中) leaveBill.setState(1); //3:使用当前对象获取到流程定义的key(对象的名称就是流程定义的key) String key = leaveBill.getClass().getSimpleName(); /** * 4:从Session中获取当前任务的办理人,使用流程变量设置下一个任务的办理人 * inputUser是流程变量的名称, * 获取的办理人是流程变量的值 */ Map<String, Object> variables = new HashMap<String,Object>(); variables.put("inputUser", SessionContext.get().getName());//表示惟一用户 /** * 5: (1)使用流程变量设置字符串(格式:LeaveBill.id的形式),通过设置,让启动的流程(流程实例)关联业务 (2)使用正在执行对象表中的一个字段BUSINESS_KEY(Activiti提供的一个字段),让启动的流程(流程实例)关联业务 */ //格式:LeaveBill.id的形式(使用流程变量) String objId = key+"."+id; variables.put("objId", objId); //6:使用流程定义的key,启动流程实例,同时设置流程变量,同时向正在执行的执行对象表中的字段BUSINESS_KEY添加业务数据,同时让流程关联业务 runtimeService.startProcessInstanceByKey(key,objId,variables); } /**2:使用当前用户名查询正在执行的任务表,获取当前任务的集合List<Task>*/ @Override public List<Task> findTaskListByName(String name) { List<Task> list = taskService.createTaskQuery()// .taskAssignee(name)//指定个人任务查询 .orderByTaskCreateTime().asc()// .list(); return list; } /**使用任务ID,获取当前任务节点中对应的Form key中的连接的值*/ @Override public String findTaskFormKeyByTaskId(String taskId) { TaskFormData formData = formService.getTaskFormData(taskId); //获取Form key的值 String url = formData.getFormKey(); return url; } /**一:使用任务ID,查找请假单ID,从而获取请假单信息*/ @Override public LeaveBill findLeaveBillByTaskId(String taskId) { //1:使用任务ID,查询任务对象Task Task task = taskService.createTaskQuery()// .taskId(taskId)//使用任务ID查询 .singleResult(); //2:使用任务对象Task获取流程实例ID String processInstanceId = task.getProcessInstanceId(); //3:使用流程实例ID,查询正在执行的执行对象表,返回流程实例对象 ProcessInstance pi = runtimeService.createProcessInstanceQuery()// .processInstanceId(processInstanceId)//使用流程实例ID查询 .singleResult(); //4:使用流程实例对象获取BUSINESS_KEY String buniness_key = pi.getBusinessKey(); //5:获取BUSINESS_KEY对应的主键ID,使用主键ID,查询请假单对象(LeaveBill.1) String id = ""; if(StringUtils.isNotBlank(buniness_key)){ //截取字符串,取buniness_key小数点的第2个值 id = buniness_key.split("\\.")[1]; } //查询请假单对象 //使用hql语句:from LeaveBill o where o.id=1 LeaveBill leaveBill = leaveBillDao.findLeaveBillById(Long.parseLong(id)); return leaveBill; } /**二:已知任务ID,查询ProcessDefinitionEntiy对象,从而获取当前任务完成之后的连线名称,并放置到List<String>集合中*/ @Override public List<String> findOutComeListByTaskId(String taskId) { //返回存放连线的名称集合 List<String> list = new ArrayList<String>(); //1:使用任务ID,查询任务对象 Task task = taskService.createTaskQuery()// .taskId(taskId)//使用任务ID查询 .singleResult(); //2:获取流程定义ID String processDefinitionId = task.getProcessDefinitionId(); //3:查询ProcessDefinitionEntiy对象 ProcessDefinitionEntity processDefinitionEntity = (ProcessDefinitionEntity) repositoryService.getProcessDefinition(processDefinitionId); //使用任务对象Task获取流程实例ID String processInstanceId = task.getProcessInstanceId(); //使用流程实例ID,查询正在执行的执行对象表,返回流程实例对象 ProcessInstance pi = runtimeService.createProcessInstanceQuery()// .processInstanceId(processInstanceId)//使用流程实例ID查询 .singleResult(); //获取当前活动的id String activityId = pi.getActivityId(); //4:获取当前的活动 ActivityImpl activityImpl = processDefinitionEntity.findActivity(activityId); //5:获取当前活动完成之后连线的名称 List<PvmTransition> pvmList = activityImpl.getOutgoingTransitions(); if(pvmList!=null && pvmList.size()>0){ for(PvmTransition pvm:pvmList){ String name = (String) pvm.getProperty("name"); if(StringUtils.isNotBlank(name)){ list.add(name); } else{ list.add("默认提交"); } } } return list; } /**指定连线的名称完成任务*/ @Override public void saveSubmitTask(WorkflowBean workflowBean) { //获取任务ID String taskId = workflowBean.getTaskId(); //获取连线的名称 String outcome = workflowBean.getOutcome(); //批注信息 String message = workflowBean.getComment(); //获取请假单ID Long id = workflowBean.getId(); /** * 1:在完成之前,添加一个批注信息,向act_hi_comment表中添加数据,用于记录对当前申请人的一些审核信息 */ //使用任务ID,查询任务对象,获取流程流程实例ID Task task = taskService.createTaskQuery()// .taskId(taskId)//使用任务ID查询 .singleResult(); //获取流程实例ID String processInstanceId = task.getProcessInstanceId(); /** * 注意:添加批注的时候,由于Activiti底层代码是使用: * String userId = Authentication.getAuthenticatedUserId(); CommentEntity comment = new CommentEntity(); comment.setUserId(userId); 所有需要从Session中获取当前登录人,作为该任务的办理人(审核人),对应act_hi_comment表中的User_ID的字段,不过不添加审核人,该字段为null 所以要求,添加配置执行使用Authentication.setAuthenticatedUserId();添加当前任务的审核人 * */ Authentication.setAuthenticatedUserId(SessionContext.get().getName()); taskService.addComment(taskId, processInstanceId, message); /** * 2:如果连线的名称是“默认提交”,那么就不需要设置,如果不是,就需要设置流程变量 * 在完成任务之前,设置流程变量,按照连线的名称,去完成任务 流程变量的名称:outcome 流程变量的值:连线的名称 */ Map<String, Object> variables = new HashMap<String,Object>(); if(outcome!=null && !outcome.equals("默认提交")){ variables.put("outcome", outcome); } //3:使用任务ID,完成当前人的个人任务,同时流程变量 taskService.complete(taskId, variables); //4:当任务完成之后,需要指定下一个任务的办理人(使用类)-----已经开发完成 /** * 5:在完成任务之后,判断流程是否结束 如果流程结束了,更新请假单表的状态从1变成2(审核中-->审核完成) */ ProcessInstance pi = runtimeService.createProcessInstanceQuery()// .processInstanceId(processInstanceId)//使用流程实例ID查询 .singleResult(); //流程结束了 if(pi==null){ //更新请假单表的状态从1变成2(审核中-->审核完成) LeaveBill bill = leaveBillDao.findLeaveBillById(id); bill.setState(2); } } /**获取批注信息,传递的是当前任务ID,获取历史任务ID对应的批注*/ @Override public List<Comment> findCommentByTaskId(String taskId) { List<Comment> list = new ArrayList<Comment>(); //使用当前的任务ID,查询当前流程对应的历史任务ID //使用当前任务ID,获取当前任务对象 Task task = taskService.createTaskQuery()// .taskId(taskId)//使用任务ID查询 .singleResult(); //获取流程实例ID String processInstanceId = task.getProcessInstanceId(); // //使用流程实例ID,查询历史任务,获取历史任务对应的每个任务ID // List<HistoricTaskInstance> htiList = historyService.createHistoricTaskInstanceQuery()//历史任务表查询 // .processInstanceId(processInstanceId)//使用流程实例ID查询 // .list(); // //遍历集合,获取每个任务ID // if(htiList!=null && htiList.size()>0){ // for(HistoricTaskInstance hti:htiList){ // //任务ID // String htaskId = hti.getId(); // //获取批注信息 // List<Comment> taskList = taskService.getTaskComments(htaskId);//对用历史完成后的任务ID // list.addAll(taskList); // } // } list = taskService.getProcessInstanceComments(processInstanceId); return list; } /**使用请假单ID,查询历史批注信息*/ @Override public List<Comment> findCommentByLeaveBillId(Long id) { //使用请假单ID,查询请假单对象 LeaveBill leaveBill = leaveBillDao.findLeaveBillById(id); //获取对象的名称 String objectName = leaveBill.getClass().getSimpleName(); //组织流程表中的字段中的值 String objId = objectName+"."+id; /**1:使用历史的流程实例查询,返回历史的流程实例对象,获取流程实例ID*/ // HistoricProcessInstance hpi = historyService.createHistoricProcessInstanceQuery()//对应历史的流程实例表 // .processInstanceBusinessKey(objId)//使用BusinessKey字段查询 // .singleResult(); // //流程实例ID // String processInstanceId = hpi.getId(); /**2:使用历史的流程变量查询,返回历史的流程变量的对象,获取流程实例ID*/ HistoricVariableInstance hvi = historyService.createHistoricVariableInstanceQuery()//对应历史的流程变量表 .variableValueEquals("objId", objId)//使用流程变量的名称和流程变量的值查询 .singleResult(); //流程实例ID String processInstanceId = hvi.getProcessInstanceId(); List<Comment> list = taskService.getProcessInstanceComments(processInstanceId); return list; } /**1:获取任务ID,获取任务对象,使用任务对象获取流程定义ID,查询流程定义对象*/ @Override public ProcessDefinition findProcessDefinitionByTaskId(String taskId) { //使用任务ID,查询任务对象 Task task = taskService.createTaskQuery()// .taskId(taskId)//使用任务ID查询 .singleResult(); //获取流程定义ID String processDefinitionId = task.getProcessDefinitionId(); //查询流程定义的对象 ProcessDefinition pd = repositoryService.createProcessDefinitionQuery()//创建流程定义查询对象,对应表act_re_procdef .processDefinitionId(processDefinitionId)//使用流程定义ID查询 .singleResult(); return pd; } /** * 二:查看当前活动,获取当期活动对应的坐标x,y,width,height,将4个值存放到Map<String,Object>中 map集合的key:表示坐标x,y,width,height map集合的value:表示坐标对应的值 */ @Override public Map<String, Object> findCoordingByTask(String taskId) { //存放坐标 Map<String, Object> map = new HashMap<String,Object>(); //使用任务ID,查询任务对象 Task task = taskService.createTaskQuery()// .taskId(taskId)//使用任务ID查询 .singleResult(); //获取流程定义的ID String processDefinitionId = task.getProcessDefinitionId(); //获取流程定义的实体对象(对应.bpmn文件中的数据) ProcessDefinitionEntity processDefinitionEntity = (ProcessDefinitionEntity)repositoryService.getProcessDefinition(processDefinitionId); //流程实例ID String processInstanceId = task.getProcessInstanceId(); //使用流程实例ID,查询正在执行的执行对象表,获取当前活动对应的流程实例对象 ProcessInstance pi = runtimeService.createProcessInstanceQuery()//创建流程实例查询 .processInstanceId(processInstanceId)//使用流程实例ID查询 .singleResult(); //获取当前活动的ID String activityId = pi.getActivityId(); //获取当前活动对象 ActivityImpl activityImpl = processDefinitionEntity.findActivity(activityId);//活动ID //获取坐标 map.put("x", activityImpl.getX()); map.put("y", activityImpl.getY()); map.put("width", activityImpl.getWidth()); map.put("height", activityImpl.getHeight()); return map; } @Override public void saveNewDeploy(String filename, File file) { InputStream fileInputStream; try { fileInputStream = new FileInputStream(file); ZipInputStream zipInputStream = new ZipInputStream(fileInputStream); repositoryService.createDeployment() //创建部署对象 .name(filename) //添加部署名称 .addZipInputStream(zipInputStream) .deploy(); //完成部署 } catch (FileNotFoundException e) { e.printStackTrace(); } } @Override public InputStream findInputStreamByImageAndId(String imageName, String deploymentId) { return repositoryService.getResourceAsStream(deploymentId, imageName); } @Override public void saveStartProcessInstance(WorkflowBean workflowBean) { Long id = workflowBean.getId(); LeaveBill leaveBill = this.leaveBillDao.findLeaveBillById(id); //更新状态 leaveBill.setState(1); //设置任务执行者(流程变量) Map<String, Object> variables = new HashMap<String, Object>(); variables.put("inputUser", SessionContext.get().getName()); String key = leaveBill.getClass().getSimpleName(); /** * 方式一:使用字符串关联业务 * 格式:业务类的名称 + "." +业务ID * 例如:LeaveBill.1 */ String objId = key + "." + id; variables.put("objId", objId); /** * 方式二:使用act_ru_execution表的business_key字段来关联业务 * 格式:业务类的名称 + "." +业务ID * 例如:LeaveBill.1 */ //使得流程实例关联业务 id就是业务id String business_key = key + "." + id; //启动流程实例(流程定义key,关联业务字段 business_key,任务执行人) runtimeService.startProcessInstanceByKey(key, business_key, variables); } @Override public LeaveBill findLeaveBill1ByTaskId(String taskId) { Task task = this.taskService.createTaskQuery() .taskId(taskId) .singleResult(); ProcessInstance pi = this.runtimeService.createProcessInstanceQuery() .processInstanceId(task.getProcessInstanceId()) .singleResult(); String businessKey = pi.getBusinessKey(); if (StringUtils.isNotEmpty(businessKey)) { String formId = businessKey.split("\\.")[1]; LeaveBill leaveBill = this.leaveBillDao.findLeaveBillById(Long.parseLong(formId)); return leaveBill; } return null; } @Override public List<String> findOutComeList1ByTaskId(String taskId) { //存放连线名称 List<String> outcomeList = new ArrayList<String>(); /** * taskId->processDefinitionId->processDefinitionEntity * taskId->processInstanceId->activityId(当前活动节点Id) * 根据activityId在processDefinitionEntity中查找当前活动节点对象 */ Task task = taskService.createTaskQuery() .taskId(taskId) .singleResult(); String processDefinitionId = task.getProcessDefinitionId(); ProcessDefinitionEntity entity = (ProcessDefinitionEntity) repositoryService.getProcessDefinition(processDefinitionId); ProcessInstance pi = runtimeService.createProcessInstanceQuery() .processInstanceId(task.getProcessInstanceId()) .singleResult(); String activityId = pi.getActivityId(); //当前活动节点 ActivityImpl activityImpl = entity.findActivity(activityId); //获取当前活动节点下的连线名称 if (activityImpl != null) { List<PvmTransition> pvmList = activityImpl.getOutgoingTransitions(); if (pvmList != null && pvmList.size() > 0) { for (PvmTransition pvm : pvmList) { String name = (String) pvm.getProperty("name"); if (StringUtils.isNotEmpty(name)) { outcomeList.add(name); } else { outcomeList.add("默认提交"); } } } } return outcomeList; } @Override public void saveSubmitTask1(WorkflowBean workflowBean) { /** * 1、添加批注 * 2、判断连线名称是否为"默认提交" * 3、完成任务(绑定流程变量) * 4、指定下一个任务人 * 5、判断流程是否结束 */ String taskId = workflowBean.getTaskId(); Task task = taskService.createTaskQuery() .taskId(taskId) .singleResult(); String processInstanceId = task.getProcessInstanceId(); String comment = workflowBean.getComment(); /** 1、添加批注*/ /** * addComment(任务ID,流程实例ID,批注),需要手动设置UserId */ Authentication.setAuthenticatedUserId(SessionContext.get().getName()); taskService.addComment(taskId, processInstanceId, comment); /** 2、判断连线名称是否为默认提交,如果不是默认提交,需要通过流程变量设置要执行的连线名称 */ Map<String, Object> variables = new HashMap<String, Object>(); String outCome = workflowBean.getOutcome(); if(outCome != null && !"默认提交".equals(outCome)) { //设置要执行的连线 variables.put("outcome", outCome); } /** 3、完成当前个人任务*/ taskService.complete(taskId, variables); /**4、指定下一个任务人(使用类)*/ /** 5、判断流程是否结束,如果结束,则更新业务状态*/ ProcessInstance pi = runtimeService.createProcessInstanceQuery() .processInstanceId(processInstanceId) .singleResult(); if (pi == null) { //根据请假id查询leaveBill LeaveBill leaveBill = this.leaveBillDao.findLeaveBillById(workflowBean.getId()); leaveBill.setState(2); /** * 此处不用调用update或者merge方法了, * 对持久化对象的任何更改,会在session.flush或者提交事务的时候更新到数据库。 */ } } /** * taskId(当前任务id)->processInstanceId->历史任务(List):act_hi_taskinst表->历史task_id->comment:act_hi_comment表 */ @Override public List<Comment> findComment1ByTaskId(String taskId) { List<Comment> listComment = new ArrayList<Comment>(); Task task = taskService.createTaskQuery() .taskId(taskId) .singleResult(); String processInstanceId = task.getProcessInstanceId(); /** * 方式一:根据历史任务实例表 id --> 历史批注表 taskId */ // List<HistoricTaskInstance> list = historyService.createHistoricTaskInstanceQuery() // .processInstanceId(processInstanceId) // .list(); // if (list != null && list.size() > 0) { // for (HistoricTaskInstance hti : list) { // String hiTaskId = hti.getId(); // List<Comment> taskComments = taskService.getTaskComments(hiTaskId); // listComment.addAll(taskComments); // } // } /** * 方式二:根据流程实例ID直接在历史批注表中查询 */ listComment = taskService.getProcessInstanceComments(processInstanceId); return listComment; } @Override public List<Comment> findComment1ByLeaveBillId(Long formId) { /** * 业务数据与流程关联的表:使用历史流程实例表或历史流程变量表 */ LeaveBill leaveBill = this.leaveBillDao.findLeaveBillById(formId); String className = leaveBill.getClass().getSimpleName(); String businessKey = className + "." + formId; HistoricProcessInstance hpi = historyService.createHistoricProcessInstanceQuery() .processInstanceBusinessKey(businessKey) .singleResult(); String processInstanceId = hpi.getId(); //根据流程实例ID查询 审核记录(批注) List<Comment> commentsList = taskService.getProcessInstanceComments(processInstanceId); return commentsList; } }