通常在利用流程设计器给业务流程建模之后,会生成一个流程描述的xml文件,业务流程的每个环节步骤,需要执行的操作,自动的,手动的等等信息,都被描述在这个流程建模的xml文件中。xml文件的内容,是一些规则的预先定义的抽象的节点信息,流程引擎负责这些节点的定义,创建,解释,定位等等,业务流程利用这些节点建模。建模完成的业务流程,挂接上业务表单后,就可以直接运行业务流程了。
业务流程的运行,从启动流程实例开始,启动一个流程实例即代表开始了一次业务流程处理。每例业务流程的处理过程,都包含从创建,到激活,到处理,到结束(当然中间也可以人为的直接终止,或挂起,再恢复),这样一个过程。流程实例创建后,就按照流程建模的xml文件,按照定义的节点路由顺序一步一步的流转,相应业务也在相应的步骤中处理。
流程实例按照节点路由顺序,每执行一次,代表一次流转。每次的流转包含流程节点的状态升迁和办理业务数据的提交,通过工作流的事务,控制这些状态升迁和业务数据达到同步和一致性。一旦这个流程实例结束了或意外终止了,都代表业务办理完成了,就再也不能再次发生流转了。
工作流实例的一次流转,会涉及到流程节点状态的升迁和办理业务数据的提交。
下面示意图,抽取流程一次流转的定义示意:从步骤A环节-》到达步骤B
当流程实例到达步骤A的时候,当前流程实例的状态=步骤A+步骤A的状态,当执行动作A的时候,通过 动作A的 结果导向 步骤B。当到达步骤B的时候,当前流程实例的状态=步骤B + 步骤B的状态。流程实例的状态通过执行动作A达到了升迁,当在动作A上面绑定了业务表单,业务数据也随着动作A的执行一起提交。业务数据的提交和流程状态的升迁是在同一个事务中的,保证数据的一致性。
从上面的分析可以看出,流程的一次流转涉及到如下图中红色框中选中的部分。为什么步骤A和步骤B会分别是一半呢,下面我们来详细说明,流转过程中,每个流程基本元素的流转顺序。
在工作流系统的基本元素中,有一些前置后置函数,可以挂接到流程的节点上。当流程实例到达这个节点的时候,会触发前置函数,离开这个节点会触发后置函数,就象事件一样。事件的内容是可以自己任意发挥的,就像一个button的点击函数一样,点击后做什么事情,有编写程序的人来编写代码。这里的前置后置函数也是一样,当触发了前置后置函数后,内容可以是预置的一些系统函数,也可以是业务流程建模者自定义做的一些业务模块,体现流程的扩展性。
上图中只描述了动作的前置后置,步骤的前置后置,实际上动作的结果,也有前置后置函数,便于做扩展用。实际上可以引入业务模块的不仅是前置后置函数,动作的可执行条件也可以引入业务规则的判断。例如一个请假的流程,在审核请假是否通过时,可以引入一个判断规则,将请假申请人的总年假-已经休的假期=可休年假天数,再和当前申请的天数比较,如果大于则申请通过,否则不通过。
综合上面的描述,我们可以看出流程的一次流转的先后顺序为:
步骤的后置函数-》动作的前置函数-》完成本步骤的任务-》检查动作结果中的条件(不成立则无条件结果)-》动作结果的前置-》 创建新的当前步骤(执行新步骤的前置函数)-》 动作结果的后置-》 动作的后置函数
因为执行动作后,会离开本步骤,所以首先是从本步骤的后置函数开始的。
其中,创建新的当前步骤,关联到任务信息,所以也有个处理过程顺序:
本步骤标记完成,转到历史步骤-》下一步为当前步骤-》关闭当前步骤的所有未完成的任务-》到达新步骤,先生成新步骤的所有任务-》再执行新的当前步骤的前置函数。
业务流程在建模的时候,可以利用一些流程的上下文中的变量等做一些控制,也可以引入一些关键的业务数据做判断用。这涉及到流程的持久变量和临时变量。
例如,获取当前流程实例的创建者,作为一个变量,传递给接下来的第一个步骤作为第一个步骤任务的参与者。
这可以用一个流程的临时变量来处理:
在流程初始化动作(或动作结果)的前置函数中,将当前流程实例的创建者保存到变量caller中。然后在下一步骤的任务参与人中,就可以引入caller变量,获取他的值了。
因为caller变量是个临时变量,仅存在于流程的一次流转的中。当流程的这次流转结束了,这个变量就实效了。就像一个子函数一样,在子函数的开始,给变量caller赋值,在接下来的代码中就可以获取这个变量的值了。
所以在用流程的临时变量时候,通常都是在相应节点的前置函数中,给变量赋值,按照流程的流转顺序,在相应的后置节点中获取变量的值。
同样的方式还适用于mostRecentCaller,mostRecentOwner 这两个变量,获取指定步骤的执行者和获取指定步骤的所有者,这两个变量都属于发生了的历史步骤才能获取到。
流程的持久化变量,就与临时变量不一样了,只要流程的任意节点中保存了值,在后续的任意节点中都可以获取到值。这个不局限于流程的一次流转,流程多次流转都可以。只要在任意一次流转中保存了变量的值了,后续的任意流转中就都可以取值了。
例如一个报销流程中,报销申请是否通过,审核人将这个结果作为一个持久化的变量保存到流程中了。则在申请人查看审核结果的环节,就可以取出这个审核结果了。审核的那次流转,和查看环节,这是流程的两个环节。不是流程的一次流转,但是审核的那次流转,必须先于查看环节,先将变量的值持久化进去,然后后续的环节就能获取值了。