




已阅读5页,还剩17页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
三十六 工作流软件中的那些人如果我们把预定义的流程比喻成一条从起点到终点的公交线路,那么流程定义中的步骤,就表示车站。汽车到站后人员有上车下车等行为,这就可以认为是流程中的动作。流程定义完后,就按照预定义好的线路往下走,当然业务流程的规则是比公交线路更复杂。业务流程的流转离不开人员的参与,工作流软件的定义就是:自动运作的业务过程部分或整体,表现为参与者对文件、信息或任务按照规程采取行动,并令其在参与者之间传递。在工作流软件中,有步骤的所有者,动作的执行人,任务的参与者,工单的执行人等等很多关于人的概念。下面一一解释工作流软件产品中的关于人的概念:业务流程建模的创建人:标识由谁创建的,对流程建模文件的一个辅助说明,主要存放在 流程建模的定义表中。业务流程建模的修改人:标识修改人,刚创建的时候,可以就是创建人,辅助查找以后由谁修改过。业务流程实例的创建人:业务流程建模后,就需要按照这个预定义的过程,启动流程实例了。一般来说,每个流程实例的创建人,都是属于流程建模时初始化动作的可执行人。业务流程实例的完成人:流程实例运转到结束前,最后一个步骤的执行人,就是流程实例的完成人。步骤的执行人:当流程实例完成一个步骤后,即这个步骤成为历史步骤后,就一定会产生一个此步骤的执行人,谁来完成的此步骤,谁就是此步骤的执行人。步骤的执行人,是一个具体的人,不会是一个对人员的分类等的概念。步骤的所有者:当业务流程在建模的时候,动作的结果导向另外一个步骤,在进入此步骤之前,给此步骤设置 了一个步骤的所有者,那么这个步骤就有所有者了。当流程实例运行到此步骤的时候,这个步骤的所有者就有值了。步骤所有者可以是一个具体的人,也可以是一个 变量(当流程实例运行到此步骤之前,给这个变量赋值,到达的时候,能获取到变量的值,否则,步骤所有者就会是空)。步骤的所有者只能是一个人,不会是一个 对人员的分类(例如角色,用户组等)。历史步骤的执行人:和步骤执行人一样,步骤执行完成后,均成为历史步骤,每个历史步骤都一定会 有一个步骤的执行人。常常用变量mostRecentCaller来表示,并辅助一个前置函数,将指定历史步骤的执行人,保存到 mostRecentCaller变量中。mostRecentCaller是临时变量,注意要在流程的一次流转中,前面环节赋值,后面的环节才能获取到 值。注:历史步骤的执行人,可用于当流程再次返回到此步骤后,仍然交给原来的步骤执行人再次执行,例如,谁填写的报销单审核不通过,打回给原来的填写人重新填写。或者后面的步骤执行人需要是以前步骤的执行人。历史步骤的执行人和历史步骤的所有者均可作此运用。历史步骤的所有者:首先要此步骤在流程建模的时候,动作结果导向此步骤后,设置了此步骤的所有者。当这 个步骤成为历史步骤后,获取此步骤的的所有者,就是历史步骤的所有者。常常用mostRecentOwner变量来表示,和 mostRecentCaller一样,是临时变量,需要在流程的一次流转中,前面的环节利用前置函数给mostRecentOwner变量赋值,后面的 环节才能获取到此值。和mostRecentCaller的区别是,每个历史步骤,不一定会有历史步骤的所有者(需要设置了才会 有),mostRecentCaller是一定会有的。当前执行者:就是执行流程的操作人。在流程建模的时候,可以用caller变量来表示,caller变 量也是临时变量,在流程的一次流转前面环节给caller变量赋值,后面的环节就可以获取caller变量的值来使用。给caller变量赋值,用 将当前执行者保存到变量caller 这个前置函数。动作的执行人:就是当前步骤的当前可执行动作的执行人。动作是否可执行,有条件可以设置,当流程实例在运行时,当前执行者符合当前步骤的当前动作的条件,此动作就是当前可执行的动作。动作的条件,可以是限制人,也可以是业务规则的限制。动作的可执行人:当流程建模时,动作的条件设置,是一个人,或者是一个角色等,那么这个人,或者是有这个角色的所有人 都是此动作的可执行人。任务的创建人:当流程实例运转的时候,会根据节点的设置产生任务记录,谁执行的流程,产生的任务记录,任务的创建人就是谁。任务的分配人:在eworkflow工作流软件中,任务的分配人通常就是指任务的创建人。任务的参与人:顾名思义,就是可以看到此任务并参与执行任务的人。在eworkflow工作流软件中,任务的参与人,不一定就是任务的最后完成人。任务的签收人:这是针对竞争型任务设置的,当产生竞争型任务时,谁先签收了此任务,谁就是任务的签收人,其它人就不能再执行此任务了。任务工单的执行人:在工作流软件中,一条任务信息,可能会产生多个任务工单。任务工单的完成人:谁完成的任务工单,谁就是任务工单的完成人。一条任务工单,只会有一个完成人。任务的完成人:因为任务会产生多条派发的工单,所以任务工单的完成人,也就是任务的完成人(任务的完成人可能是多个)。任务的抄送人抄送给某些用户,任务的抄送人只能查看任务,不能执行任务。.随着工作流软件系统的不断升级,工作流软件的那些人,还会继续的添加.三十七 自由流的实现(续)工作流系统的自由流实现了不按照流程预定义的轨迹流转,即需要在节点之间任意的跳转。上 一篇自由流的实现主要说明了跳转规律,如果是单节点间的跳转,只要有当前的节点,以及跳转到的节点,就ok了。但是当当前节点和任意跳转到的节点之间有分 支并发线路后,就不是简单的跳转了,当分支套分支,分支主干等之间的跳转就更复杂了。如果是这种串行路由,就很简单了。但是这样的多路分支,分支嵌套分支的,就很复杂了。因此在实现的时候,必需找出,当前节点到跳转到的节点之间的轨迹线路。又因为分支之间是可以嵌套的,所以必需用递归来遍历这之间的轨迹。由当前节点开始,查找这个节点的动作结果节点是否为跳转到的节点,如果是,则找到之间的轨迹,返回。如果不是,则将当前这个节点的动作结果节点作为当前节点,继续调用这个函数,查找,直到找到后退出。因为流程定义的轨迹,可以是循环的轨迹,即一个节点的动作结果可以返回到前面的节点,如:当返回到前面的节点时,用递归调用的话,就永远也退不出循环了。因此,将处理过的节点放到traceNodeList中,每次调用递归函数前,均判断一下,此节点是否在traceNodeList中,如果在,就不用处理了。不在的继续处理。eworkflow自定义工作流系统有.net版和java版,两个版本的实现过程完全一样,只是一个是c#语言的一个是java语言的。c#的递归函数:private ArrayList getJoinsAndSplitsBwteenStep(WorkflowDescriptor wd,IDictionary orgNodeMap,ResultDescriptor theResult,ArrayList traceNodeList)ArrayList tagList = new ArrayList();string nodeType =(System.String)orgNodeMapnode_type;AbstractDescriptor node = (AbstractDescriptor)orgNodeMapnode; ArrayList results = new ArrayList();if (nodeType.Equals(join)JoinDescriptor join = (JoinDescriptor)node;results.Add(join.Result);if (nodeType.Equals(split)SplitDescriptor split = (SplitDescriptor)node;results.AddRange(split.Results);if (nodeType.Equals(subflow)SubflowDescriptor subflow = (SubflowDescriptor)node;results.Add(subflow.unconditionalResult);results.AddRange(subflow.conditionalResults);if (nodeType.Equals(step)StepDescriptor step = (StepDescriptor)node;ArrayList actions = step.actions;for (IEnumerator iter = actions.GetEnumerator();iter.MoveNext();)ActionDescriptor action =(ActionDescriptor)iter.Current;ResultDescriptor result = action.UnconditionalResult;results.Add(result);results.AddRange(action.ConditionalResults); bool bFind=false;for (IEnumerator it = results.GetEnumerator();it.MoveNext();)ResultDescriptor result = (ResultDescriptor)it.Current;if (result.Id=theResult.Id)/找到跳转到的节点,退出bFind = true;break;if (bFind) return tagList;/将当前处理节点 存入traceNodeList中traceNodeList.Add(node); for (IEnumerator iterator = results.GetEnumerator();iterator.MoveNext();)ResultDescriptor resultDesc = (ResultDescriptor)iterator.Current;int joinid = resultDesc.join;int splitid = resultDesc.Split;int stepid = resultDesc.Step;int subflowid = resultDesc.subflow;int traceid = 0;IDictionary orgMap = new Hashtable();/记录节点信息if (joinid0)IDictionary m = new Hashtable();mjoin = joinid;/new Integer(joinid);tagList.Add(m);JoinDescriptor join = wd.getJoin(joinid);orgMapnode_type = join;orgMapnode = join;traceid = joinid;if (splitid0)SplitDescriptor split = wd.getSplit(splitid);orgMapnode_type = split;orgMapnode = split;IDictionary m = new Hashtable();msplit = splitid;/ new Integer(splitid);for (int i=0;i0)StepDescriptor step = wd.getStep(stepid);orgMapnode_type = step;orgMapnode = step;traceid = stepid;if (subflowid0)SubflowDescriptor subflow = wd.getSubflow(subflowid);orgMapnode_type = subflow;orgMapnode = subflow; traceid = subflowid;/判断 关联到的节点 是否处理过bool inTrace = false;for (IEnumerator itrace=traceNodeList.GetEnumerator();itrace.MoveNext();)AbstractDescriptor trace = (AbstractDescriptor)itrace.Current;if (trace.Id=traceid)/已经处理过的了inTrace = true;break;if (!inTrace)tagList.AddRange(getJoinsAndSplitsBwteenStep(wd,orgMap,theResult,traceNodeList);return tagList;java的递归函数: private List getJoinsAndSplitsBwteenStep(WorkflowDescriptor wd,Map orgNodeMap,ResultDescriptor theResult,List traceNodeList) throws WorkflowException List tagList =new ArrayList(); String nodeType =(String)orgNodeMap.get(node_type); AbstractDescriptor node = (AbstractDescriptor)orgNodeMap.get(node); List results = new ArrayList(); if (nodeType.equals(join) JoinDescriptor join = (JoinDescriptor)node; results.add(join.getResult(); if (nodeType.equals(split) SplitDescriptor split = (SplitDescriptor)node; results.addAll(split.getResults(); if (nodeType.equals(subflow) SubflowDescriptor subflow = (SubflowDescriptor)node; results.add(subflow.getUnconditionalResult(); results.addAll(subflow.getConditionalResults(); if (nodeType.equals(step) StepDescriptor step = (StepDescriptor)node; List actions = step.getActions(); for (Iterator iter = actions.iterator();iter.hasNext();) ActionDescriptor action =(ActionDescriptor)iter.next(); ResultDescriptor result = action.getUnconditionalResult(); results.add(result); results.addAll(action.getConditionalResults(); boolean bFind=false; for (Iterator it = results.iterator();it.hasNext();) ResultDescriptor result = (ResultDescriptor)it.next(); if (result.getId()=theResult.getId()/找到跳转到的节点,退出 bFind = true; break; /return tagList; if (bFind) return tagList; /将当前处理节点 存入traceNodeList中 traceNodeList.add(node); for (Iterator iterator = results.iterator();iterator.hasNext();)ResultDescriptor resultDesc = (ResultDescriptor)iterator.next();int joinid = resultDesc.getJoin();int splitid = resultDesc.getSplit();int stepid = resultDesc.getStep();int subflowid = resultDesc.getSubflow();int traceid = 0;Map orgMap = new HashMap();/记录节点信息if (joinid0)Map m = new HashMap();m.put(join, new Integer(joinid);tagList.add(m);JoinDescriptor join = wd.getJoin(joinid);orgMap.put(node_type, join);orgMap.put(node, join);traceid = joinid;if (splitid0)SplitDescriptor split = wd.getSplit(splitid);orgMap.put(node_type, split);orgMap.put(node, split);Map m = new HashMap();m.put(split, new Integer(splitid);/tagList.add(m);for (int i=0;i0)StepDescriptor step = wd.getStep(stepid);orgMap.put(node_type, step);orgMap.put(node, step);traceid = stepid;if (subflowid0)SubflowDescriptor subflow = wd.getSubflow(subflowid);orgMap.put(node_type, subflow);orgMap.put(node, subflow); traceid = subflowid;/判断 关联到的节点 是否处理过boolean inTrace = false;for (Iterator itrace=traceNodeList.iterator();itrace.hasNext();)AbstractDescriptor trace = (AbstractDescriptor)itrace.next();if (trace.getId()=traceid)/已经处理过的了inTrace = true;break;if (!inTrace)tagList.addAll(getJoinsAndSplitsBwteenStep(wd,orgMap,theResult,traceNodeList); return tagList; 三十八 工作流软件中的定时器处理工作流软件中的定时器处理,一般分为两种:应用服务启动就启动的定时器这种类型和通常的web系统中的定时器处理一样。应用服务器启动后,定时器就启动了,然后按照定制的时间段轮询处理。当应用服务器关闭的时候,这种 定时器才会关闭。这种定时器通常是对所有需要定时处理的记录来做的,在工作流软件中,就对应到所有的业务流程,所有的流程实例。这种类型的定时器,在报表软件,报表产品中经常有用到,比如 每天晚上定时生成按日汇总表,每个月未生成月结汇总表。在工作流软件系统中,可以利用这种定时器按计划启动业务流程的流程实例。按计划扫描执行那些过期需要自动处理的任务等等。由流程的流转来启动定时器当流程示例流转到某个节点时,启动这个节点的定时器,按定时器设置的 时间间隔轮询执行处理。当流程流转流程实例离开这个节点了,这个定时器就关闭了。这种类型的定时器,和流程的特定节点关联,每个流程实例都会经历定时器的 启动执行关闭 这样整个过程。在eworkflow工作流系统中 定时器有三种处理方式:1. 应用服务器启动就启动的定时器。2. 流程的节点中挂接的定时器。3. 定制实现的定时器处理。下面详解三种处理方式:1. 应用服务器启动就启动的定时器。 定时器的执行程序,轮询的间隔时间,以及相关参数设置都在fcconfig.xml文件中。 当应用程序启动的时候,从fcconfig.xml中查找定时器的配置信息。根据配置信息启动定时器。 一个典型的fcconfig.xml文件中的配置信息如下: 0 0 1 * * ? USR_0000001trigger:1group:1job:130 0/1 * * * ? USR_0000001trigger:2group:2job:23 一个节点为一个定时器的定义。 属性 className 中设置的类为定时器启动后,按时间点执行的代码 .fcsoft.workflow.timer.StartWorkflowJob 是定时启动指定流程实例的处理代码。 0 0 1 * * ? 这个节点定义是轮询的时间间隔,节点值的设置,从左到右的意义如下:字段名 允许的值 允许的特殊字符 秒 0-59 , - * / 分 0-59 , - * / 小时 0-23 , - * / 日 1-31 , - * ? / L W C 月 1-12 or JAN-DEC , - * / 周几 1-7 or SUN-SAT , - * ? / L C # 年 (可选字段) empty , 1970-2099 , - * / 一些典型的cronExpression表达式的含义如下:0 0 12 * * ? 每天中午十二点触发 0 15 10 ? * * 每天早上10:15触发 0 15 10 * * ? 每天早上10:15触发 0 15 10 * * ? * 每天早上10:15触发 0 15 10 * * ? 2005 2005年的每天早上10:15触发 0 * 14 * * ? 每天从下午2点开始到2点59分每分钟一次触发 0 0/5 14 * * ? 每天从下午2点开始到2:55分结束每5分钟一次触发 0 0/5 14,18 * * ? 每天的下午2点至2:55和6点至6点55分两个时间段内每5分钟一次触发 0 0-5 14 * * ? 每天14:00至14:05每分钟一次触发 0 10,44 14 ? 3 WED 三月的每周三的14:10和14:44触发 0 15 10 ? * MON-FRI 每个周一、周二、周三、周四、周五的10:15触发 0 15 10 15 * ? 每月15号的10:15触发 0 15 10 L * ? 每月的最后一天的10:15触发 0 15 10 ? * 6L 每月最后一个周五的10:15触发 0 15 10 ? * 6L 每月最后一个周五的10:15触发 0 15 10 ? * 6L 2002-2005 2002年至2005年的每月最后一个周五的10:15触发 0 15 10 ? * 6#3 每月的第三个周五的10:15触发 USR_0000001 为启动流程的用户userid,如果这个用户没有权限则流程实例不能启动。 为初始化流程需要访问的数据库连接的连接名 节点是fcconfig.xml中定义的数据库连接信息的dsn名称。即ds name=daqin dbType=sqlserver . 节点中 name属性后面设置的名称。如果此节点值为空或没有设置此节点,则用fcconfig.xml中的第一个ds节点中设置的数据库连接信息。 trigger:1group:1job:1这几个节点为定时器中的triggerName,groupName,jobName等。通常是每个每个定时器中的名称不一样。用于标识定时器启动后,需要执行的job。3这种这种节点为传递业务数据的节点,有几个需要传递到流程中的业务数据,就设置几个arg 的节点。在流程初始化的时候,会将这种节点的数据加载到流程的上下文中。2、流程的节点中挂接的定时器这种类型的定时器,是利用流程节点的前置函数挂接 计划执行触发器的定时器类 来启动的。当流程实例流转到这个节点时,执行前置函数,启动定时器。按设置的时间轮询,执行这个前置函数中定义的触发器。触发器类为定时执行的业务处理。当流程实例离开这个节点时,后置函数中,挂接取消执行触发器的定时器, 关闭这个定时器。一个典型的应用,前置函数中的设置如下: true test testTrigger 10 -对应触发器的id号 计划执行触发器的定时器类 test true 0,5,10,15 * * * * ? .fcsoft.workflow.util.ScheduleJob testJob .fcsoft.workflow.util.UnscheduleJob test testTrigger 取消执行触发器的定时器 在eworkflow工作流软件中触发器类也是前置函数类,实现了FunctionProvider接口,能获得流程上下文中的信息。在触发器类中,做实际的业务处理。3、定制实现的定时器处理这种类型的定时器处理,是按应用系统的业务需要,定制实现。既不是在服务器启动的时候,启动定时器,也不是在流程的流转当中启动定时器。而是在应用系统的界面中,增加启动定时器,和关闭定时器的功能。例如 一个流程实例启动了,在显示运行轨迹的界面上,增加启动定时器的功能,定时执行此流程实例的动作,达到自动执行此流程的效果,当流程实例运行结束后,就关闭此定时器,避免资源的浪费。也可以由操作员点击关闭此定时器,达到灵活的控制。三十九 利用工作流引擎给业务系统建模工作流软件系统,都会包含一个工作流引擎,流程设计器等。工作流引擎是工作流系统的微内核,是多种业务流程的抽象。工作流引擎设计的好坏,直接影响到流程的功能。工作流引擎包含一些基本的节点,利用这些节点组合出各种各样的路由结构,利用这些路由结构来标识各式的业务流程,也就是说利用这些基本的节点能给业 务流程建模,流程引擎能建立并解释这些节点,并利用用户输入,自动执行,定时执行,外部调用等等使得流程得以递进,达到流程的流转。所以要理解一套工作流 软件系统产品,首先必须要理解流程引擎的这些基本节点,才能将大千世界中各式各样的业务流程表达出来,即给业务流程建模。工作流引擎中包含基本的节点:步骤:表示业务环节,例如 登记,审核 等等,都可以认为是一个步骤。如果我们把工作流比喻成一条从起点站驶向终点站的公共汽车路线,那么步骤就相当于汽车站台。在给一个具体的业务流程建模时, 首先要定下这个流程中有那些步骤,就象首先要定下公交线路中那些地方设置站点一样。动作: 表示工作流中每一步骤中需要处理的事,通常为用户输入,自动执行,外部调用等等。动作挂接业务模块,动作的执行(包含业务模块的提交)导致业务流程的递进。动作结果:工作流中每一个动作执行完毕以后都有一个结果,结果导向另外的步骤,这样达到流程的递进。动作的结果在工作流系统中是一个很重要的概念。公共汽车停站下客就好比一个动作,动作完成以后,开向下一站,或者加油,或者返程等等就都是动作结果。条件: 按设置的条件返回的结果决定不同的路由方向。条件为true时,导向有条件结果,条件为false时,导向无条件结果。有条件结果/无条件结果:在eworkflow中动作结果分为有条件结果和无条件结 果。有条件结果中设置条件表达式,或者执行业务规则判断,返回true时,导向有条件结果关联到的下一步;返回false,则执行无条件结果关联到的下一 步。每个动作都必须包含一个无条件结果和0到多个有条件结果。循环: 用有条件结果导回原来的路径,构成一个封闭的回路,这样来构成一个循环路由。当工作流运行时,如果满足动作结果的条件,就一直会在循环路由中进行,只有当不满足条件了,才能跳出循环,继续执行。用这种循环路由加上定时器的轮询处理,能达到自动执行循环的效果。任务:当流程实例到达步骤时产生任务,任务和动作一样,是步骤中待要处理的事,只是任务是通过执行 动作来完成的。在eworkflow工作流软件产品中,任务节点不是必须的,只是对动作节点的一个分类和关联。任务分为竞争型,直接指派型,会签型,平均 分配型,还可以按需扩展出自己的类型。在流程建模时,可以指派任务的执行人,参与人,抄送人等。静态分支:是指需要并行处理多件事情而没有先后顺序。在eworkflow工作流软件产品中,就是到达静态分支后,平行分支成流程设计时的多个步骤节点。动态分支:是指需要没有先后顺序的并行处理多件事情,只是每条分支中处理事情的轨迹是一样的,在流程建模时,只 需要设计一条模版分支,在每个流程实例到达分支之前,需要动态的得到这次的动态分支个数,到达分支后,根据模版分支路线加动态分支个数,动态复制出多个分 支,这些分支的执行是没有先后顺序的。静态合并:和静态分支匹配,将多个静
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 地下室考试题及答案
- 地理地图考试题目及答案
- 导游考试题诠释题及答案
- 单招药学考试题及答案
- 大专心理考试题及答案
- 中国偏硼酸钡项目商业计划书
- 大林和小林考试题及答案
- 村委后备书记考试题及答案
- 2025房产交易买卖合同模板
- 审查行政协议书
- 消化内镜教学课件
- 垂钓园转让合同(标准版)
- 医疗耗材采购流程及合同范本
- 智算产业园人才引进与培养方案
- 2024贵州省社区《网格员》备考题汇编(含答案)
- 无人机侦察机课件
- 西藏公务员2025年真题
- 安全生产第二季度会议纪要
- 2025年《医疗器械生产监督管理办法》培训考核试题附答案
- (正式版)DB46∕710-2025 《天然橡胶初加工行业污染物排放标准》
- GB/T 45762-2025精细陶瓷室内照明环境下半导体光催化材料测试用光源
评论
0/150
提交评论