微型工作流引擎-功能设计

我的微型工作流引擎-功能设计解析及使用示例

一、前言

上一篇我给大家介绍了我的工作流的模型和基本的设计,这篇我想详细说明下我这款工作流的功能及使用示例。这款工作流主要是面向开发者设计的,为了先让大家有个全局的认识,局部功能的设计实现就不细说了,后续有时间我会继续写文章向大家介绍。

二、功能详解及使用示例代码

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(180))
    .SetMemo("memo1")
    .Create()   //创建流程定义
    .Parse()    //解析xml

流程创建时,版本号是自动生成的,默认从1.0开始,当流程名称相同时,就会生成不同版本。 
在xml中可定义不同的任务节点:开始节点、自动节点、人工节点、决策节点、发散节点、聚合节点、子流程节点、会签节点、等待节点、结束节点。 
及连接任务节点的路由、人员分配情况、变量定义、事件动作等信息,可参照我上篇文章中的xml定义

//加载流程定义
var processDefinition = bpm.LoadProcessDefiniton("1");
processDefinition.Deploy();     //发布流程定义
processDefinition.Revoke();     //召回流程定义
processDefinition.Delete();     //删除流程定义

5、流程实例

//发起流程实例
var process = bpm.NewProcessIntance("请假流程","萧秦");
process.SetVariable("project_id", 1399); //保存流程变量
process.Start();   //启动
process.Suspend(); //挂起
process.Resume();  //恢复
process.Cancel();  //撤销
process.End();     //结束

这里NewProcessInstance这个方法实例上有三个参数,第一个是流程定义ID,第二个是启动的业务ID,第三个是子流程的返回栈点ID,非子流程可以忽略。

//启动流程
var startTask = process.Start();
startTask.SetRecord("SO20150903001");       //保存表单数据(关联)
startTask.SetAttach("01", "02");            //保存附件信息(关联),可多个
startTask.SetVariable("var1", "value1");    //保存任务变量
startTask.Signal();                         //转交下一步

task.SetRecord用于保存当前表单数据id,数据本身保存在业务表中 
task.SetAttach用于保存当前节点的附件id,附件信息则保存在附件管理表中 
task.Signal流程流转的关键方法,根据流程定义触发token令牌离开动作

//审批任务
var task = bpm.LoadTaskInstance("00");
task.SetOpinion(SignResult.Passed, "我同意");  //设置审批意见
task.SetReceiver("颜经理");                    //设置下一步的审批人
task.Signal();                                //转交下一步

这里提供了SetReceiver的方法设置下一步的审批人,正常情况下流程定义中已经定义好了,是不需要再进行设置的,但是考虑在实际应用中可能会有把任务给指定领导审批的情况,在通达OA中也是可以设置下一步审批人,故添加了此方法,需要时可以调用,注意应用此方法会覆盖定义中对工作项owner属性的设置。

//任务委派
var task1 = bpm.LoadTaskInstance("01");
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("02");
task2.ToCountersign(RunMode.Parallel, DecisionMode.Vote, true, 0.65M);
task2.CountersignAdd(new Countersigner() { actor_id = "张三", vote_weight = 1 });
task2.CountersignAdd(new Countersigner() { actor_id = "李四", vote_weight = 0.5 });
task2.CountersignAdd(new Countersigner() { actor_id = "小五", vote_weight = 2 });

并行模式即为并加签,前加签、后加签的前提是串行模式,假设task2为串行、主办人模式、原审批人为萧秦

//前加签
task2.CountersignAddBefore("萧秦", new Countersigner() { actor_id = "张三"});

//后加签
task2.CountersignAddAfter("萧秦", new Countersigner() { actor_id = "李四", is_sponsor = true});

减签则相对比较简单了

//减签
task2.CountersignRemove("王五");

会签节点转普通审批,直接让一个人决策

//转审批
 task2.ToSinglesign("隔壁老王");

自由流模式,创建临时路直接跳转到指定节点进行审批

//自由流
var task3 = bpm.LoadTaskInstance("03");
task3.SetFreeRedirect("总经理审批");
task3.Signal();

7、回退机制 
流程回退到指定节点

//流程实例指定任意节点回退
var process2 = bpm.LoadProcessInstance("02");
process2.Rollback("填写请假单");

任务实例回退到上一步

//当前工作任务回退到上一个审批节点
var task4 = bpm.LoadTaskInstance("04");
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(30)) //生效期间
   .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)的工作流引擎,接口也简单易于二次开发,支持多数据库并且功能还算强大。从前年开始的简易版本设计开发到现在基本成形,测试也是花费了大量的时间,可能还有问题没有测到,不过现在基本稳定。接下来如果有时间我会慢慢跟大家介绍功能细节的设计和实现,还有什么功能我考虑不周全的或意见或有哪部分想详细了解的都可以给我留言。

时间: 2024-10-27 07:32:08

微型工作流引擎-功能设计的相关文章

我的微型工作流引擎-功能设计解析及使用示例

一.前言 上一篇我给大家介绍了我的工作流的模型和基本的设计,这篇我想详细说明下我这款工作流的功能及使用示例.这款工作流主要是面向开发者设计的,为了先让大家有个全局的认识,局部功能的设计实现就不细说了,后续有时间我会继续写文章向大家介绍. 二.功能详解及使用示例代码 1.配置流程引擎,一般在程序启动过程中调用(Global.asax.cs中) //初始化流程引擎 BpmConfiguration .Instance() .Config(@"C:\Configration\BpmConfig.xml

微型工作流引擎设计

微型工作流引擎设计 一.前言 提到工作流很多人就会想到OA,的确OA就是典型的工作流的应用,但是工作流并不仅仅局限于OA,工作流应该算是基础框架软件,主要用于流程的重组和优化,它有广阔的应用领域.在java下有很多优秀的开源工作流可以选择比如activit5.jpbm4等,在.net下却几乎找不到令人满意的工作流引擎可用.当然不是说.net下没有开源的只是有些国产开源的但看了代码后就一点兴趣都没有了,且不说代码质量如何,还引入了一大堆的东西,想在项目中应用也是非常困难.鉴于此我还是决定自己开发一

我的微型工作流引擎设计

一.前言 提到工作流很多人就会想到OA,的确OA就是典型的工作流的应用,但是工作流并不仅仅局限于OA,工作流应该算是基础框架软件,主要用于流程的重组和优化,它有广阔的应用领域.在java下有很多优秀的开源工作流可以选择比如activit5.jpbm4等,在.net下却几乎找不到令人满意的工作流引擎可用.当然不是说.net下没有开源的只是有些国产开源的但看了代码后就一点兴趣都没有了,且不说代码质量如何,还引入了一大堆的东西,想在项目中应用也是非常困难.鉴于此我还是决定自己开发一款.NET微型工作流

我的微型工作流引擎-办公应用实战

一.前言 前面已经给大家介绍了我的工作流引擎的总体设计及的API设计,这篇是实战篇说说怎么实际应用了,这就得涉及到UI界面了.首先我们常用的工作流个人办公应用系统至少要包括发起流程.待办事项.已办事项等.我们设计了一个尽量简单的系统,能够满足个人办公的基本需求,只实现以下功能:     1.发起流程     2.待办事项     3.已办事项     4.我的流程     5.我的消息     6.我的委办 这些功能基本就是流程能正常的运行流转基础,其实只应用了我们引擎的一小部分功能,其它功能如

几种开源工作流引擎的简单比较(转)

摘要:目前开源工作流引擎用的最多的是jbpm , 各种特性都不错, 文档也比较多, 下面只简单列举一下 目前开源工作流引擎用的最多的是jbpm , 各种特性都不错, 文档也比较多, 下面只简单列举一下 其他几种工作流引擎的特性.   Apache ODE Enhydra Shark Bonita Open Business Engine Eclipse JWT  支持的流程建模标准  WS-BPEL 2.0,流程定义必须使用该标准编写才能执行 WfMC和OMG标准 符合WfMC规范 遵循WfMC

《程序猿闭门造车》之NBPM工作流引擎 - 项目整体架构

前言: 又是一年一度的圣诞节,可这关我什么事呢 :( ,好不容易周末了,还是说说其他的吧,前不久我发布了一篇关于工作流的文章:<程序猿闭门造车>之NBPM工作流引擎 - 开篇,很多爱好工作流的小伙伴对该组件表示感兴趣,所以我打算写一个系列文章来介绍该组件的一些情况,给关心该组件的小伙伴们一些参考和帮助. 先列个目录吧(由于我工作比较忙,只能周末抽空来分享相关资料,进度上还希望大家理解): 01.<程序猿闭门造车>之NBPM工作流引擎 - 开篇02.<程序猿闭门造车>之N

ccbpm工作流引擎是怎样支持多种流程模式的

前言: 在BPM领域支持流程运转的理论模型有多种.有的21种.28种.32种. 每种模式都代表了这样的模式的理论设计者研究者的人员主张.思想.这些模式尽可能的,全然去覆盖到现实生产.工作.应用上的流程流转规则. 可是不论什么领域都有自己未探索到的流程运转可能,假设说自己的理论可以涵盖全部的应用需求,那就说的有点太早. 就类似于世界上的教派或者哲学家一样.不同的教主与哲学家有不同的世界观.不同的世界认识,都对自己的"追随者"来宣扬自己的主张.观点,可是他们也能"和谐"

工作流引擎驳回设计

1.1 关于驳回 驳回,在有的应用中叫“回退”.驳回是中国特色的一种方式,驳回在流程图上也没有迁移线的表达经常也是隐性的,比如申请经费可能由于资料不足被驳回来补充资料,像这样的例子有非常多,也很常见. 驳回是工作流参与者对自己“待办任务”的一种操作,即参与者主动回退待办任务列表中的任务到已经执行过的人工节点. 回退的情况实际上是非常复杂的,有串行上的驳回,也有并行内的驳回,并行区内驳回到并行区外,从分支驳回到主干等,从主干驳回到分支内,多重聚合的驳回等.驳回过程中会发生很多事情,也会可能导致重走

Atitit。&#160;&#160;工作流引擎的发展趋势

Atitit.  工作流引擎的发展趋势 1.1. 图灵完备1 1.2. 图形化与文本化1 1.3. Jit1 1.4. Dsl化2 1.5. Oo2 1.6. 托管与本地代码的互操作2 1.7. 大型标准库2 1.8. 异常处理机制2 2. 参考2 1.1. 图灵完备 现有工作流引擎 比如jbpm 的最大问题是不是图灵完备的,不能作为一个通用图形化编程语言来实现所有系统. 简单判定图灵完备的方法就是看该语言能否模拟出图灵机 图灵不完备的语言常见原因有循环或递归受限(无法写不终止的程序,如 whi