Activiti工作流学习(三)Activiti工作流与spring集成
一.前言
前面Activiti工作流的学习,说明了Activiti的基本应用,在我们开发中可以根据实际的业务参考Activiti的API去更好的理解以及巩固。我们实际的开发中我们基本上都使用spring框架进行开发,现在来说明一下Activiti工作流与spring集成,Activiti工作流与spring集成还算比较简单,可以参考Activiti的API来进行整合。
二.Activiti常用的表
---------------------------------------------部署对象和流程定义相关的表--------------------------------------------- --部署对象信息表 SELECT T.*, T.ROWID FROM ACT_RE_DEPLOYMENT T; --流程定义表 --ID_ 由KEY_ + VERSION_ + 随机生成是数组成 SELECT T.*, T.ROWID FROM ACT_RE_PROCDEF T where t.category_='1' order by t.version_ asc; --资源文件表 SELECT T.*, T.ROWID FROM ACT_GE_BYTEARRAY T; --主键生成策略表 SELECT T.*, T.ROWID FROM ACT_GE_PROPERTY T; ------------------------------------------流程实例、执行对象、任务------------------------------------------------ --正在执行的执行对象表 -- 执行ID_ 56 流程实例ID_ 56 流程定义ID_ _3701622B-4133-7B3D-F50F-E14B4F21E847:1:55 正在运行的任务定义ID_ 【可变】 USERTASKE736BEF8-4133-7B3D-F510-7B2DE7BEA8C6 SELECT T.*, T.ROWID FROM ACT_RU_EXECUTION T; --流程实例历史表 开始信息 --历史流程定义ID_ 56 流程S实例ID_ 56 业务KEY_10000001 流程定义ID_ _3701622B-4133-7B3D-F50F-E14B4F21E847:1:55 开始任务节点ID_ STARTEVENT52B3145F-C133-7B3D-F50F-E6D48BA60EAE SELECT T.*, T.ROWID FROM ACT_HI_PROCINST T; --正在执行的任务对象表 --任务ID_ 68 执行ID_ 56 流程实例ID_ 56 流程定义ID_ _3701622B-4133-7B3D-F50F-E14B4F21E847:1:55 任务节点ID_ USERTASKE736BEF8-4133-7B3D-F510-7B2DE7BEA8C6 SELECT T.*, T.ROWID FROM ACT_RU_TASK T; --历史任务流程实例信息 --历史任务ID_ 68 流程实例ID_ 56 执行实例ID_ 56 流程定义ID_ _3701622B-4133-7B3D-F50F-E14B4F21E847:1:55 任务节点ID_ USERTASKE736BEF8-4133-7B3D-F510-7B2DE7BEA8C6 表单KEY_ /PAGES/HOLIDAY/HOLIDAYMANAGE/HOLIDAYFORMHANDLE.JSP --历史任务ID_ 74 流程实例ID_ 56 执行实例ID_ 56 流程定义ID_ _3701622B-4133-7B3D-F50F-E14B4F21E847:1:55 任务节点ID_ USERTASK04A84BE1-1133-7B3D-F511-1D0B7BB0A668 表单KEY_ /PAGES/HOLIDAY/HOLIDAYMANAGE/HOLIDAYFORMVIEW.JSP SELECT T.*, T.ROWID FROM ACT_HI_TASKINST T; --所有活动节点历史任务表 --历史任务ID_58 流程定义ID_ _3701622B-4133-7B3D-F50F-E14B4F21E847:1:55 流程实例ID_ 56 流程执行ID_ 56 任务节点ID_ STARTEVENT52B3145F-C133-7B3D-F50F-E6D48BA60EAE --历史任务ID_67 流程定义ID_ _3701622B-4133-7B3D-F50F-E14B4F21E847:1:55 流程实例ID_ 56 流程执行ID_ 56 任务节点ID_ USERTASKE736BEF8-4133-7B3D-F510-7B2DE7BEA8C6 任务ID_ 68 --历史任务ID_73 流程定义ID_ _3701622B-4133-7B3D-F50F-E14B4F21E847:1:55 流程实例ID_ 56 流程执行ID_ 56 任务节点ID_ USERTASK04A84BE1-1133-7B3D-F511-1D0B7BB0A668 任务ID_ 74 SELECT T.*, T.ROWID FROM ACT_HI_ACTINST T; ----------------------------------------流程变量信息-------------------------------------------------- --正在执行的流程变量信息 SELECT T.*, T.ROWID FROM ACT_RU_VARIABLE T; --历史流程变量信息 存放历史表单重要信息 --流程实例ID_ 56 执行实例ID_ 56 任务ID_ SELECT T.*, T.ROWID FROM ACT_HI_VARINST T; -------------------------------------------历史意见信息----------------------------------------------- --历史审批意见表 --任务ID_ 68 流程定义ID_ 56 SELECT T.*, T.ROWID FROM ACT_HI_COMMENT T; -----------------------------------------节点参与者信息------------------------------------------------- --任务办理人表(个人任务、组任务) SELECT T.*, T.ROWID FROM ACT_RU_IDENTITYLINK T; --历史任务办理人表(个人任务、组任务) SELECT T.*, T.ROWID FROM ACT_HI_IDENTITYLINK T; --临时对象 SELECT T.*, T.ROWID FROM EA_IST.IST_APPR_BUSI_DATA T
三.Activiti与spring整合xml配置文件
向spring配置文件中,添加一个spring-workflow2-activiti.xml配置文件,里面如下:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd"> <!--工作流引擎配置 --> <bean id="processEngineConfiguration" class="com.shine.workflow2.spring.ShineSpringProcessEngineConfiguration"> <property name="dataSource" ref="dataSource" /> <property name="transactionManager" ref="transactionManager" /> <property name="databaseSchemaUpdate" value="false" /> <property name="jobExecutorActivate" value="false" /> <!-- 组织机构适配 --> <property name="organizationConnector" ref="organizationAdapter" /> </bean> <!-- 组织机构适配实现 --> <bean id="organizationAdapter" class="com.shine.workflow2.organization.impl.OrganizationAdapter" /> <!--工作流引擎 --> <bean id="processEngine" class="com.shine.workflow2.spring.ShineProcessEngineFactoryBean"> <property name="processEngineConfiguration" ref="processEngineConfiguration" /> </bean> <!--扩展服务 --> <bean id="processDefinitionService" factory-bean="processEngine" factory-method="getProcessDefinitionService" /> <bean id="processLogService" factory-bean="processEngine" factory-method="getProcessLogService" /> <bean id="processManagementService" factory-bean="processEngine" factory-method="getProcessManagementService" /> <!--原生服务 --> <bean id="repositoryService" factory-bean="processEngine" factory-method="getRepositoryService" /> <bean id="runtimeService" factory-bean="processEngine" factory-method="getRuntimeService" /> <bean id="taskService" factory-bean="processEngine" factory-method="getTaskService" /> <bean id="historyService" factory-bean="processEngine" factory-method="getHistoryService" /> <bean id="managementService" factory-bean="processEngine" factory-method="getManagementService" /> <bean id="formService" factory-bean="processEngine" factory-method="getFormService" /> <bean id="identityService" factory-bean="processEngine" factory-method="getIdentityService" /> </beans>
四.Activiti工作流常用service
1.BaseProcessService
/** * */ package com.shine.eosp.workflow2.common.process; import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity; import org.activiti.engine.impl.pvm.PvmActivity; import org.activiti.engine.impl.pvm.process.ActivityImpl; import org.activiti.engine.impl.task.TaskDefinition; import org.activiti.engine.repository.ProcessDefinition; import org.activiti.engine.runtime.Execution; import org.activiti.engine.runtime.ProcessInstance; import org.activiti.engine.task.Task; import com.shine.workflow2.exception.WorkflowException; /** * * 类说明: 常用工作流核心操作封装 . * * <pre> * 修改日期 修改人 修改原因 * 2016-6-2 hongwz 新建 * </pre> */ public interface BaseProcessService { /** * 方法说明 : 根据流程定义Key查询最新流程定义. * * @param processDefinitionKey * @throws WorkflowException */ public ProcessDefinition findLatestProcessDefinitionByPrcDefKey(String processDefinitionKey) throws WorkflowException; /** * 方法说明 : 根据流程定义Id查询流程定义. * * @param processDefinitionId 流程定义Id * @throws WorkflowException */ public ProcessDefinitionEntity findProcessDefinitionEntityByProcDefId(String processDefinitionId) throws WorkflowException; /** * * 方法说明 : 根据流程实例Id查询流程实例. * * @param processInstanceId 流程实例Id * @return * @throws WorkflowException */ public ProcessInstance findProcessInstanceByProcInst(String processInstanceId) throws WorkflowException; /** * 根据流程实例Id查询流程实例. * * @param processInstanceId * @throws WorkflowException */ public Execution findExecutionByProcInst(String processInstanceId) throws WorkflowException; /** * 方法说明 : 根据流程实例Id查询任务. * * @param processInstanceId 流程实例Id * @throws WorkflowException */ public Task findTaskByProcInstId(String processInstanceId) throws WorkflowException; /** * 方法说明 : 根据实例Id查询任务. * * @param executionId 实例Id * @throws WorkflowException */ public Task findTaskByExecutionId(String executionId) throws WorkflowException; /** * 方法说明 : 根据活动节点查询任务定义. * * @param activityImpl 活动节点 * @throws WorkflowException */ public TaskDefinition findTaskDefinitionByActivityImpl(ActivityImpl activityImpl) throws WorkflowException; /** * 方法说明 : 查询上一个节点. * * @param activityImpl 活动节点 * @param activityId 当前活动节点ID * @param elString * @throws ShineException */ public TaskDefinition beforeTaskDefinition(ActivityImpl activityImpl,String activityId, String elString) throws WorkflowException; /** * 方法说明 : 查询下一个节点. * * @param activityImpl 活动节点 * @param activityId 当前活动节点ID * @param elString * @throws ShineException */ public TaskDefinition nextTaskDefinition(ActivityImpl activityImpl,String activityId, String elString) throws WorkflowException; /** * 方法说明: 根据活动节点、活动线路查询线路的连接线. * * @throws WorkflowException */ public PvmActivity findPvmActivity(ActivityImpl activityImpl, String transitions) throws WorkflowException; /** * 方法说明 :根据流程定义Id查询任务定义 * * @param processDefinitionId 流程定义Id * @return * @throws WorkflowException */ public TaskDefinition findTaskDefinition(String processDefinitionId) throws WorkflowException; /** * 方法说明 : 添加任务意见. * * @param taskId 任务Id * @param processInstanceId 流程实例Id * @param comment 意见 * @throws WorkflowException */ public void addTaskComment(String taskId, String processInstanceId, String comment) throws WorkflowException; /** * 方法说明 : 拾取任务. * * @param taskId 任务Id * @param operator 办理人 * @throws WorkflowException */ public void claimTask(String taskId, String operator) throws WorkflowException; /** * 方法说明 : 根据流程定义Id查询最新流程定义. * * @param processDefinitionId 流程定义Id * @return * @throws WorkflowException */ public ProcessDefinition findProcessDefinitionByPrcDefId(String processDefinitionId) throws WorkflowException; }
2.BaseProcessServiceImpl
/** * */ package com.shine.eosp.workflow2.common.process; import java.util.Iterator; import java.util.List; import org.activiti.engine.HistoryService; import org.activiti.engine.RepositoryService; import org.activiti.engine.RuntimeService; import org.activiti.engine.TaskService; import org.activiti.engine.impl.RepositoryServiceImpl; import org.activiti.engine.impl.bpmn.behavior.UserTaskActivityBehavior; import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity; import org.activiti.engine.impl.pvm.PvmActivity; import org.activiti.engine.impl.pvm.PvmTransition; import org.activiti.engine.impl.pvm.process.ActivityImpl; import org.activiti.engine.impl.task.TaskDefinition; import org.activiti.engine.repository.ProcessDefinition; import org.activiti.engine.runtime.Execution; import org.activiti.engine.runtime.ProcessInstance; import org.activiti.engine.task.Task; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import com.shine.util.CollectionUtil; import com.shine.workflow2.exception.WorkflowException; /** * * 类说明: 常用工作流核心操作封装 . * * <pre> * 修改日期 修改人 修改原因 * 2016-6-2 hongwz 新建 * </pre> */ public class BaseProcessServiceImpl implements BaseProcessService { /** * log. */ private static Logger logger = LoggerFactory.getLogger(BaseProcessServiceImpl.class); @Autowired private RepositoryService repositoryService; @Autowired private RuntimeService runtimeService; @Autowired private TaskService taskService; @Autowired private HistoryService historyService; /** * 方法说明 : 根据流程定义Key查询最新流程定义. * * @param processDefinitionKey 流程定义Key * @return * @throws WorkflowException */ @Override public ProcessDefinition findLatestProcessDefinitionByPrcDefKey(String processDefinitionKey) throws WorkflowException{ ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery() .processDefinitionKey(processDefinitionKey) .latestVersion() .singleResult(); return processDefinition; } /** * 方法说明 : 根据流程定义Id查询最新流程定义. * * @param processDefinitionId 流程定义Id * @return * @throws WorkflowException */ @Override public ProcessDefinition findProcessDefinitionByPrcDefId(String processDefinitionId) throws WorkflowException{ ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery() .processDefinitionId(processDefinitionId) .orderByProcessDefinitionVersion() .desc() .singleResult(); return processDefinition; } /** * 方法说明 : 根据流程定义Id查询流程定义. * * @param processDefinitionId 流程定义Id * @return * @throws WorkflowException */ @Override public ProcessDefinitionEntity findProcessDefinitionEntityByProcDefId(String processDefinitionId) throws WorkflowException{ ProcessDefinitionEntity processDefinitionEntity = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService) .getDeployedProcessDefinition(processDefinitionId); return processDefinitionEntity; } /** * * 方法说明 : 根据流程实例Id查询流程实例. * * @param processInstanceId 流程实例Id * @return * @throws WorkflowException */ @Override public ProcessInstance findProcessInstanceByProcInst(String processInstanceId) throws WorkflowException{ return runtimeService.createProcessInstanceQuery() .processInstanceId(processInstanceId) .singleResult(); } /** * 根据流程实例Id查询流程实例. * * @param processInstanceId * @return * @throws WorkflowException */ @Override public Execution findExecutionByProcInst(String processInstanceId) throws WorkflowException{ return runtimeService.createExecutionQuery().processInstanceId(processInstanceId).singleResult(); } /** * 方法说明 : 根据流程实例Id查询任务. * * @param processInstanceId 流程实例Id * @return * @throws WorkflowException */ @Override public Task findTaskByProcInstId(String processInstanceId) throws WorkflowException{ return taskService.createTaskQuery().processInstanceId(processInstanceId).singleResult(); } /** * 方法说明 : 根据实例Id查询任务. * * @param executionId 实例Id * @return * @throws WorkflowException */ @Override public Task findTaskByExecutionId(String executionId) throws WorkflowException{ return taskService.createTaskQuery().executionId(executionId).singleResult(); } /** * 方法说明 : 根据活动节点查询任务定义. * * @param activityImpl 活动节点 * @return * @throws WorkflowException */ @Override public TaskDefinition findTaskDefinitionByActivityImpl(ActivityImpl activityImpl) throws WorkflowException{ return ((UserTaskActivityBehavior)activityImpl.getActivityBehavior()).getTaskDefinition(); } /** * 方法说明 : 查询上一个节点. * * @param activityImpl 活动节点 * @param activityId 当前活动节点ID * @param elString * @return * @throws ShineException */ @Override public TaskDefinition beforeTaskDefinition(ActivityImpl activityImpl,String activityId, String elString) throws WorkflowException { if("userTask".equals(activityImpl.getProperty("type")) && !activityId.equals(activityImpl.getId())){ TaskDefinition taskDefinition = null; if(activityImpl != null){ taskDefinition = findTaskDefinitionByActivityImpl(activityImpl); } return taskDefinition; }else{ List<PvmTransition> inTransitions = activityImpl.getIncomingTransitions(); //通过活动节点查询所有线路 if(!CollectionUtil.isEmpty(inTransitions)){ List<PvmTransition> inTransitionsTemp = null; for(PvmTransition tr:inTransitions){ PvmActivity ac = tr.getSource(); //获取线路的前节点 if("exclusiveGateway".equals(ac.getProperty("type"))){ inTransitionsTemp = ac.getIncomingTransitions(); if(inTransitionsTemp.size() == 1){ return beforeTaskDefinition((ActivityImpl)inTransitionsTemp.get(0).getSource(), activityId, elString); }else if(inTransitionsTemp.size() > 1){ for(PvmTransition tr1 : inTransitionsTemp){ Object s = tr1.getProperty("conditionText"); if(elString.equals(StringUtils.replacePattern(StringUtils.trim(s.toString()), " ", ""))){ return beforeTaskDefinition((ActivityImpl)tr1.getSource(), activityId, elString); } } } } } } return null; } } /** * 方法说明 : 查询下一个节点. * * @param activityImpl 活动节点 * @param activityId 当前活动节点ID * @param elString * @return * @throws ShineException */ @Override public TaskDefinition nextTaskDefinition(ActivityImpl activityImpl,String activityId, String elString) throws WorkflowException { if("userTask".equals(activityImpl.getProperty("type")) && !activityId.equals(activityImpl.getId())){ TaskDefinition taskDefinition = null; if(activityImpl != null){ taskDefinition = findTaskDefinitionByActivityImpl(activityImpl); } return taskDefinition; }else{ List<PvmTransition> outTransitions = activityImpl.getOutgoingTransitions(); //通过活动节点查询所有线路 if(!CollectionUtil.isEmpty(outTransitions)){ List<PvmTransition> outTransitionsTemp = null; for(PvmTransition tr:outTransitions){ PvmActivity ac = tr.getDestination(); //获取线路的终点节点 if("exclusiveGateway".equals(ac.getProperty("type"))){ outTransitionsTemp = ac.getOutgoingTransitions(); if(outTransitionsTemp.size() == 1){ return nextTaskDefinition((ActivityImpl)outTransitionsTemp.get(0).getDestination(), activityId, elString); }else if(outTransitionsTemp.size() > 1){ for(PvmTransition tr1 : outTransitionsTemp){ Object s = tr1.getProperty("conditionText"); if(s != null && elString.equals(StringUtils.replacePattern(StringUtils.trim(s.toString()), " ", ""))){ return nextTaskDefinition((ActivityImpl)tr1.getDestination(), activityId, elString); } } } }else if("userTask".equals(ac.getProperty("type"))){ return findTaskDefinitionByActivityImpl((ActivityImpl)ac); } else if("startEvent".equals(ac.getProperty("type"))){ return findTaskDefinitionByActivityImpl((ActivityImpl)ac); } else{ logger.info(ac.getProperty("type").toString()); } } } return null; } } /** * 方法说明: 根据活动节点、活动线路查询线路的连接线. * * @return * @throws WorkflowException */ @SuppressWarnings("rawtypes") @Override public PvmActivity findPvmActivity(ActivityImpl activityImpl, String transitions) throws WorkflowException{ PvmActivity activity = null; List<PvmTransition> pvmTransitions = activityImpl.getOutgoingTransitions(); //获取所有线路 for (Iterator iterator = pvmTransitions.iterator(); iterator.hasNext();) { PvmTransition pvmTransition = (PvmTransition) iterator.next(); PvmActivity pvmActivity = pvmTransition.getDestination(); //获取下一个任务节点 String transitionsVal = (String) pvmActivity.getProperty("name"); if(transitions.equals(transitionsVal)){ activity = pvmActivity; break; } } return activity; } /** * 方法说明 :根据流程定义Id查询任务定义 * * @param processDefinitionId 流程定义Id * @return * @throws WorkflowException */ @Override public TaskDefinition findTaskDefinition(String processDefinitionId) throws WorkflowException{ //获取流程定义 ProcessDefinitionEntity processDefinitionEntity = findProcessDefinitionEntityByProcDefId(processDefinitionId); TaskDefinition tdf = null; if(processDefinitionEntity != null){ List<ActivityImpl> activityImpls = processDefinitionEntity.getActivities(); //获取所有活动的节点 for(int i = activityImpls.size() - 1; i > 0; i-- ){ ActivityImpl activityImpl = activityImpls.get(i); String startEventType = (String) activityImpl.getProperty("type"); if("startEvent".equals(startEventType)){ tdf = nextTaskDefinition(activityImpl, activityImpl.getId(), null); } } } return tdf; } /** * 方法说明 : 添加任务意见. * * @param taskId 任务Id * @param processInstanceId 流程实例Id * @param comment 意见 * @throws WorkflowException */ @Override public void addTaskComment(String taskId,String processInstanceId,String comment) throws WorkflowException{ taskService.addComment(taskId, processInstanceId, comment); } /** * 方法说明 : 拾取任务. * * @param taskId 任务Id * @param operator 办理人 * @throws WorkflowException */ @Override public void claimTask(String taskId,String operator) throws WorkflowException{ taskService.claim(taskId, operator); } }