﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-囧囧之猪-随笔分类-workflow</title><link>http://www.blogjava.net/fullqin/category/34344.html</link><description /><language>zh-cn</language><lastBuildDate>Tue, 16 Sep 2008 13:38:52 GMT</lastBuildDate><pubDate>Tue, 16 Sep 2008 13:38:52 GMT</pubDate><ttl>60</ttl><item><title>【原】通过jbpm源码分析jbpm引擎内核工作原理</title><link>http://www.blogjava.net/fullqin/archive/2008/09/16/229236.html</link><dc:creator>囧囧之猪</dc:creator><author>囧囧之猪</author><pubDate>Tue, 16 Sep 2008 11:28:00 GMT</pubDate><guid>http://www.blogjava.net/fullqin/archive/2008/09/16/229236.html</guid><wfw:comment>http://www.blogjava.net/fullqin/comments/229236.html</wfw:comment><comments>http://www.blogjava.net/fullqin/archive/2008/09/16/229236.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/fullqin/comments/commentRss/229236.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fullqin/services/trackbacks/229236.html</trackback:ping><description><![CDATA[<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Jbpm，他是jboss下的一个开源项目，是个基于petri net理论为基础的工作流引擎。本文主要通过jbpm源代码分析下jbpm引擎内核工作原理。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Jbpm是基于微内核引擎的基础上扩展开发出来的工作流平台，其运行的核心包是在org.jbpm.graph下，在该包下又分有action、def、exe、log、node几个包，jbpm内核引擎实现逻辑主要存放在def、exe这两个包下，其他的包是基于此内核扩展出来的动作、模型和日志。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 下面我们通过一个简单的例子来逐步的分析jbpm是如何工作的。看下面jbpm自带演示的一个hello流程（视乎大家都喜欢从hello实现开始^_^），代码如下：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public void testHelloWorldProcess() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ProcessDefinition processDefinition = ProcessDefinition.parseXmlString(<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"&lt;process-definition&gt;" +<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;" &lt;start-state&gt;" +<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;" &lt;transition to='s' /&gt;" +<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;" &lt;/start-state&gt;" +<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;" &lt;state name='s'&gt;" +<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;" &lt;transition to='end' /&gt;" +<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;" &lt;/state&gt;" +<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;" &lt;end-state name='end' /&gt;" +<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"&lt;/process-definition&gt;"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ProcessInstance processInstance =new ProcessInstance(processDefinition);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Token token = processInstance.getRootToken();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;assertSame(processDefinition.getStartState(), token.getNode());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;token.signal();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;assertSame(processDefinition.getNode("s"), token.getNode());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;token.signal();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;assertSame(processDefinition.getNode("end"), token.getNode());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 首先，我们定义个流程模板（ProcessDefinition），就是上面代码的ProcessDefinition processDefinition = ProcessDefinition.parseXmlString(&#8230;.);这段，在括号中是jbpm定义的流程，其中包括三个环节，分别是starts-state、state和end-state。parseXmlString（）方法的主要功能是解析这段xml语言返回个流程模板对象（processDefinition）。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 接着，通过流程实例类（ProcessInstance）来实例化个流程实例，通过传进来的流程模板对象创建ProcessInstance processInstance =new ProcessInstance(processDefinition)。我们来看看new ProcessInstance(processDefinition)到底做了什么，通过查看ProcessInstance的源代码，可以看到其中主要的一段是<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public ProcessInstance( ProcessDefinition processDefinition ) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//略去其他代码<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.processDefinition = processDefinition; //将流程模板对象付给流程实例<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.rootToken = new Token(this); //创建跟令牌<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//略去其他代码<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 我们继续跟进Token这个类<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public Token(ProcessInstance processInstance) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //主要一句如下<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.node = processInstance.getProcessDefinition().getStartState();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;这样就实现了令牌绑定到开始节点。至此，一个流程实例就创建起来了，并且该流程实例走到了开始节点，即令牌所处的位置。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;我们接着往下走token.signal()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public void signal() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;signal(node.getDefaultLeavingTransition(), new ExecutionContext(this));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//这里的getDefaultLeavingTransition()如果有多条路径，则去第一条路径<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void signal(Transition transition, ExecutionContext executionContext) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //省略其他代码<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; node.leave(executionContext, transition);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //省略其他代码<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;这里的node就是刚才令牌所在的开始节点，我们来看看jbpm是如何将令牌从开始节点移到下个节点的。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public void leave(ExecutionContext executionContext, Transition transition) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Token token = executionContext.getToken();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; token.setNode(this);//此时令牌还在开始节点<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; executionContext.setTransition(transition);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //略去部分代码<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;executionContext.setTransitionSource(this);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; transition.take(executionContext);//实现令牌的转移<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;我们来看看transition.take(..)方法做了什么<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public void take(ExecutionContext executionContext) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //略去部分代码<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; to.enter(executionContext);//离开开始节点，进入到下个节点<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;大家可能会有点疑问，这个to节点是什么是否初始化的？其实在signal时有句node.getDefaultLeavingTransition()，这句返回Transition对象，该对象就已经初始化了to节点的对象。我们在跟进to.enter(..)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public void enter(ExecutionContext executionContext) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Token token = executionContext.getToken();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; token.setNode(this);//此时令牌就到了名字为&#8220;s&#8221;的state节点<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; token.setNodeEnter(new Date());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; executionContext.setTransition(null);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; executionContext.setTransitionSource(null);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; execute(executionContext);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;在这段代码中的注释这句，真正实现了令牌从开始节点到下个节点了。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;至此，jbpm工作流引擎的内部工作原理就介绍完了，其实这就是工作流引擎最核心的部分了，就是如何从一个环节转移到另一个环节。或许你会说&#8220;这么简单，我马上就可以写一个&#8221;，其实不然，上面我们所用的例子是十分简单的例子，其实在工作流联盟规范中还有其他复杂的节点模型，如split，join，subflow等。不过幸运的是这些复杂的节点模型jbpm都为我们提供了他自己的默认的实现，这些节点模型都在org.jbpm.graph.node包下。jbpm引擎中很好的抽象了节点模型Node类，大部分的复杂节点模型都继承自Node，我们也可以定制自己的节点，只要实现Node类的execute()方法即可方便的实现。其实从上面分析的代码可以看出，Node类主要的逻辑处理是在leave()、enter()和execute()三个方法，大家可以看下ProcessState，join，fork这些节点模型是如何实现的。<br />
以上简单介绍了jbpm引擎内核的工作原理，如有不对的地方还望指正。<br />
</p>
 <img src ="http://www.blogjava.net/fullqin/aggbug/229236.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fullqin/" target="_blank">囧囧之猪</a> 2008-09-16 19:28 <a href="http://www.blogjava.net/fullqin/archive/2008/09/16/229236.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>从基于db的workflow转战到jbpm</title><link>http://www.blogjava.net/fullqin/archive/2008/09/15/229013.html</link><dc:creator>囧囧之猪</dc:creator><author>囧囧之猪</author><pubDate>Mon, 15 Sep 2008 10:21:00 GMT</pubDate><guid>http://www.blogjava.net/fullqin/archive/2008/09/15/229013.html</guid><wfw:comment>http://www.blogjava.net/fullqin/comments/229013.html</wfw:comment><comments>http://www.blogjava.net/fullqin/archive/2008/09/15/229013.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/fullqin/comments/commentRss/229013.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fullqin/services/trackbacks/229013.html</trackback:ping><description><![CDATA[<p><span style="font-family: 宋体">&nbsp;&nbsp;&nbsp; 开始接触工作流是两年前，那时刚进公司，自己也算是个新手，到公司后被分配到做</span>IT<span style="font-family: 宋体">网管的项目组，做了些东西，后来成立了个新的项目组，我被分配到这个新组成的项目组，也就是从这以后开始接触工作流的。当时对工作流是一点概念都没有，慢慢从公司开发的基于</span>db<span style="font-family: 宋体">的工作流平台开始接触工作流，并基于此工作流平台结合业务开发了几个模块。<br />
</span><span style="font-family: 宋体">&nbsp;&nbsp;&nbsp; 公司的这个基于</span>db<span style="font-family: 宋体">的工作流平台还是实现了许多功能：<br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1<span style="font-family: 宋体">、基于</span>web<span style="font-family: 宋体">的流程设计器，主要是基于</span>IE<span style="font-family: 宋体">的</span>vml<span style="font-family: 宋体">语言开发的，可以设计出如下图的流程模板。<br />
<img alt="" src="http://www.blogjava.net/images/blogjava_net/fullqin/34626/r_4.gif" border="0" /><br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">此流程模板包括开始环节，结束环节以及人工处理的两个环节（专家组处理和发起人确认），实现环节的自循环以及回朔，分别在&#8220;专家组处理&#8221;环节和&#8220;发起人确认&#8221;环节上实现。基于此流程运行中的实例图如下：</span></p>
<img alt="" src="http://www.blogjava.net/images/blogjava_net/fullqin/34626/r_instance.gif" border="0" /><br />
&nbsp;&nbsp;&nbsp; 2<span style="font-family: 宋体">、环节的扭转<br />
</span>&nbsp;&nbsp;&nbsp; A<span style="font-family: 宋体">、串行<br />
</span><span style="font-family: 宋体">&nbsp;&nbsp;&nbsp; 像上图中介绍的就是实现了串行的功能。<br />
</span>&nbsp;&nbsp;&nbsp; B<span style="font-family: 宋体">、并行</span><span style="font-size: 10.5pt; font-family: 宋体">如图<br />
<img alt="" src="http://www.blogjava.net/images/blogjava_net/fullqin/34626/r_5.gif" border="0" /><br />
&nbsp;&nbsp;&nbsp; C<span style="font-family: 宋体">、多实例（即平常所说的会签）<br />
</span><span style="font-family: 宋体">&nbsp;&nbsp;&nbsp; 实现了包括所有会签都完成后才往下个环节走和几个会签后就可往下个环节走的功能，流程的模板如图：<br />
<img alt="" src="http://www.blogjava.net/images/blogjava_net/fullqin/34626/r_3.gif" border="0" /><br />
&nbsp;&nbsp;&nbsp; <span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">其中环节模板上带&#8220;</span><span lang="EN-US">M</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">&#8221;的环节就表示是多实例的环节。<br />
</span><span style="font-size: 10.5pt; font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-bidi-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">&nbsp;&nbsp;&nbsp; 运行中的实例如图：<br />
<img alt="" src="http://www.blogjava.net/images/blogjava_net/fullqin/34626/r_1.gif" border="0" /><br />
&nbsp;&nbsp;&nbsp; D<span style="font-family: 宋体">、子流程</span><span style="font-size: 10.5pt; font-family: 宋体">子流程是在一个虚拟环节中实现的，即该环节不是人工环节。如图：<br />
<img alt="" src="http://www.blogjava.net/images/blogjava_net/fullqin/34626/r_ss.gif" border="0" /><br />
&nbsp;&nbsp;&nbsp; <span style="font-size: 10.5pt; font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-bidi-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">基本上一个简单的工作流平台的功能都差不多实现了，不过在使用过程中还是发现了许多的弊端，毕竟系统的逻辑大部分是基于数据库函数实现的，这使得大部分的逻辑都要依赖于数据库，而外围的一些基于</span><span lang="EN-US" style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-fareast-font-family: 宋体">java</span><span style="font-size: 10.5pt; font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-bidi-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">的逻辑实现就比较难实现了，举个例子：在和外系统做接口时，当某个环节竣工后要向外系统发信息，而信息是通过</span><span lang="EN-US" style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-fareast-font-family: 宋体">url</span><span style="font-size: 10.5pt; font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-bidi-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">的方式传递的，这个用</span><span lang="EN-US" style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-fareast-font-family: 宋体">java</span><span style="font-size: 10.5pt; font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-bidi-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">实现是很容易的，而用数据库函数就无法直接实现了（据目前自己掌握的技术判断，不知是否有办法实现，望知道者告知），现在变通的一个做法是在数据库里保存信息，然后通过</span><span lang="EN-US" style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-fareast-font-family: 宋体">quartz</span><span style="font-size: 10.5pt; font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-bidi-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">定时的扫描该表，有数据则通过</span><span lang="EN-US" style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-fareast-font-family: 宋体">httpclient</span><span style="font-size: 10.5pt; font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-bidi-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">给外系统发送信息。还有模型本身只有开始环节，结束环节，虚拟环节和人工执行环节，使得客户提的要按业务路由的功能就无法实现了，因为缺少个判断环节模板，就是</span><span lang="EN-US" style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-fareast-font-family: 宋体">jbpm</span><span style="font-size: 10.5pt; font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-bidi-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">中的</span><span lang="EN-US" style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-fareast-font-family: 宋体">decision</span><span style="font-size: 10.5pt; font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-bidi-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">环节模板，所以在创建下个环节的时候大部分都是人为的主观去判断到底是走上图中的&#8220;方案审核&#8221;还是&#8220;任务分配&#8221;环节。这使得运用流程整合业务逻辑时并没有完全的实现流程的自动化。<br />
&nbsp;&nbsp;&nbsp; <span style="font-size: 10.5pt; font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-bidi-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">其实还有很多的缺陷，只是我们都是通过变相的方式给予了实现，可是客户有些需求在该平台上还是无法实现的。鉴于此，就开始寻找开源的工作流引擎，在</span><span lang="EN-US" style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-fareast-font-family: 宋体">osworkflow</span><span style="font-size: 10.5pt; font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-bidi-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">、</span><span lang="EN-US" style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-fareast-font-family: 宋体">jbpm</span><span style="font-size: 10.5pt; font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-bidi-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">、</span><span lang="EN-US" style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-fareast-font-family: 宋体">shark</span><span style="font-size: 10.5pt; font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-bidi-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">等的开源工作流引擎中选择了</span><span lang="EN-US" style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-fareast-font-family: 宋体">jbpm</span><span style="font-size: 10.5pt; font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-bidi-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">。为什么会选择</span><span lang="EN-US" style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-fareast-font-family: 宋体">jbpm</span><span style="font-size: 10.5pt; font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-bidi-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">呢？原因还是蛮多的，具体列出几条如下几条：<br />
</span>&nbsp;&nbsp;&nbsp; 1、&nbsp;<span style="font-family: 宋体">基于</span>petri net<span style="font-family: 宋体">理论实现的工作流。<br />
</span>&nbsp;&nbsp;&nbsp; 2、&nbsp;<span style="font-family: 宋体">引擎核心以微内核的方式实现（主要逻辑都在</span>graph<span style="font-family: 宋体">包下）。<br />
</span>&nbsp;&nbsp;&nbsp; 3、&nbsp;<span style="font-family: 宋体">基于</span>hibernate<span style="font-family: 宋体">实现持久化。<br />
</span>&nbsp;&nbsp;&nbsp; 4、&nbsp;<span style="font-family: 宋体">很容易的和</span>spring<span style="font-family: 宋体">实现整合，通过</span>spring-modules<span style="font-family: 宋体">实现整合。<br />
</span><span style="font-size: 10.5pt; font-family: 宋体">等。最后附上一个最复杂的流程图（像蜘蛛网更贴切^_^）<br />
</span></span></span></span></span></span></span><img alt="" src="http://www.blogjava.net/images/blogjava_net/fullqin/34626/r_2.gif" border="0" />&nbsp; 
 <img src ="http://www.blogjava.net/fullqin/aggbug/229013.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fullqin/" target="_blank">囧囧之猪</a> 2008-09-15 18:21 <a href="http://www.blogjava.net/fullqin/archive/2008/09/15/229013.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>