- 浏览: 185683 次
文章分类
最新评论
-
yuxiangtong:
你好,请问如何匹配null列呢
Oracle正则表达式函数 -
dy.f:
last-regret 写道安装到最后一步,总是提示dnsmg ...
WINDOWS XP系统安装和配置DNS -
last-regret:
安装到最后一步,总是提示dnsmgmt.msc无法找到,这个问 ...
WINDOWS XP系统安装和配置DNS -
yinhe402:
[color=red][/color]
Oracle正则表达式函数 -
simpcity:
唉,看不懂啊。。。 能否分享一份源码出来啊
Liferay分页新闻列表(Journal Articles二次开发)
一个workflow有许许多多的step组成,而一个step到另一个step的流转是通过action来完成的。
我们先来看看actions的DTD声明
<!-- A list of zero or more common-actions and a list of zero or more actions for the enclosing step. Note that you must define one or the other, an actions element with neither will be considered invalid. Used in: step --> <!ELEMENT actions (common-action*, action*)>
actions的父节点是step,从声明中可以看出,我们可以在他的下面定制各种各样的common-action和action
从action说起
下面是action的定义
<!ELEMENT action (meta*, restrict-to? , validators?, pre-functions?, results, post-functions?)> <!ATTLIST action id CDATA #REQUIRED name CDATA #REQUIRED view CDATA #IMPLIED auto (TRUE | FALSE | true | false) #IMPLIED finish (TRUE | FALSE | true | false) #IMPLIED >
Attributes:
id: 标识符,在整个流程定义中,他必须唯一
name: 名称
view: a view name for the action
auto: 可选值(true|false),如果为true的话,这个action将在条件满足后会被自动执行,默认值false
finish: 可选值(true|false),默认值false
Action执行的Condition
Condition接口只有一个passesCondition方法,返回值是boolean,只有返回true的时候,我们的Action才可能被后续执行。下面是passesCondition的方法签名:
public boolean passesCondition(Map transientVars, Map args, PropertySet ps) throws WorkflowException;
passesCondition参数:
A、transientVars
作为一个Map类型的参数,他内部保存了一些内置的key-value,同时他也能保存着我们希望他保存的东西(我们可以通过在调用OSWorkflow的API的时候作为参数传递给他,稍后介绍)。
transientVars中的内置变量:
1、createdStep:新建Step的相关信息,保存的是Step接口的实现
2、currentSteps:保存当前的steps
3、descriptor:Workflow的Descriptor信息,保存的是WorkflowDescriptor实例
4、context:Workflow的上下文信息,保存的是WorkflowContext接口实现
5、entry:保存当前WorkflowEntry的实例
6、store:保存当前存储方式
7、configuration:保存Configuration接口的实现——DefaultConfiguration实例
8、actionId:保存当前actionId
9、jn:保存JoinNodes信息
他承载着以上的这些内置变量以及doAction方法的Map类型参数的值,并作为以下这些方法的参数在整个流程中共享和传递。
1、Condition接口的passesCondition方法,我们可以实现Condition接口来自定义条件,并配置到流程文件中的各种condition元素中去
2、Validator接口的validate方法,我们可以实现Validator接口来自定义验证器,并配置到流程文件中的各种validator元素中去
3、FunctionProvider接口的execute方法,我们可以实现FunctionProvider接口来自定义各种方法,并配置到流程文件中的各种function元素中去
这三个方法作为OSWorkflow流程最常见的扩展点,我们可以在自己实现相关接口的同时获取到这些变量信息,配合我们完成相关需求的实现。
B、args
我们先看一个流程定制文件的片段
<condition type="class"> <arg name="class.name">com.opensymphony.workflow.util.StatusCondition</arg> <arg name="status">Queued</arg> </condition>
args参数保存的就是在以上代码片段中的两个关于arg元素的配置部分的信息,我们可以在passesCondition方法中通过
args的get("status")方法或者相关参数的值。
C、ps
该参数对应的参数类型为com.opensymphony.module.propertyset.PropertySet,他可以将一些类型的变量以key-value的方式持久化到存储设备中去。我们以MYSQL数据库为例,看看他的庐山真面目
图1:
前三列为联合主键,entity_key是我们的key名称,对应的值则保存在key_type以后的那些列中,根据value值的类型不同来确定保存在哪一列中。
我们需要引入下面jar来支持PropertySet
propertyset-1.5.jar:基础包
propertyset-hibernate3-1.5.jar:通过hibernate的方式来持久化数据,这个包里有一个PropertySetItemImpl.hbm.xml的映射文件,可以根据情况使用。
内置的Condition
OSWorkflow给我们提供了一些Condition可以供我们直接使用。
图2:
其中AllowOwnerOfStepCondition、AllowOwnerOnlyCondition、DenyOwnerCondition已经被deprecated掉了,不推荐使用,而是用IsUserOwnerCondition替代啦。
IsUserOwnerCondition
IsUserOwnerCondition作为一个内置的Condition,他返回当前workflow实例的caller和owner的匹配结果。如果相等则返回true,否则为false。
BeanShellCondition
http://www.beanshell.org/
beanshell可以在嵌入到系统中,就像在执行脚本语言一样,在系统运行时动态的执行JAVA代码。我们也可以通过BeanShell调用我们的应用程序及其对象,它可以让JAVA对象和API动态运行。BeanShell是用JAVA写的,所以它可以和你的应用程序运行在同一个JVM空间内,我们也可以自由的传递实时对象的References到脚本代码中,调用相关方法并且作为结果返回。
以下是一个简单的配置例子,直接返回true
<condition type="beanshell"> <arg name="script">true</arg> </condition>
注意:
<arg name="script">我们的代码在这里</arg>
BSFCondition
Bean Scripting Framework(BSF)是一个支持在Java应用程序内调用脚本语言 (Script),并且支持脚本语言直接访问Java对象和方法的一个开源项目。有了它 , 你就能在java application中使用javascript, Python, XSLT, Perl, tcl, ……等一大堆scripting language。反过来也可以,就是在这些scripting language中调用任何已经注册过了的JavaBean、java object。
BSF最初是IBM的Alpha工作组的项目后来贡献给了Apache。以下是BSF支持的一些Script以及对应的处理Engine:
Languages.properties:
javascript = org.apache.bsf.engines.javascript.JavaScriptEngine, js jacl = org.apache.bsf.engines.jacl.JaclEngine, jacl netrexx = org.apache.bsf.engines.netrexx.NetRexxEngine, nrx java = org.apache.bsf.engines.java.JavaEngine, java javaclass = org.apache.bsf.engines.javaclass.JavaClassEngine, class bml = org.apache.bml.ext.BMLEngine, bml vbscript = org.apache.bsf.engines.activescript.ActiveScriptEngine, vbs jscript = org.apache.bsf.engines.activescript.ActiveScriptEngine, jss perlscript = org.apache.bsf.engines.activescript.ActiveScriptEngine, pls perl = org.apache.bsf.engines.perl.PerlEngine, pl jpython = org.apache.bsf.engines.jpython.JPythonEngine, py jython = org.apache.bsf.engines.jython.JythonEngine, py lotusscript = org.apache.bsf.engines.lotusscript.LsEngine, lss xslt = org.apache.bsf.engines.xslt.XSLTEngine, xslt pnuts = pnuts.ext.PnutsBSFEngine, pnut beanbasic = org.apache.bsf.engines.beanbasic.BeanBasicEngine, bb beanshell = bsh.util.BeanShellBSFEngine, bsh ruby = org.jruby.javasupport.bsf.JRubyEngine, rb judoscript = com.judoscript.BSFJudoEngine, judo|jud groovy = org.codehaus.groovy.bsf.GroovyEngine, groovy|gy objectscript = oscript.bsf.ObjectScriptEngine, os prolog = ubc.cs.JLog.Extras.BSF.JLogBSFEngine, plog|prolog rexx = org.rexxla.bsf.engines.rexx.RexxEngine, rex | rexx | cls | rxj | rxs
虽然BSF提供以上如此多Script的支持,但我们在使用的时候还得参考我们使用的BSF版本,并不是所有版本都支持以上这些Script Engine的。
以下是一个简单配置例子:
<condition type="bsf"> <arg name="language">java</arg> <arg name="source"></arg> <arg name="row">0</arg> <arg name="col">0</arg> <arg name="script">true</arg> </condition>
language参数的值则对应Languages.properties中的key,script则是需要执行的脚本或者代码的内容。
OSWorkflow根据language参数的值来映射由哪一种Engine来负责处理我们的script中的代码,所有的一切都是通过用BSFEngine的eval方法来完成的。以下是方法签名:
/** * This is used by an application to evaluate an expression. The * expression may be string or some other type, depending on the * language. (For example, for BML it'll be an org.w3c.dom.Element * object.) * * @param source (context info) the source of this expression * (e.g., filename) * @param row (context info) the line number in source for expr * @param col (context info) the column number in source for expr * @param script the expression to evaluate * * @exception BSFException if anything goes wrong while eval'ing a * BSFException is thrown. The reason indicates the problem. */ public Object eval(String source, int row, int col, Object script) throws BSFException;
source、row、col三个参数都是context info,并不是所有的BSFEngine都会用到这三个参数,目前只发现JavaScriptEngine有使用到。因为JavaScriptEngine最终是调用org.mozilla.javascript.Context的evaluateString方法来执行JS代码,这个方法里有用到了source和row两个参数,关于org.mozilla.javascript.Context的使用请大家自己参考API吧。所以说大多数时候,我们都只需要language和script两个参数。
JNDICondition
JNDICondition会接收一个name为jndi.location的参数,用来从JNDI中获得Condition的实例,并返回这个Condition实例的匹配结果。
<condition type="jndi"> <arg name="jndi.location">java:comp/env/myCondition</arg> </condition>
OSUserGroupCondition
OSUserGroupCondition接收一个name为group的参数,并与当前workflow的caller所属的group比较,如果caller在group中,则返回true,否则返回false。OSUserGroupCondition的使用需要依赖OSUser,OSUser也是opensymphony下一个项目,如果我们用OSUser来管理我们的用户,可以考虑使用该Condition。
Condition也可以是EJB,可根据情况选择LocalEJBCondition和RemoteEJBCondition。
StatusCondition
StatusCondition接收一个name为status的参数,并与当前workflow实例step的status属性作匹配。如果相等则返回true,否则为false。
<condition type="class"> <arg name="class.name">com.opensymphony.workflow.util.StatusCondition</arg> <arg name="status">Underway</arg> </condition>
自定义Condition
我们可以自已实现com.opensymphony.workflow.Condition接口,来定制我们自己的条件判断,配置如下:
<condition type="class"> <arg name="class.name">packagename.MyCondition</arg> ......other args </condition>
多个Condition可以组合使用,通过AND和OR来完成更加复杂的逻辑判断:
<conditions type="AND"> <condition type="beanshell"> <arg name="script">true</arg> </condition> <condition type="class"> <arg name="class.name">com.opensymphony.workflow.util.StatusCondition</arg> <arg name="status">Underway</arg> </condition> <condition type="class"> <arg name="class.name">com.opensymphony.workflow.util.AllowOwnerOnlyCondition</arg> </condition> </conditions>
conditions下面还可以有更多的conditions,以下是conditions的定义:
<!ELEMENT conditions (conditions | condition)*> <!ATTLIST conditions type (AND | OR) #IMPLIED >
让action使用Condition
<action id="1" name="Finish First Draft"> <restrict-to> <conditions type="AND"> <condition type="beanshell"> <arg name="script">true</arg> </condition> <condition type="class"> <arg name="class.name">com.opensymphony.workflow.util.StatusCondition</arg> <arg name="status">Underway</arg> </condition> <condition type="class"> <arg name="class.name">com.opensymphony.workflow.util.AllowOwnerOnlyCondition</arg> </condition> </conditions> </restrict-to> ..... </action>
Function
OSWorkflow中的com.opensymphony.workflow.FunctionProvider接口定义了所有function的统一行为,该接口只有一个execute方法。
public void execute(Map transientVars, Map args, PropertySet ps) throws WorkflowException;
该方法的参数和Condition的参数是一样的,可参考Condition接口参数的介绍。
OSWorkflow提供了很多内置的FunctionProvider实现,其中有一些function和condition的实现比较类似,如:BeanShellFunctionProvider、BSFFunctionProvider、JNDIFunctionProvider。
同时还提供了发送JMS消息的JMSMessage,用于发送邮件的SendEmail,以及用于处理Quartz的ScheduleJob和UnscheduleJob。
自定义Function
我们可以自己实现com.opensymphony.workflow.FunctionProvider接口,定制我们自己的Function。
function 可用于pre-functions, post-functions的XML定义中。
Action的validators
和Condition和Function一样,Validator也有一个接口定义——com.opensymphony.workflow.Validator
public void validate(Map transientVars, Map args, PropertySet ps) throws InvalidInputException, WorkflowException;
使用方法和Function一样没有区别。OSWorkflow给出了几个默认实现,和之前Funtion、Condition的相关实现类似,他们分别是BeanShellValidator、BSFValidator、JNDIValidator、LocalEJBValidator、RemoteEJBValidator等,具体使用方法可以参考之前Funtion、Condition部分的介绍。
和Function一样,我们可以自己实现com.opensymphony.workflow.Validator接口,来定制自己的Validator。
以下是一个配置示例片段:
<validators> <validator type="class"> <arg name="class.name">com.opensymphony.workflow.util.jndi.JNDIValidator</arg> <arg name="jndi.location">java:comp/env/MyValidator</arg> </validator> </validators>
TypeResolver
不论是Condition还是Function还是Validator,都有一个"type"属性作为#REQUIRED在ATTLIST的定义中,在我们之前的示例中有看到关于type的配置部分,有beanshell、bsf、jndi、class等等等等。我们到底有多少种选择,而OSWorkflow又是如何根据我们提供的type来定位最终的处理者呢——TypeResolver都帮我们搞定啦。
type的选择
TypeResolver的构造方法给出了所有支持的type方案,如下:
validators.put("remote-ejb", "com.opensymphony.workflow.util.ejb.remote.RemoteEJBValidator"); validators.put("local-ejb", "com.opensymphony.workflow.util.ejb.local.LocalEJBValidator"); validators.put("jndi", "com.opensymphony.workflow.util.jndi.JNDIValidator"); validators.put("beanshell", "com.opensymphony.workflow.util.beanshell.BeanShellValidator"); validators.put("bsf", "com.opensymphony.workflow.util.bsf.BSFValidator"); conditions.put("remote-ejb", "com.opensymphony.workflow.util.ejb.remote.RemoteEJBCondition"); conditions.put("local-ejb", "com.opensymphony.workflow.util.ejb.local.LocalEJBCondition"); conditions.put("jndi", "com.opensymphony.workflow.util.jndi.JNDICondition"); conditions.put("beanshell", "com.opensymphony.workflow.util.beanshell.BeanShellCondition"); conditions.put("bsf", "com.opensymphony.workflow.util.bsf.BSFCondition"); registers.put("remote-ejb", "com.opensymphony.workflow.util.ejb.remote.RemoteEJBRegister"); registers.put("local-ejb", "com.opensymphony.workflow.util.ejb.local.LocalEJBRegister"); registers.put("jndi", "com.opensymphony.workflow.util.jndi.JNDIRegister"); registers.put("beanshell", "com.opensymphony.workflow.util.beanshell.BeanShellRegister"); registers.put("bsf", "com.opensymphony.workflow.util.bsf.BSFRegister"); functions.put("remote-ejb", "com.opensymphony.workflow.util.ejb.remote.RemoteEJBFunctionProvider"); functions.put("local-ejb", "com.opensymphony.workflow.util.ejb.local.LocalEJBFunctionProvider"); functions.put("jndi", "com.opensymphony.workflow.util.jndi.JNDIFunctionProvider"); functions.put("beanshell", "com.opensymphony.workflow.util.beanshell.BeanShellFunctionProvider"); functions.put("bsf", "com.opensymphony.workflow.util.bsf.BSFFunctionProvider");
我们可以清晰看到他们各自都支持哪些type,以及他们各自的HandlerMapping。但是我们并没有看到type="class"这样的定义,TypeResolver又是如何处理的呢?我们看一段原型代码:
String className = (String) functions.get(type); if (className == null) { className = (String) args.get("class.name"); } if (className == null) { throw new WorkflowException("No type or class.name argument specified to TypeResolver"); } try { return (FunctionProvider)ClassLoaderUtil.loadClass(className.trim(), getClass()).newInstance(); } catch (Exception e) { log.error("Could not load class '" + className + "'", e); return null; }
真相大白,如果没有Resolver到对应的type,那么会参照class.name参数,并创建一个相应的实例。这种情况,多用于我们自己实现接口的场景。
SpringTypeResolver
SpringTypeResolver继承了TypeResolver,他提供了另外一种支持。
<function type="spring"> <arg name="bean.name">myFunction</arg> </function>
当type="spring"时, SpringTypeResolver就出场了,他会从spring的上下文中,返回bean.name中对应的Bean实例。
在上下文中使用SpringTypeResolver:
<bean id="workflowTypeResolver" class="com.opensymphony.workflow.util.SpringTypeResolver"/> <bean id="basicWorkflow" class="com.opensymphony.workflow.basic.BasicWorkflow"> <constructor-arg> <value>test</value> </constructor-arg> <property name="configuration"> <ref local="osworkflowConfiguration" /> </property> <property name="resolver"> <ref local="workflowTypeResolver" /> </property> </bean>
Action的Results
<!ELEMENT results (result*, unconditional-result)>
Action必须有与之对应的results才有意义,他表示这个流程处理的结果。从results的定义来看,他包含了0到多个result和一个unconditional-result。
unconditional-result
当不需要任何condition判断或者不满足任何condition判断的场景下,我们需要一个unconditional-result,来告诉OSWorkflow流程下一步要做什么,这时候他更像是一个default result.
<!ELEMENT unconditional-result (validators?, pre-functions?, post-functions?)> <!ATTLIST unconditional-result old-status CDATA #REQUIRED status CDATA #IMPLIED step CDATA #IMPLIED owner CDATA #IMPLIED split CDATA #IMPLIED join CDATA #IMPLIED due-date CDATA #IMPLIED id CDATA #IMPLIED display-name CDATA #IMPLIED >
unconditional-result虽然没有自己的conditions,但是他也可以有自己的validators、pre-functions和post-functions
Attributes:
old-status:Action结束后,流程会结束或者流转到其他的step中去,此时当前的流程就成为历史,old-status则表示即将成为历史的流程的status。
status:下一个流程的状态,可选值。
step:下一个step的id
owner:下一个流程的owner
split:下一个流程如果需要有分路,则可选择split属性,他与steps元素下定义的split的id对应
join:如果当前流程作为一个分路,且下一个流程需要做分路合并,则可选择join属性,他与steps元素下定义的join的id对应
due-date:下一个流程的结束时间
conditional-result
conditional-result又称为result,因为他可以有自己的conditions,之所以这样称呼是相对于unconditional-result而言的。我们可以看到他的定义下有自己的validators、pre-functions和post-functions,这些和unconditional-result是一样的,除此之外,他还有自己的conditions定义。
<!ELEMENT result (conditions, validators?, pre-functions?, post-functions?)> <!ATTLIST result old-status CDATA #REQUIRED status CDATA #IMPLIED step CDATA #IMPLIED owner CDATA #IMPLIED split CDATA #IMPLIED join CDATA #IMPLIED due-date CDATA #IMPLIED id CDATA #IMPLIED display-name CDATA #IMPLIED >
attlist部分请参考之前unconditional-result的Attributes介绍,这些都是相同的。
关于splits和joins的使用,请参考附件中workflow_2_8.dtd中的定义。
至此,关于action的部分基本上就介绍完了,我们再来看一个完成的action的定义供大家参考
<action id="1" name="Finish First Draft"> <restrict-to> <conditions type="AND"> <condition type="beanshell"> <arg name="script">true</arg> </condition> <condition type="class"> <arg name="class.name">com.opensymphony.workflow.util.StatusCondition</arg> <arg name="status">Underway</arg> </condition> <condition type="class"> <arg name="class.name">com.opensymphony.workflow.util.AllowOwnerOnlyCondition</arg> </condition> </conditions> </restrict-to> <validators> <validator type="class"> <arg name="class.name">com.opensymphony.workflow.util.jndi.JNDIValidator</arg> <arg name="jndi.location">java:comp/env/MyValidator</arg> </validator> </validators> <pre-functions> <function type="beanshell"> <arg name="script"> String caller = context.getCaller(); propertySet.setString("caller", caller); boolean test = true; String yuck = null; String blah = "987654321"; System.out.println("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$"); </arg> </function> </pre-functions> <results> <result old-status="Finished" split="1"> <conditions type="AND"> <condition type="beanshell"> <arg name="script"> propertySet.getString("caller").equals("test") </arg> </condition> </conditions> <post-functions> <function type="beanshell"> <arg name="script"> System.out.println("11111111111111"); System.out.println("11111111111111"); System.out.println("11111111111111"); System.out.println("11111111111111"); System.out.println("11111111111111"); System.out.println("11111111111111"); System.out.println("11111111111111"); </arg> </function> </post-functions> </result> <unconditional-result old-status="Finished" split="2"/> </results> <post-functions> <function type="beanshell"> <arg name="script"> System.out.println("22222222222222"); System.out.println("22222222222222"); System.out.println("22222222222222"); System.out.println("22222222222222"); System.out.println("22222222222222"); System.out.println("22222222222222"); System.out.println("22222222222222"); System.out.println("22222222222222"); System.out.println("22222222222222"); </arg> </function> </post-functions> </action>
更高层次上的actions
除了之前介绍的action之外,还有一些更高层次上的actions,他们是initial-actions、global-actions和common-actions。
initial-actions
作为最早执行的action,他和普通的action没有什么不同。他是在流程initialize的时候被执行的。
Workflow wf = new BasicWorkflow("test"); long id = wf.initialize("example", 100, null);
wf.initialize方法的第二个参数则为我们定义好的initial-actions下的action id,如果这个id不存在,则会抛出InvalidActionException异常。
global-actions
A list of global actions that can be excuted on any step.
他会隐式的被每一个step调用。
common-actions
他与global-actions不同,他需要显示的调用才会被执行。
A common (shared) action reference that references an action defined in the 'common-actions' element
<common-action id="111" />
文中有一些element的定义并没有一一列出,请参考workflow_2_8.dtd(附件)
未完待续……
相关推荐
"OSWorkflow——请假审批系统(代码全,数据库mysql)" 指的是一个基于OSWorkflow工作流引擎实现的请假审批系统,该系统完整地提供了代码和数据库脚本,且数据库部分使用MySQL作为后台存储。 **描述解析:** 虽然描述...
OSWorkflow,全称OpenSymphony Workflow,是由OpenSymphony Group开发的一个轻量级工作流引擎。它的设计目标是提供一个可扩展且易于使用的平台,用于实现业务流程的建模和执行。OSWorkflow的核心特性包括: 1. **...
工作流(Workflow)是自动化业务过程的模型,它定义了任务如何在参与者之间传递,以及在什么条件下任务的执行方式。OSWorkflow(OpenSymphony Workflow)是一个开源的工作流引擎,它提供了一种灵活的方式来设计、...
OSWorkflow
- **lib**: 依赖库目录,包含了OSWorkflow运行所需的第三方库。 ### 4. 开发实践 为了利用OSWorkflow开发自己的工作流程应用,你需要: 1. **配置数据库**: 根据`osworkflow数据库配置.txt`调整数据库配置,并...
4. 第三方教程:网上有许多关于OSWorkFlow的教程和博客文章,深入讲解各个功能和最佳实践。 总的来说,OSWorkFlow为Java开发者提供了一个强大且易用的工作流解决方案,能够有效地提升企业的业务流程管理水平。通过...
OsWorkflow,全称为OpenSymphony Workflow,是由OpenSymphony团队开发的。它支持复杂的流程定义,包括分支、循环、条件判断等,并允许在运行时动态修改流程。这个工作流实例是作者基于OsWorkflow实现的,已经过测试...
<action id="100" name="Start Workflow"> </action> ... </workflow> ``` - `initial-actions`标签定义了工作流的初始动作,`action`标签表示一个动作,`results`标签则定义了动作的结果流向。 5. ...
1. **流程定义(Workflow Definition)**:osWorkflow 中的流程定义是通过 XML 文件来创建的,它描述了工作流的各个步骤、转移条件、参与者等信息。 2. **状态(State)**:每个任务在流程中都有一个特定的状态,如...
OSWorkflow(Open Source Workflow)是一个开源的工作流管理系统,它允许开发者在Java应用程序中实现复杂的业务流程。以下是对该压缩包中可能包含的内容的详细解释: 1. **OSWorkflow介绍**:OSWorkflow提供了一个...
Workflow wf = (Workflow)cxt.getBean("workflow"); 用osworkflow自带的designer把example重新生成一下图片和example.lyt.,然后把example.lyt.修改为example.lyt.xml,把这个文也给换了example.lyt.xml,然后替换原...
**工作流**(workflow)是业务自动化的重要组成部分,它定义了任务如何在不同参与者之间流转,以及这些任务如何相互影响。osworkflow 的设计基于事件驱动模型,通过状态机的概念来表示流程的状态转换,使得流程可以...
OSWorkflow(Open Source Workflow)是一个开源的工作流引擎,它允许开发者在应用程序中实现复杂的业务流程管理。在OA(Office Automation)系统中,工作流引擎扮演着核心角色,它负责处理审批流程、任务分配等业务...
OSWorkflow,全称为OpenSymphony Workflow,是一款轻量级、高度灵活的开源工作流引擎,专为满足各类组织和企业的工作流程管理需求而设计。它提供了丰富的API和配置选项,使得开发者可以轻松地将工作流集成到自己的...
1. **配置**:在项目中引入 Osworkflow 的依赖库,然后配置相关的bean或者服务,如WorkflowService,以初始化工作流引擎。 2. **流程定义加载**:将XML流程定义文件加载到引擎中,这样引擎就能理解和执行定义的流程...
- **参与者与角色**:定义流程中的执行者,可以是单个用户或一组用户(角色)。 3. **流程设计与配置** OSWorkflow提供了XML格式的流程定义文件,允许通过编辑XML来设计复杂的流程图。用户可以通过添加、删除、...
OsWorkflow 是一个基于Java的工作流引擎,主要用于设计和执行复杂的业务流程。这个项目是一个请假申请的工作流示例,其中流程的定义完全存储在XML文件中,这样可以方便地进行流程的配置和更改,无需修改源代码。对于...