activiti工作流引擎流程走啦一半被删除怎么半

Activiti工作流(一)之基本操作介绍 - Asen丶的博客 - ITeye博客
博客分类:
工作流的概念:
工作流(Workflow),就是“业务过程的部分或整体在计算机应用环境下的自动化”,它主要解决的是“使在多个参与者之间按照某种预定义的规则传递文档、信息或任务的过程自动进行,从而实现某个预期的业务目标,或者促使此目标的实现”。通俗的说,流程就是多个人在一起合作完成某件事情的步骤,把步骤变成计算机能理解的形式就是工作流。
常见的工作流引擎有:OSWorkFlow、jbpm、activiti(对jbpm的升级)
如果在一个项目中我们需要引入工作流的话,首先需要引入相关jar包,然后获得一个工作流引擎,而获得这个工作流引擎的方式有三种:
1、通过代码方式获得:
public void getProcessEngine1(){
ProcessEngineConfiguration engineConfiguratoin = ProcessEngineConfiguration
.createStandaloneProcessEngineConfiguration();
engineConfiguration.setJdbcDriver("com.mysql.jdbc.Driver");
engineConfiguration
.setJdbcUrl("jdbc:mysql://10.10.10.30:3306/activitiDB?createDatabaseIfNotExist=true"
+ "&useUnicode=true&characterEncoding=utf8");
engineConfiguration.setJdbcUsername("root");
engineConfiguration.setJdbcPassword("aaaaaaaaa");
engineConfiguration.setDatabaseSchemaUpdate("true");
ProcessEngine buildProcessEngine = engineConfiguration.buildProcessEngine();
2、通过加载指定的xml文件获取:
&beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"&
&bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration"&
&property name="jdbcDriver" value="com.mysql.jdbc.Driver"&&/property&
&property name="jdbcUrl" value="jdbc:mysql://10.10.10.30:3306/activitiDB?createDatabaseIfNotExist=true&useUnicode=true&characterEncoding=utf8"&&/property&
&property name="jdbcUsername" value="root"&&/property&
&property name="jdbcPassword" value="aaaaaaaa"&&/property&
&property name="databaseSchemaUpdate" value="true"&&/property&
public void getProcessEngine2(){
ProcessEngineConfiguration engineConfiguration =
ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti.cfg.xml");
ProcessEngine processEngine = engineConfiguration.buildProcessEngine();
3、通过加载默认的xml文件获取,默认xml文件名称为activiti.cfg.xml
public void getProcessengine3(){
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
当获得了工作流引擎之后,会创建一个数据库,数据库中有默认的23张表
资源库流程规则表
1) act_re_deployment
部署信息表
2) act_re_model
流程设计模型部署表
3) act_re_procdef
流程定义数据表
运行时数据库表
1) act_ru_execution 运行时流程执行实例表
2) act_ru_identitylink 运行时流程人员表,主要存储任务节点与参与者的相关信息
3) act_ru_task
运行时任务节点表
4) act_ru_variable
运行时流程变量数据表
历史数据库表
1) act_hi_actinst
历史节点表
2) act_hi_attachment 历史附件表
3) act_hi_comment
历史意见表
4) act_hi_identitylink 历史流程人员表
5) act_hi_detail
历史详情表,提供历史变量的查询
6) act_hi_procinst
历史流程实例表
7) act_hi_taskinst
历史任务实例表
8) act_hi_varinst
历史变量表
组织机构表
1) act_id_group
用户组信息表
2) act_id_info
用户扩展信息表
3) act_id_membership 用户与用户组对应信息表
4) act_id_user
用户信息表
这四张表很常见,基本的组织机构管理,关于用户认证方面建议还是自己开发一套,组件自带的功能太简单,使用中有很多需求难以满足
通用数据表
1) act_ge_bytearray 二进制数据表
2) act_ge_property
属性数据表存储整个流程引擎级别的数据,初始化表结构时,会默认插入三条记录
还有两张表不怎么常用
act_ru_event_subscr
act_ru_job
接下来就是activiti的核心API部分
这些service可以由ProcessEngine获得,且这些service都有着各自的任务
RepositoryService
管理流程定义
RuntimeService
执行管理,包括启动、推进、删除流程实例等操作
TaskService
HistoryService
历史管理(执行完的数据的管理)
IdentityService
组织机构管理
FormService
一个可选服务,任务表单管理
ManagerService
接下来是完成一个工作流程的基本操作步骤,首先我们需要安装Activiti插件,然后我们构建一个流程实例并部署上去
public void deploy(){
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
RepositoryService service = processEngine.getRepositoryService();
Deployment deploy = service.createDeployment()
.addClasspathResource("diagrams/LeaveProcess.bpmn")
.addClasspathResource("diagrams/LeaveProcess.png")
.name("请假流程")
.deploy();
部署流程还有一种方法也可以:加载压缩文件(zip格式)
public void deployProcess2(){
InputStream in = getClass().getClassLoader().getResourceAsStream("Leave.zip");
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
Deployment deploy = processEngine.getRepositoryService()
.createDeployment()
.name("请假流程")
.addZipInputStream(new ZipInputStream(in))
.deploy();
接下来就是启动流程
public void test(){
String instanceKey = "myProcess";
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
RuntimeService service = processEngine.getRuntimeService();
ProcessInstance instance = service.startProcessInstanceByKey(instanceKey);
在流程启动的过程中,我们可以查询流程的进度
public void query(){
String assignee = "Meixi";
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
TaskService service = processEngine.getTaskService();
TaskQuery taskQuery = service.createTaskQuery();
List&Task& list = taskQuery.taskAssignee(assignee).list();
for (Task task : list){
System.out.println(task);
接下来就是完成每一个流程
public void complete(){
String taskID = "104";
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
TaskService service = processEngine.getTaskService();
plete(taskID);
浏览: 7522 次
来自: 深圳扩展Activiti 5.12轻松搞定流程实例跟随流程版本一起升级 - bboss,activiti,BPMN,流程部署,流程任务升级 - Java - ITeye论坛
扩展Activiti 5.12轻松搞定流程实例跟随流程版本一起升级
& 上一页 1
锁定老帖子
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
积分: 1950
来自: 长沙
发表时间:&&
最后修改:
相关知识库:
扩展Activiti 5.12轻松搞定流程实例跟随流程版本一起升级,本文详细介绍之
本功能依托于分支和版本。
为activiti组件org.activiti.engine.repository.DeploymentBuilder增加以下接口方法:
Deployment deploy(int deploypolicy);
参数deploypolicy为int类型,用来指定流程部署策略,有三个值:
DeploymentBuilder.Deploy_policy_default
DeploymentBuilder.Deploy_policy_upgrade
DeploymentBuilder.Deploy_policy_delete
这三个值作为常量定义在部署接口org.activiti.engine.repository.DeploymentBuilder中。他们的含义分别为:
DeploymentBuilder.Deploy_policy_default 没有执行完毕的旧版本实例任务仍然根据旧版本流程定义运行
DeploymentBuilder.Deploy_policy_upgrade 没有执行完毕的旧版本实例任务迁移到新版本流程定义运行
DeploymentBuilder.Deploy_policy_delete 直接取消没有执行完毕的旧版本实例任务
原来的部署接口方法任然保留:
Deployment deploy();
以下是两个简单的使用扩展接口部署流程示例:
public Deployment deployProcDefByZip(String deploymentName,
ZipInputStream processDef,int upgradepolicy) {
DeploymentBuilder deploymentBuilder = processEngine
.getRepositoryService().createDeployment().name(deploymentName);
deploymentBuilder.addZipInputStream(processDef);
* 参数upgradepolicy可以为以下常量值:
DeploymentBuilder.Deploy_policy_default
* DeploymentBuilder.Deploy_policy_upgrade
DeploymentBuilder.Deploy_policy_delete
return deploymentBuilder.deploy(upgradepolicy);
public Deployment deployProcDefByPath(String deploymentName,
String xmlPath, String jpgPath,int deploypolicy) {
Deployment deploy =
* 参数deploypolicy可以为以下常量值:
DeploymentBuilder.Deploy_policy_default
* DeploymentBuilder.Deploy_policy_upgrade
DeploymentBuilder.Deploy_policy_delete
if(jpgPath != null && !jpgPath.equals(""))
deploy = repositoryService.createDeployment()
.name(deploymentName).addClasspathResource(xmlPath)
.addClasspathResource(jpgPath).deploy(deploypolicy);
deploy = repositoryService.createDeployment()
.name(deploymentName).addClasspathResource(xmlPath).deploy(deploypolicy);
积分: 2110
来自: 成都
发表时间:&&
解决了这个问题,非常好啊。。。
请登录后投票
等级: 初级会员
发表时间:&&
这样容易出问题,你修改流程的时候还要去考虑会不会出问题。。。我想activiti不做这种功能就是因为不同版本升级要考虑的事情太多
请登录后投票
积分: 1950
来自: 长沙
发表时间:&&
cjwkof 写道这样容易出问题,你修改流程的时候还要去考虑会不会出问题。。。
我想activiti不做这种功能就是因为不同版本升级要考虑的事情太多
呵呵,什么情况下都可能出现问题,注意我们在文中提到了三种策略,一种是最常用的默认策略,一种是升级实例策略,一种是取消实例策略,每种策略都有他适用的场景。更新策略举个最简单的例子,当流程跑到中间某个环节时,跑不下去了,结果发现是流程定义有问题,这时候就会修改一流程定义,业务和前端程序都没修改,这样就可以在部署新流程时选择升级实例策略,将旧版实例全部升级到新版上来了。当然根据实际需要,也可以选择取消实例策略。
请登录后投票
等级: 初级会员
来自: 北京
发表时间:&&
楼主考虑的很全面,新扩展的功能也是很多场景用到的,支持!
请登录后投票
Jacarri_Chan
等级: 初级会员
发表时间:&&
请问有在线的流程设计器么?
请登录后投票
zuiyanwangyue
来自: 河北
发表时间:&&
最后修改:
个人觉得楼主这样做意义不大,拿更新策略来说,难道你的应用上线时不做测试?还会出现旧流程跑到某个节点走不下去的情况?
请登录后投票
积分: 2110
来自: 成都
发表时间:&&
运行时更改流程的情况还是比较多的,这个设计的意义很重大。。。。
请登录后投票
积分: 1950
来自: 长沙
发表时间:&&
最后修改:
Jacarri_Chan 写道
请问有在线的流程设计器么?
暂时没有做activiti的在线web流程设计器,不过activiti官方提供了一个activiti modler的web在线流程设计器,感兴趣可以去试用一下。
请登录后投票
积分: 1950
来自: 长沙
发表时间:&&
最后修改:
zuiyanwangyue 写道个人觉得楼主这样做意义不大,拿更新策略来说,难道你的应用上线时不做测试?还会出现旧流程跑到某个节点走不下去的情况?
我只是举了个简单的例子而已,例子中的场景更适应于开发环境流程的调试场景,但是也不排除在实际生产环境下使用。
总之,流程实例升级特性一般更多地出现在很多商业bpm产品中,比如ibm bpm,oracle bpm,SoftAG bpm等,开源BPM中很少有提供这种便利功能的,这些商业产品动辄上百万的投资,非常昂贵,我只是希望在开源的产品中也能够具备这些便利的功能,从而为自己的项目提供更多的便利。
请登录后投票
& 上一页 1
跳转论坛:移动开发技术
Web前端技术
Java企业应用
编程语言技术Activiti工作流引擎使用--初学心得
&目前所在的公司是从事互联网金融的,线上的借款申请时要通过风控人员按流程一步步审批下来才可,所以系统需要使用工作流。
官网:http://www.activiti.org/
API:http://www.activiti.org/userguide/
下载:http://www.activiti.org/download.html
国内最权威(中国Activiti领域第一人和布道师)的Activiti专家咖啡兔深度讲解Activiti的实现原理和核心技术:http://www.kafeitu.me/activiti.html
流程图设计工具用什么
Activiti提供了两个流程设计工具,但是面向对象不同。
Modeler,面向业务人员,使用开源的BPMN设计工具Signavio,使用BPMN描述业务流程图
Designer,面向开发人员,Eclipse的插件,可以让开发人员定制每个节点的属性(ID、Name、Listener、Attr等)
Activiti支持部署*.bpmn20.xml、bar、zip格式的流程定义。
使用Activit Deisigner工具设计流程图的时候会有三个类型的文件:
.activiti设计工具使用的文件
.bpmn20.xml设计工具自动根据.activiti文件生成的xml文件
.png流程图图片
解决办法就是把xml文件和图片文件同时部署,因为在单独部署xml文件的时候Activiti会自动生成一张流程图的图片文件,但是这样在使用的时候坐标和图片对应不起来……
所以把xml和图片同时部署的时候Activiti自动关联xml和图片,当需要获取图片的时候直接返回部署时压缩包里面的图片文件,而不是Activiti自动生成的图片文件.
//起动流程
startProcessInstanceByKey(String processDefinitionKey, Map
variabes)&
& & Starts a new process instance
in the latest version of the process definition with the given
其中businessKey就是业务ID,例如要申请请假,那么先填写登记信息,然后(保存+启动流程),因为请假是单独设计的数据表,所以保存后得到实体ID就可以把它传给processInstanceBusinessKey方法启动流程。当需要根据businessKey查询流程的时候就可以通过API查询:
runtimeService.createProcessInstanceQuery().processInstanceBusinessKey(processInstanceBusinessKey,
processDefinitionKey);
建议数据库冗余设计:在业务表设计的时候添加一列:PROCESS_INSTANCE_ID
varchar2(64),在流程启动之后把流程ID更新到业务表中,这样不管从业务还是流程都可以查询到对方!
特别说明: 此方法启动时自动选择最新版本的流程定义。
javadoc对其说明:
startProcessInstanceById(String processDefinitionId, String
businessKey, Map variables)&
& & Starts a new process instance
in the exactly specified version of the process definition with the
processDefinitionId:这个参数的值可以通过repositoryService.createProcessDefinitionQuery()方法查询,对应数据库:ACT_RE_PROCDEF;每次部署一次流程定义就会添加一条数据,同名的版本号累加。
特别说明: 此可以指定不同版本的流程定义,让用户多一层选择。
建议使用startProcessInstanceByKey,特殊情况需要使用以往的版本选择使用startProcessInstanceById。
各种状态的任务查询以及和业务对象关联
我们目前分为4中状态:未签收、办理中、运行中、已完成
&1、未签收(Task)
此类任务针对于把Task分配给一个角色时,例如部门领导,因为部门领导角色可以指定多个人所以需要先签收再办理,术语:抢占式
对应的API查询:
@Transactional(readOnly = true)
publicTaskQuery createUnsignedTaskQuery(String userId) {
& & TaskQuery
taskCandidateUserQuery =
taskService.createTaskQuery().processDefinitionKey(getProcessDefKey())
.taskCandidateUser(userId);
returntaskCandidateUserQ
2、办理中(Task)
此类任务数据类源有两种:
签收后的,签收后就应该为办理中状态
节点指定的是具体到一个人,而不是角色
对应的API查询:
@Transactional(readOnly = true)
publicTaskQuery createTodoTaskQuery(String userId) {
& & TaskQuery
taskAssigneeQuery =
taskService.createTaskQuery().processDefinitionKey(getProcessDefKey()).taskAssignee(userId);
returntaskAssigneeQ
3、运行中(ProcessInstance)
没有结束的流程,所有参与过的人都应该可以看到这个实例,
从表ACT_RU_EXECUTION中查询数据。
对应的API查询:
@Transactional(readOnly = true)
publicProcessInstanceQuery
createUnFinishedProcessInstanceQuery(String userId) {
& & ProcessInstanceQuery
unfinishedQuery =
runtimeService.createProcessInstanceQuery().processDefinitionKey(getProcessDefKey())
.active();
returnunfinishedQ
4、已完成(HistoricProcessInstance)
已经结束的流程实例。
从表ACT_HI_PROCINST中查询数据。
@Transactional(readOnly = true)
publicHistoricProcessInstanceQuery
createFinishedProcessInstanceQuery(String userId) {
HistoricProcessInstanceQuery finishedQuery =
historyService.createHistoricProcessInstanceQuery()
.processDefinitionKey(getProcessDefKey()).finished();
returnfinishedQ
详细的例子在国内Activiti领域第一人咖啡兔的博客中有讲解
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。activiti 工作流(7)
package com.famousPro.process.service.
import java.util.ArrayL
import java.util.HashM
import java.util.L
import java.util.M
import org.activiti.engine.FormS
import org.activiti.engine.HistoryS
import org.activiti.engine.RepositoryS
import org.activiti.engine.RuntimeS
import org.activiti.engine.TaskS
import org.activiti.engine.history.HistoricActivityI
import org.activiti.engine.impl.RepositoryServiceI
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionE
import org.activiti.engine.impl.persistence.entity.TaskE
import org.activiti.engine.impl.pvm.PvmT
import org.activiti.engine.impl.pvm.process.ActivityI
import org.activiti.engine.impl.pvm.process.ProcessDefinitionI
import org.activiti.engine.impl.pvm.process.TransitionI
import org.activiti.engine.runtime.ProcessI
import org.activiti.engine.task.T
import mon.service.impl.BaseServiceI
import mon.util.IDG
import mon.util.StringU
import com.famousPro.process.service.ProcessCoreS
import com.famousPro.process.service.ProcessOtherS
* 流程操作核心类&br&
* 此核心类主要处理:流程通过、驳回、会签、转办、中止、挂起等核心操作&br&
* @author wangfuwei
public class ProcessCoreServiceImpl extends BaseServiceImp implements
ProcessCoreService {
protected RepositoryService repositoryS
protected RuntimeService runtimeS
protected TaskService taskS
protected FormService formS
protected HistoryService historyS
protected ProcessOtherService processOtherS
* 根据当前任务ID,查询可以驳回的任务节点
* @param taskId
当前任务ID
public List&ActivityImpl& findBackAvtivity(String taskId) throws Exception {
List&ActivityImpl& rtnList =
if (processOtherService.isJointTask(taskId)) {// 会签任务节点,不允许驳回
rtnList = new ArrayList&ActivityImpl&();
rtnList = iteratorBackActivity(taskId, findActivitiImpl(taskId,
null), new ArrayList&ActivityImpl&(),
new ArrayList&ActivityImpl&());
return reverList(rtnList);
* 审批通过(驳回直接跳回功能需后续扩展)
* @param taskId
当前任务ID
* @param variables
流程存储参数
* @throws Exception
public void passProcess(String taskId, Map&String, Object& variables)
throws Exception {
List&Task& tasks = taskService.createTaskQuery().parentTaskId(taskId)
.taskDescription(&jointProcess&).list();
for (Task task : tasks) {// 级联结束本节点发起的会签任务
commitProcess(task.getId(), null, null);
commitProcess(taskId, variables, null);
* 驳回流程
* @param taskId
当前任务ID
* @param activityId
驳回节点ID
* @param variables
流程存储参数
* @throws Exception
public void backProcess(String taskId, String activityId,
Map&String, Object& variables) throws Exception {
if (StringUtil.isNull(activityId)) {
throw new Exception(&驳回目标节点ID为空!&);
// 查询本节点发起的会签任务,并结束
List&Task& tasks = taskService.createTaskQuery().parentTaskId(taskId)
.taskDescription(&jointProcess&).list();
for (Task task : tasks) {
commitProcess(task.getId(), null, null);
// 查找所有并行任务节点,同时驳回
List&Task& taskList = findTaskListByKey(findProcessInstanceByTaskId(
taskId).getId(), findTaskById(taskId).getTaskDefinitionKey());
for (Task task : taskList) {
commitProcess(task.getId(), variables, activityId);
* 取回流程
* @param taskId
当前任务ID
* @param activityId
取回节点ID
* @throws Exception
public void callBackProcess(String taskId, String activityId)
throws Exception {
if (StringUtil.isNull(activityId)) {
throw new Exception(&目标节点ID为空!&);
// 查找所有并行任务节点,同时取回
List&Task& taskList = findTaskListByKey(findProcessInstanceByTaskId(
taskId).getId(), findTaskById(taskId).getTaskDefinitionKey());
for (Task task : taskList) {
commitProcess(task.getId(), null, activityId);
* 中止流程(特权人直接审批通过等)
* @param taskId
public void endProcess(String taskId) throws Exception {
ActivityImpl endActivity = findActivitiImpl(taskId, &end&);
commitProcess(taskId, null, endActivity.getId());
* 会签操作
* @param taskId
当前任务ID
* @param userCodes
会签人账号集合
* @throws Exception
public void jointProcess(String taskId, List&String& userCodes)
throws Exception {
for (String userCode : userCodes) {
TaskEntity task = (TaskEntity) taskService.newTask(IDGenerator
.generateID());
task.setAssignee(userCode);
task.setName(findTaskById(taskId).getName() + &-会签&);
task.setProcessDefinitionId(findProcessDefinitionEntityByTaskId(
taskId).getId());
task.setProcessInstanceId(findProcessInstanceByTaskId(taskId)
.getId());
task.setParentTaskId(taskId);
task.setDescription(&jointProcess&);
taskService.saveTask(task);
* 转办流程
* @param taskId
当前任务节点ID
* @param userCode
被转办人Code
public void transferAssignee(String taskId, String userCode) {
taskService.setAssignee(taskId, userCode);
* ***************************************************************************************************************************************************&br&
* ************************************************以下为流程会签操作核心逻辑******************************************************************************&br&
* ***************************************************************************************************************************************************&br&
* ***************************************************************************************************************************************************&br&
* ************************************************以上为流程会签操作核心逻辑******************************************************************************&br&
* ***************************************************************************************************************************************************&br&
* ***************************************************************************************************************************************************&br&
* ************************************************以下为流程转向操作核心逻辑******************************************************************************&br&
* ***************************************************************************************************************************************************&br&
* @param taskId
当前任务ID
* @param variables
* @param activityId
流程转向执行任务节点ID&br&
此参数为空,默认为提交操作
* @throws Exception
private void commitProcess(String taskId, Map&String, Object& variables,
String activityId) throws Exception {
if (variables == null) {
variables = new HashMap&String, Object&();
// 跳转节点为空,默认提交操作
if (StringUtil.isNull(activityId)) {
plete(taskId, variables);
} else {// 流程转向操作
turnTransition(taskId, activityId, variables);
* 清空指定活动节点流向
* @param activityImpl
* @return 节点流向集合
private List&PvmTransition& clearTransition(ActivityImpl activityImpl) {
// 存储当前节点所有流向临时变量
List&PvmTransition& oriPvmTransitionList = new ArrayList&PvmTransition&();
// 获取当前节点所有流向,存储到临时变量,然后清空
List&PvmTransition& pvmTransitionList = activityImpl
.getOutgoingTransitions();
for (PvmTransition pvmTransition : pvmTransitionList) {
oriPvmTransitionList.add(pvmTransition);
pvmTransitionList.clear();
return oriPvmTransitionL
* 还原指定活动节点流向
* @param activityImpl
* @param oriPvmTransitionList
原有节点流向集合
private void restoreTransition(ActivityImpl activityImpl,
List&PvmTransition& oriPvmTransitionList) {
// 清空现有流向
List&PvmTransition& pvmTransitionList = activityImpl
.getOutgoingTransitions();
pvmTransitionList.clear();
// 还原以前流向
for (PvmTransition pvmTransition : oriPvmTransitionList) {
pvmTransitionList.add(pvmTransition);
* 流程转向操作
* @param taskId
当前任务ID
* @param activityId
目标节点任务ID
* @param variables
* @throws Exception
private void turnTransition(String taskId, String activityId,
Map&String, Object& variables) throws Exception {
// 当前节点
ActivityImpl currActivity = findActivitiImpl(taskId, null);
// 清空当前流向
List&PvmTransition& oriPvmTransitionList = clearTransition(currActivity);
// 创建新流向
TransitionImpl newTransition = currActivity.createOutgoingTransition();
// 目标节点
ActivityImpl pointActivity = findActivitiImpl(taskId, activityId);
// 设置新流向的目标节点
newTransition.setDestination(pointActivity);
// 执行转向任务
plete(taskId, variables);
// 删除目标节点新流入
pointActivity.getIncomingTransitions().remove(newTransition);
// 还原以前流向
restoreTransition(currActivity, oriPvmTransitionList);
* ***************************************************************************************************************************************************&br&
* ************************************************以上为流程转向操作核心逻辑******************************************************************************&br&
* ***************************************************************************************************************************************************&br&
* ***************************************************************************************************************************************************&br&
* ************************************************以下为查询流程驳回节点核心逻辑***************************************************************************&br&
* ***************************************************************************************************************************************************&br&
* 迭代循环流程树结构,查询当前节点可驳回的任务节点
* @param taskId
当前任务ID
* @param currActivity
当前活动节点
* @param rtnList
存储回退节点集合
* @param tempList
临时存储节点集合(存储一次迭代过程中的同级userTask节点)
* @return 回退节点集合
private List&ActivityImpl& iteratorBackActivity(String taskId,
ActivityImpl currActivity, List&ActivityImpl& rtnList,
List&ActivityImpl& tempList) throws Exception {
// 查询流程定义,生成流程树结构
ProcessInstance processInstance = findProcessInstanceByTaskId(taskId);
// 当前节点的流入来源
List&PvmTransition& incomingTransitions = currActivity
.getIncomingTransitions();
// 条件分支节点集合,userTask节点遍历完毕,迭代遍历此集合,查询条件分支对应的userTask节点
List&ActivityImpl& exclusiveGateways = new ArrayList&ActivityImpl&();
// 并行节点集合,userTask节点遍历完毕,迭代遍历此集合,查询并行节点对应的userTask节点
List&ActivityImpl& parallelGateways = new ArrayList&ActivityImpl&();
// 遍历当前节点所有流入路径
for (PvmTransition pvmTransition : incomingTransitions) {
TransitionImpl transitionImpl = (TransitionImpl) pvmT
ActivityImpl activityImpl = transitionImpl.getSource();
String type = (String) activityImpl.getProperty(&type&);
* 并行节点配置要求:&br&
* 必须成对出现,且要求分别配置节点ID为:XXX_start(开始),XXX_end(结束)
if (&parallelGateway&.equals(type)) {// 并行路线
String gatewayId = activityImpl.getId();
String gatewayType = gatewayId.substring(gatewayId
.lastIndexOf(&_&) + 1);
if (&START&.equals(gatewayType.toUpperCase())) {// 并行起点,停止递归
return rtnL
} else {// 并行终点,临时存储此节点,本次循环结束,迭代集合,查询对应的userTask节点
parallelGateways.add(activityImpl);
} else if (&startEvent&.equals(type)) {// 开始节点,停止递归
return rtnL
} else if (&userTask&.equals(type)) {// 用户任务
tempList.add(activityImpl);
} else if (&exclusiveGateway&.equals(type)) {// 分支路线,临时存储此节点,本次循环结束,迭代集合,查询对应的userTask节点
currActivity = transitionImpl.getSource();
exclusiveGateways.add(currActivity);
* 迭代条件分支集合,查询对应的userTask节点
for (ActivityImpl activityImpl : exclusiveGateways) {
iteratorBackActivity(taskId, activityImpl, rtnList, tempList);
* 迭代并行集合,查询对应的userTask节点
for (ActivityImpl activityImpl : parallelGateways) {
iteratorBackActivity(taskId, activityImpl, rtnList, tempList);
* 根据同级userTask集合,过滤最近发生的节点
currActivity = filterNewestActivity(processInstance, tempList);
if (currActivity != null) {
// 查询当前节点的流向是否为并行终点,并获取并行起点ID
String id = findParallelGatewayId(currActivity);
if (StringUtil.isNull(id)) {// 并行起点ID为空,此节点流向不是并行终点,符合驳回条件,存储此节点
rtnList.add(currActivity);
} else {// 根据并行起点ID查询当前节点,然后迭代查询其对应的userTask任务节点
currActivity = findActivitiImpl(taskId, id);
// 清空本次迭代临时集合
tempList.clear();
// 执行下次迭代
iteratorBackActivity(taskId, currActivity, rtnList, tempList);
return rtnL
* 反向排序list集合,便于驳回节点按顺序显示
* @param list
private List&ActivityImpl& reverList(List&ActivityImpl& list) {
List&ActivityImpl& rtnList = new ArrayList&ActivityImpl&();
// 由于迭代出现重复数据,排除重复
for (int i = list.size(); i & 0; i--) {
if (!rtnList.contains(list.get(i - 1)))
rtnList.add(list.get(i - 1));
return rtnL
* 根据当前节点,查询输出流向是否为并行终点,如果为并行终点,则拼装对应的并行起点ID
* @param activityImpl
private String findParallelGatewayId(ActivityImpl activityImpl) {
List&PvmTransition& incomingTransitions = activityImpl
.getOutgoingTransitions();
for (PvmTransition pvmTransition : incomingTransitions) {
TransitionImpl transitionImpl = (TransitionImpl) pvmT
activityImpl = transitionImpl.getDestination();
String type = (String) activityImpl.getProperty(&type&);
if (&parallelGateway&.equals(type)) {// 并行路线
String gatewayId = activityImpl.getId();
String gatewayType = gatewayId.substring(gatewayId
.lastIndexOf(&_&) + 1);
if (&END&.equals(gatewayType.toUpperCase())) {
return gatewayId.substring(0, gatewayId.lastIndexOf(&_&))
+ &_start&;
* 根据流入任务集合,查询最近一次的流入任务节点
* @param processInstance
* @param tempList
流入任务集合
private ActivityImpl filterNewestActivity(ProcessInstance processInstance,
List&ActivityImpl& tempList) {
while (tempList.size() & 0) {
ActivityImpl activity_1 = tempList.get(0);
HistoricActivityInstance activityInstance_1 = findHistoricUserTask(
processInstance, activity_1.getId());
if (activityInstance_1 == null) {
tempList.remove(activity_1);
if (tempList.size() & 1) {
ActivityImpl activity_2 = tempList.get(1);
HistoricActivityInstance activityInstance_2 = findHistoricUserTask(
processInstance, activity_2.getId());
if (activityInstance_2 == null) {
tempList.remove(activity_2);
if (activityInstance_1.getEndTime().before(
activityInstance_2.getEndTime())) {
tempList.remove(activity_1);
tempList.remove(activity_2);
if (tempList.size() & 0) {
return tempList.get(0);
* 查询指定任务节点的最新记录
* @param processInstance
* @param activityId
private HistoricActivityInstance findHistoricUserTask(
ProcessInstance processInstance, String activityId) {
HistoricActivityInstance rtnVal =
// 查询当前流程实例审批结束的历史节点
List&HistoricActivityInstance& historicActivityInstances = historyService
.createHistoricActivityInstanceQuery().activityType(&userTask&)
.processInstanceId(processInstance.getId()).activityId(
activityId).finished()
.orderByHistoricActivityInstanceEndTime().desc().list();
if (historicActivityInstances.size() & 0) {
rtnVal = historicActivityInstances.get(0);
return rtnV
* *******************************************************************************************************&br&
* ********************************以上为查询流程驳回节点核心逻辑***********************************************&br&
* ********************************************************************************************************&br&
* ********************************************************************************&br&
* **********************以下为activiti 核心service
* set方法***************************&br&
* *********************************************************************************&br&
public void setFormService(FormService formService) {
this.formService = formS
public void setHistoryService(HistoryService historyService) {
this.historyService = historyS
public void setRepositoryService(RepositoryService repositoryService) {
this.repositoryService = repositoryS
public void setRuntimeService(RuntimeService runtimeService) {
this.runtimeService = runtimeS
public void setTaskService(TaskService taskService) {
this.taskService = taskS
* ********************************************************************************&br&
* **********************以上为activiti 核心service
* set方法***************************&br&
* *********************************************************************************&br&
* ********************************************************************************&br&
* **********************以下为根据 任务节点ID 获取流程各对象查询方法**********************&br&
* *********************************************************************************&br&
public void setProcessOtherService(ProcessOtherService processOtherService) {
this.processOtherService = processOtherS
* 根据任务ID获得任务实例
* @param taskId
* @throws Exception
private TaskEntity findTaskById(String taskId) throws Exception {
TaskEntity task = (TaskEntity) taskService.createTaskQuery().taskId(
taskId).singleResult();
if (task == null) {
throw new Exception(&任务实例未找到!&);
* 根据流程实例ID和任务key值查询所有同级任务集合
* @param processInstanceId
* @param key
private List&Task& findTaskListByKey(String processInstanceId, String key) {
return taskService.createTaskQuery().processInstanceId(
processInstanceId).taskDefinitionKey(key).list();
* 根据任务ID获取对应的流程实例
* @param taskId
* @throws Exception
private ProcessInstance findProcessInstanceByTaskId(String taskId)
throws Exception {
// 找到流程实例
ProcessInstance processInstance = runtimeService
.createProcessInstanceQuery().processInstanceId(
findTaskById(taskId).getProcessInstanceId())
.singleResult();
if (processInstance == null) {
throw new Exception(&流程实例未找到!&);
return processI
* 根据任务ID获取流程定义
* @param taskId
* @throws Exception
private ProcessDefinitionEntity findProcessDefinitionEntityByTaskId(
String taskId) throws Exception {
// 取得流程定义
ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
.getDeployedProcessDefinition(findTaskById(taskId)
.getProcessDefinitionId());
if (processDefinition == null) {
throw new Exception(&流程定义未找到!&);
return processD
* 根据任务ID和节点ID获取活动节点 &br&
* @param taskId
* @param activityId
活动节点ID &br&
如果为null或&&,则默认查询当前活动节点 &br&
如果为&end&,则查询结束节点 &br&
* @throws Exception
private ActivityImpl findActivitiImpl(String taskId, String activityId)
throws Exception {
// 取得流程定义
ProcessDefinitionEntity processDefinition = findProcessDefinitionEntityByTaskId(taskId);
// 获取当前活动节点ID
if (StringUtil.isNull(activityId)) {
activityId = findTaskById(taskId).getTaskDefinitionKey();
// 根据流程定义,获取该流程实例的结束节点
if (activityId.toUpperCase().equals(&END&)) {
for (ActivityImpl activityImpl : processDefinition.getActivities()) {
List&PvmTransition& pvmTransitionList = activityImpl
.getOutgoingTransitions();
if (pvmTransitionList.isEmpty()) {
return activityI
// 根据节点ID,获取对应的活动节点
ActivityImpl activityImpl = ((ProcessDefinitionImpl) processDefinition)
.findActivity(activityId);
return activityI
* ********************************************************************************&br&
* **********************以上为根据 任务节点ID 获取流程各对象查询方法**********************&br&
* *********************************************************************************&br&
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:55557次
排名:千里之外
原创:29篇
转载:54篇
(1)(1)(2)(3)(1)(1)(1)(1)(1)(12)(15)(16)(23)(1)(2)(1)(1)

我要回帖

更多关于 activiti工作流原理 的文章

 

随机推荐