我的微型工作流引擎-功能解析及API设计
一、前言
上一篇我给大家介绍了我的工作流的模型和基本的设计,这篇我想详细说明下我这款工作流的功能及使用示例。这款工作流主要是面向开发者设计的,为了先让大家有个全局的认识,局部功能的设计实现就不细说了,后续有时间我会继续写文章向大家介绍。
二、功能详解及使用示例代码
1、配置流程引擎,一般在程序启动过程中调用(Global.asax.cs中)
//初始化流程引擎
BpmConfiguration
.Instance()
.Config(@"C:\Configration\BpmConfig.xml")
.Start();
如果不指定配置文件,则默认从app.config或web.config中读取流程配置
//初始化流程引擎
BpmConfiguration
.Instance()
.Start();
当然还支持同时启动多个流程引擎,以提供SAAS程序的支持。
//A租户引擎配置
BpmConfiguration
.Instance("TenantA")
.Config(@"C:\BpmConfigA.xml")
.Start(); //B租户引擎配置
BpmConfiguration
.Instance("TenantB")
.Config(@"C:\BpmConfigB.xml")
.Start();
XML中的配置包括:数据库连接、日志配置文件、任务计划启动延时、任务计划执行周期、用户关系结构的映射、流程中变量类型的拓展等。
2、取得工作流上下文,即工作流的入口,所有的功能都集中在这个入口上。
var bpm = new BpmContext()
.UseTransaction(true)
.SetActor("萧秦");
当前对于不同的引擎实例,其上下文是不同的
var bpm = new BpmContext("TenantA");
var bpm = new BpmContext("TenantB");
不传构造参数时,返回的是默认实例。
3、事务支持,是否开启事务、提交、回滚。
bpm.UseTransaction(true);
bpm.Commit();
bpm.Rollback();
4、流程定义
//新增流程定义
bpm.NewProcessDefinition("请假流程")
.SetXmlFile(@"C:\Definition\demo1.xml")
.SetCategory("分类1")
.SetEffectDate(DateTime.Now)
.SetExpireDate(DateTime.Now.AddDays())
.SetMemo("memo1")
.Create() //创建流程定义
.Parse() //解析xml
流程创建时,版本号是自动生成的,默认从1.0开始,当流程名称相同时,就会生成不同版本。
在xml中可定义不同的任务节点:开始节点、自动节点、人工节点、决策节点、发散节点、聚合节点、子流程节点、会签节点、等待节点、结束节点。
及连接任务节点的路由、人员分配情况、变量定义、事件动作等信息,可参照我上篇文章中的xml定义
//加载流程定义
var processDefinition = bpm.LoadProcessDefiniton("");
processDefinition.Deploy(); //发布流程定义
processDefinition.Revoke(); //召回流程定义
processDefinition.Delete(); //删除流程定义
5、流程实例
//发起流程实例
var process = bpm.NewProcessIntance("请假流程","萧秦");
process.SetVariable("project_id", ); //保存流程变量
process.Start(); //启动
process.Suspend(); //挂起
process.Resume(); //恢复
process.Cancel(); //撤销
process.End(); //结束
这里NewProcessInstance这个方法实例上有三个参数,第一个是流程定义ID,第二个是启动的业务ID,第三个是子流程的返回栈点ID,非子流程可以忽略。
//启动流程
var startTask = process.Start();
startTask.SetRecord("SO20150903001"); //保存表单数据(关联)
startTask.SetAttach("", ""); //保存附件信息(关联),可多个
startTask.SetVariable("var1", "value1"); //保存任务变量
startTask.Signal(); //转交下一步
task.SetRecord用于保存当前表单数据id,数据本身保存在业务表中
task.SetAttach用于保存当前节点的附件id,附件信息则保存在附件管理表中
task.Signal流程流转的关键方法,根据流程定义触发token令牌离开动作
//审批任务
var task = bpm.LoadTaskInstance("");
task.SetOpinion(SignResult.Passed, "我同意"); //设置审批意见
task.SetReceiver("颜经理"); //设置下一步的审批人
task.Signal(); //转交下一步
这里提供了SetReceiver的方法设置下一步的审批人,正常情况下流程定义中已经定义好了,是不需要再进行设置的,但是考虑在实际应用中可能会有把任务给指定领导审批的情况,在通达OA中也是可以设置下一步审批人,故添加了此方法,需要时可以调用,注意应用此方法会覆盖定义中对工作项owner属性的设置。
//任务委派
var task1 = bpm.LoadTaskInstance("");
task1.AssignCandidate("小郑,小胡"); //添加任务候选人
task1.AssignCandidate("saler", ActorType.Role); //添加任务候选人
task1.AssignTo("李四"); //把任务分配给李四
我的工作流中,对于工作任务只能有一个所有者(owner),一个实际操作者(actor),但可以拥有多个候选人(candidate)。
候选人是当前工作可分配的一范围限制或人员列表,owner是任务的拥有者,actor是owner考虑复杂委办关系后计算出的操作者。
task.AssignCandidate这个方法用于添加任务候选人,第二个参数是对象类型,可以直接添加一个角色、机构、用户组等。
task.AssignTo即分配任务,任务的分配状态包括以下几个状态
public enum AssignStatus
{
//未决
Pending, //认领, 用户认领任务并接收任务输入数据
Claim, //委办, 委派给另一个人(例如,经理)以代替他或她执行任务
Depute, //到期, 没有在指定的时间段内处理批准任务
Expire, //续订, 没有在给定的时间范围内处理此任务,则该任务将被续订,以便在另一时间段内执行
Renew
}
如果流程卡到某个节点很久,我们可以发催办消息
如果一个流程节点的确需要很久才能完成,我设计了一个当前工作进度汇报接口
//工作催办
task.Urge("很急,请经理尽快处理,在线等!"); //汇报当前工作进度
task.Report(0.6, "预计这个星期就能完成");
task.Urge会向任务实际拥有者发送一条催办通知,并生成催办历史。
task.Report会向任务的订阅者(所有关注当前流程任务的人)发送一条进度报告。
//查询变量
var var0 = process.GetVariable("project_id");
var var1 = task1.GetVariable("var1");
var var2 = task1.GetVariable<DateTime>("var2");
var var3 = task1.GetVariableObject("var3");
变量分为三种:
流程变量 会持久化,存在于整个的流程周期内
任务变量 会持久化,存在在当前的任务中
临时变量 不会持久化到数据库中,只存在于当前执行上下文中(executionContext)。
设置变量SetVariable 获取变量GetVariable
支持任意数据类型
6、中国特色审批方式,主要包括会签、加签(前加签、后加签、并加签)、减签、自由流
会签:一个任务由多个人参与共同做决策
加签:这个任务我自己觉得没有把握,想加入一个人或多个人跟我共同决策(在前加签顺序在当前决策者之前,后加签顺序在当前决策者之后,并加签不分顺序并行处理)
减签:跟加签相反,取消某人参与决策的资格
自由流:流程定义中没有,临时添加的动态路由直接把当前工作发送到指定的节点审批。
转会签:由单人决策的普通审批节点转成多人共同决策的会签节点,支持递归会签,即会签子节点可以继续转会签节点 。
转审批:由多人共同决策的会签节点转成单人决策的普通审批节点
在我在工作流中,会签设计了以下几个参数:
a 运行模式,并行时如发散节点,进入会签节点时会同时激活所有参与人的工作任务,串行时则有先后顺序,所以才有了前加签和后加签
public enum RunMode
{
//串行
Serial, //并行
Parallel
}
b 决策模式,根据子节点的结果如何去决策会签节点
public enum DecisionMode
{
//主办人模式
Sponsor, //投票模式
Vote, //一票通过
OnePass, //一票否决
OneVeto
}
主办人模式:需要设置一个主办人,结果以主办人的决策为准,其它人的决策只是提供参考
投票模式:即设置一个通过的比例,由大家投票决定。支持设置每个人的投票权重。
一票通过:其实可以看作是投票模式通过率设置大于0%的一种。
一票否决:可以看作投票模式通过率设置100%的一种。
当然这里只是我把常用的几种模式列出来了,还可以自己拓展决策模式,只需要继承实现我定义的抽象类Decision即可。
c 是否等待,即还有人未表决,但目前已表决的情况已经可以确定会签结果的情况下,需不需要等待其它人表决完成后才继续转交下一步。
会签分两种,一种是流程定义中定义好的会签,一种是普通审批节点临时转成会签的。实际上中国式审批其实就是要灵活,如果在流程定义中定义好的,其实可以不用会签节点,用多个普通节点也可以去实现。会签节点的设计主要是为了转会签这个场景:就是当前普通审批节点的审批人觉得自己没有把握或者不想担责任,可以加入上级领导或其它更多的人一起来决策或提供参考意见。
示例:普通审批转会签 运行模式设置为并行,决策模式是权重投票,需要等待所有人都投票,通过线为65%
//转会签
var task2 = bpm.LoadTaskInstance("");
task2.ToCountersign(RunMode.Parallel, DecisionMode.Vote, true, 0.65M);
task2.CountersignAdd(new Countersigner() { actor_id = "张三", vote_weight = });
task2.CountersignAdd(new Countersigner() { actor_id = "李四", vote_weight = 0.5 });
task2.CountersignAdd(new Countersigner() { actor_id = "小五", vote_weight = });
并行模式即为并加签,前加签、后加签的前提是串行模式,假设task2为串行、主办人模式、原审批人为萧秦
//前加签
task2.CountersignAddBefore("萧秦", new Countersigner() { actor_id = "张三"}); //后加签
task2.CountersignAddAfter("萧秦", new Countersigner() { actor_id = "李四", is_sponsor = true});
减签则相对比较简单了
//减签
task2.CountersignRemove("王五");
会签节点转普通审批,直接让一个人决策
//转审批
task2.ToSinglesign("隔壁老王");
自由流模式,创建临时路直接跳转到指定节点进行审批
//自由流
var task3 = bpm.LoadTaskInstance("");
task3.SetFreeRedirect("总经理审批");
task3.Signal();
7、回退机制
流程回退到指定节点
//流程实例指定任意节点回退
var process2 = bpm.LoadProcessInstance("");
process2.Rollback("填写请假单");
任务实例回退到上一步
//当前工作任务回退到上一个审批节点
var task4 = bpm.LoadTaskInstance("");
task4.Rollback();
8、工作委办
张三把某个任务直接委托给李四办理,支持递归委办关系,即张三委托给李四,李四再委托给王五,王五在委托给赵六…
bpm.NewDeputeService("张三", "李四")
.ForTaskInstance("任务实例ID")
.Depute();
把整个流程实例委托给李四,即此流程实例下所有的张三的任务都会委托给李四
bpm.NewDeputeService("张三", "李四")
.ForProcessInstance("流程实例ID")
.Depute();
把某个流程定义中的一个任务节点委托给李四,即所有的这个节点创建的所有任务实例如果是张三的任务都会委托给李四
bpm.NewDeputeService("张三", "李四")
.ForTaskDefinition("任务定义ID")
.Depute();
把某个流程定义委托给李四,即这个流程中创建的所有的任务实例,如果是张三的任务,在设置的生效期间中都会委托给李四
bpm.NewDeputeService("张三", "李四")
.ForProcessDefinition("流程定义ID")
.SetDateRange(DateTime.Now, DateTime.Now.AddDays()) //生效期间
.SetMemo("这个月出差,这个流程都委托给李四代办") //委托说明
.Depute();
收回委托关系,只要将Revoke替换Depute动作即可
//收回委办工作
bpm.NewDeputeService("张三", "李四")
.ForProcessInstance("流程实例ID")
.Revoke();
9、关注订阅
这个功能跟委托相似,订阅后会收到流程动态或任务动态消息提醒,如:流程已创建、启动、挂起…,任务已创建、分配给谁、进度汇报、任务完成等等
//关注订阅
bpm.NewSubscribeService("张三")
.ForTaskInstance("任务实例ID")
.Subscribe(); bpm.NewSubscribeService("张三")
.ForProcessInstance("流程实例ID")
.Subscribe(); bpm.NewSubscribeService("张三")
.ForProcessDefinition("流程定义ID")
.Subscribe(); bpm.NewSubscribeService("张三","李四","王五")
.ForTaskDefinition("任务定义ID")
.Subscribe();
取消订阅,一样只需要把Subscribe改为Unsubscribe即可
//取消订阅
bpm.NewSubscribeService("李四")
.ForProcessDefinition("采购流程")
.Unsubscribe();
10、数据查询
查询我没有提供接口,直接开放数据库查询比我提供的接口会更加灵活,比如:
a 查询已发布的流程定义
select * from bpm_definition_process where state = 'Deploy'
流程定义状态包括
public enum ProcessDefinitionState
{
//创建
Create, //解析
Parse, //发布
Deploy, //回收
Revoke, //删除
Delete
}
b 我的流程
select * from bpm_instance_process where state = 'Run' and starter = '萧秦'
流程状态包括
public enum ProcessState
{
//创建
Create, //运行
Run, //挂起
Pending, //终止
Termination, //完成
Complete, //取消
Cancel
}
c 我的待办任务
select * from bpm_instance_task where state = 'Run' and actor_id = '萧秦'
待办任务包括了别人委托给你的任务,如果只想看属于自己的任务则可以
select * from bpm_instance_task where state = 'Run' and owner_id = '萧秦'
任务状态包括
public enum TaskState
{
//创建, 任务已被创建
Create, //阻塞, 到达线中有阻塞任务还未完成
Blocking, //启动
Run, //完成, 用户已经完成任务并提供了任务的输出数据
Complete, //失败, 用户已经完成任务, 并且提供了错误消息
Failure, //回退
Rollback
}
d 查询任务的候选人信息
select * from bpm_instance_assignment where task_instance_id = 'ID'
e 查询我的消息
select * from bpm_application_notify where state='Unread' and reciever_id = '萧秦'
其它查询就不再举例了
三、总结
之前我有说过我开发这个的引擎的目的是为了在做项目时,有一个体积轻巧,引入方便的单dll文件(发布后大小为1.1M)的工作流引擎,接口也简单易于二次开发,支持多数据库并且功能还算强大。从前年开始的简易版本设计开发到现在基本成形,测试也是花费了大量的时间,可能还有问题没有测到,不过现在基本稳定。接下来如果有时间我会慢慢跟大家介绍功能细节的设计和实现,还有什么功能我考虑不周全的或意见或有哪部分想详细了解的都可以给我留言。联系13606021792
我的微型工作流引擎-功能解析及API设计的更多相关文章
- CCBPM工作流引擎的消息机制与设计
keyword:ccflowjflow 消息机制流程引擎 自己主动发送短信 发送邮件 发送消息 流程引擎微信连接 消息接口 关于ccbpm: 我们把ccflow jflow两个版本号的工作流引擎统称为 ...
- 浅谈备受开发者好评的.NET core敏捷开发工具,讲讲LEARUN工作流引擎
通俗来讲,所谓一个工作流管理系统,如果将其拆分出来一个个单讲话,大致可理解为由工作流引擎.工作流设计器.流程操作.工作流客户界面. 流程监控.表单设计器.与表单的集成以及与应用程序的集成等几个部分组成 ...
- 工作流引擎JFlow与activiti 对比分析(一)5种基本控制流模式的对比
为了更好的说明activiti 与jflow的两款工作流引擎的特点与区别,我们按照如下几个方面做一次全面的.客观的对比. 首先activiti是国外的一款开源的工作流程引擎,在国际上影响比较深远与广泛 ...
- 【2016-11-7】【坚持学习】【Day22】【工作流引擎设计--执行用户】
最近在做一个工作流引擎,架构师已经设计好了,但是我发现他设计 每一步的用户集合的设计,有一定的不足,或者是不方便,不同的组织架构影响着他的用户数据源配置方式. 于是我想花点时间去看看人家优秀是工作流引 ...
- 驰骋开源的asp.net工作流程引擎java工作流 2015 正文 驰骋工作流引擎ccflow6的功能列表
关键词: 驰骋工作流引擎 ccflow的功能列表 工作流功能列表 表单引擎功能列表 我们工作流引擎ccflow6重构之后对功能做了一些调整,要想快速了解ccbpm的功能,可以以下面列表为准 ...
- 驰骋工作流引擎ccflow-流转自定义功能使用说明
流转自定义功能使用说明 关键字: 驰骋工作流程快速开发平台 工作流程管理系统 工作流引擎 asp.net工作流引擎 java工作流引擎. 节点跳转 节点流转自定义 应用背景: 有一些流程在运行过程中是 ...
- .net工作流引擎ccflow开发平台属性功能的隐藏显示介绍
关键字: 工作流程管理系统 工作流引擎 asp.net工作流引擎 java工作流引擎. 表单引擎 工作流功能说明 工作流设计 工作流快速开发平台 业务流程管理 bpm工作流系统 java工 ...
- Java工作流引擎的测试容器-功能-使用方法-注意事项
工作流引擎的测试容器-功能-使用方法-注意事项 关键字 Ccbpm, ccflow,jflow,工作流引擎,工作流引擎测试容器,表单引擎 功能说明 工作流的测试容器是为了解决手工模拟人工登录模式下测试 ...
- .net工作流引擎ccflow新增支持PostgreSQL数据库的功能的发布说明
关键字: 驰骋工作流程快速开发平台 工作流程管理系统 工作流引擎 asp.net工作流引擎 java工作流引擎. 各位驰骋工作流引擎爱好着,经过驰骋公司与正元公司的共同努力,ccflow支持Post ...
随机推荐
- 【转】ETL数据增量抽取——通过触发器方式实现
在使用Kettle进行数据同步的时候, 共有 1.使用时间戳进行数据增量更新 2.使用数据库日志进行数据增量更新 3.使用触发器+快照表 进行数据增量更新 今天要介绍的是第3中方法. 实验的思路是这样 ...
- js 添加节点dom
var elemet = document.createElement("p"); var attr=document.createAttribute("align&qu ...
- 关于iOS构建版本提交iTunes后,一直不出现,没加号的解决方案
最近第一次遇到,正常打包,上传iTunes App Store,都能正常upload. 也可能是因为刚升了Xcode 8 的缘故,莫名其妙的小问题... 描述如下: 如果进iTunes的活动界面,也能 ...
- js判断手机访问PC端跳转到手机站
<script type="text/javascript">(function() { //得到域名后缀 var path = location.pathname.s ...
- [转] cordova-plugin-x-toast
本文转自:https://www.npmjs.com/package/cordova-plugin-x-toast cordova plugin add https://github.com/Eddy ...
- 平面直接坐标系线段相交问题(小Q(钟神)的问题)
[问题描述] 小 Q 对计算几何有着浓厚的兴趣.他经常对着平面直角坐标系发呆,思考一些有趣的问题.今天,他想到了一个十分有意思的题目:首先,小 Q 会在?轴正半轴和?轴正半轴分别挑选?个点.随后,他将 ...
- Sass关于颜色函数的乐趣
阅读目录 1. 了解RGB和HSL颜色标准 2. RGB函数 3. HSL函数 4. Opacity函数 5. 其他颜色函数 6. 一个简单的应用 在Sass中,定义了很多现成的函数,可供我们使用.在 ...
- 手机开启HDR后拍照有什么不同?
转自http://www.leiphone.com/news/201406/hdr-pic.html HDR这词大家可能并不陌生,但大部分人只是听过而已,在脑子并没有太多的概念,可能只是简单的认为HD ...
- Rhino 是一个完全使用Java语言编写的开源JavaScript实现。Rhino通常用于在Java程序中,为最终用户提供脚本化能力。它被作为J2SE 6上的默认Java脚本化引擎。
https://developer.mozilla.org/zh-CN/docs/Mozilla/Projects/Rhino
- $(window).load(function() {})和$(document).ready(function(){})的区别
JavaScript 中的以下代码 : Window.onload = function (){// 代码 } 等价于 Jquery 代码如下: $(window).load(function ( ...