update:这个例子是不当的,更合适的例子请自己上javaeye上搜索个帖子。源码俺早就丢了,请不要再发邮件给我,谢谢。  
    osworkflow扩展非常容易,跟我们的应用结合起来使用也很容易。假设一个请假流程:员工请假,需要经过部门经理和人力资源部经理两人共同审批,只有当两人都许可时才通过,任一人驳回就失效,也就是一个and split和and Join流程,并且我们附加一个要求,当发送请假请求、许可和驳回这几个操作时都将发送一条消息给相应的用户。
    流程定义文件如下:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE workflow PUBLIC "-//OpenSymphony Group//DTD OSWorkflow 2.7//EN" 
"http://www.opensymphony.com/osworkflow/workflow_2_7.dtd">
<workflow>
    <initial-actions>
        <action id="0" name="开始">
            <pre-functions>
                <function type="class">
                    <arg name="class.name">
                        com.opensymphony.workflow.util.Caller
                    </arg>
                </function>
            </pre-functions>
            <results>
                <unconditional-result old-status="Finished"
                    status="Underway" step="1" owner="${caller}" />
            </results>
        </action>
    </initial-actions>

<steps>
        <step id="1" name="填假单">
            <external-permissions>
                <permission name="permA">
                    <restrict-to>
                        <conditions type="AND">
                            <condition type="class"><!--流程处于Underway状态(流程已经启动)-->
                                <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>
                </permission>
            </external-permissions>
            <actions>
                <action id="1" name="送出">
                    <restrict-to>
                        <conditions type="AND">
                            <condition type="class"><!--流程处于Underway状态(流程已经启动)-->
                                <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>
                    <pre-functions>
                        <function type="class">
                            <arg name="class.name">
                                com.opensymphony.workflow.util.Caller
                            </arg>
                        </function>

</pre-functions>
                    <results>
                        <unconditional-result old-status="Finished"
                            split="1" status="Queued">
                            <post-functions>
                                <function type="class">
                                    <arg name="class.name">
                                        net.rubyeye.leavesys.service.workflow.SendRemindInfFunction
                                    </arg>
                                    <arg name="groupName">
                                        AND (GROUPNAME='dept_manager' or
                                        GROUPNAME='comp_manager')
                                    </arg>
                                    <arg name="content">
                                        you have leavemsg to
                                        check!please check it!
                                    </arg>
                                </function>
                            </post-functions>
                        </unconditional-result>
                    </results>
                </action>
            </actions>
        </step>
        <step id="2" name="部门经理批假单">
            <actions>
                <action id="2" name="准许">
                    <restrict-to>
                        <conditions>
                            <condition type="class">
                                <arg name="class.name">
                                    com.opensymphony.workflow.util.OSUserGroupCondition
                                </arg>
                                <arg name="group">dept_manager</arg>
                            </condition>
                        </conditions>
                    </restrict-to>
                    <pre-functions>
                        <function type="class">
                            <arg name="class.name">
                                com.opensymphony.workflow.util.Caller
                            </arg>
                        </function>
                        <function type="beanshell">
                            <arg name="script">
                                propertySet.setString("action1",
                                "success");
                            </arg>
                        </function>
                    </pre-functions>
                    <results>
                        <unconditional-result old-status="Finished"
                            status="Queued" join="1" owner="${caller}" />
                    </results>
                </action>

<action id="3" name="驳回">
                    <restrict-to>
                        <conditions>
                            <condition type="class">
                                <arg name="class.name">
                                    com.opensymphony.workflow.util.OSUserGroupCondition
                                </arg>
                                <arg name="group">dept_manager</arg>
                            </condition>
                        </conditions>
                    </restrict-to>
                    <pre-functions>
                        <function type="class">
                            <arg name="class.name">
                                com.opensymphony.workflow.util.Caller
                            </arg>
                        </function>
                        <function type="beanshell">
                            <arg name="script">
                                propertySet.setString("action1",
                                "fail");
                            </arg>
                        </function>
                    </pre-functions>
                    <results>
                        <unconditional-result old-status="Finished"
                            status="Queued" join="2" owner="${caller}" />
                    </results>
                </action>
            </actions>
        </step>

<step id="3" name="公司经理批假单">
            <actions>
                <action id="4" name="准许">
                    <restrict-to>
                        <conditions>
                            <condition type="class">
                                <arg name="class.name">
                                    com.opensymphony.workflow.util.OSUserGroupCondition
                                </arg>
                                <arg name="group">comp_manager</arg>
                            </condition>
                        </conditions>
                    </restrict-to>
                    <pre-functions>
                        <function type="class">
                            <arg name="class.name">
                                com.opensymphony.workflow.util.Caller
                            </arg>
                        </function>
                        <function type="beanshell">
                            <arg name="script">
                                propertySet.setString("action2",
                                "success");
                            </arg>
                        </function>
                    </pre-functions>
                    <results>
                        <unconditional-result old-status="Finished"
                            status="Queued" join="1" owner="${caller}" />
                    </results>
                </action>

<action id="5" name="驳回">
                    <restrict-to>
                        <conditions>
                            <condition type="class">
                                <arg name="class.name">
                                    com.opensymphony.workflow.util.OSUserGroupCondition
                                </arg>
                                <arg name="group">dept_manager</arg>
                            </condition>
                        </conditions>
                    </restrict-to>
                    <pre-functions>
                        <function type="class">
                            <arg name="class.name">
                                com.opensymphony.workflow.util.Caller
                            </arg>
                        </function>
                        <function type="beanshell">
                            <arg name="script">
                                propertySet.setString("action2",
                                "fail");
                            </arg>
                        </function>
                    </pre-functions>
                    <results>
                        <unconditional-result old-status="Finished"
                            status="Queued" join="2" owner="${caller}" />
                    </results>
                </action>
            </actions>
        </step>

<step id="4" name="停止" />
    </steps>
    <splits>
        <split id="1">
            <unconditional-result old-status="Finished" status="Queued"
                step="2" />
            <unconditional-result old-status="Finished" status="Queued"
                step="3" />
        </split>
    </splits>
    <joins>
        <join id="1">
            <conditions type="AND">
                <condition type="beanshell">
                    <arg name="script">
                        <![CDATA[
     "Finished".equals(jn.getStep(2).getStatus()) &&
        "Finished".equals(jn.getStep(3).getStatus())&&"success".equals(propertySet.getString("action1"))&&
        "success".equals(propertySet.getString("action2"))
      ]]>
                    </arg>
                </condition>
            </conditions>
            <unconditional-result old-status="Finished" status="Queued"
                step="4"/>
        </join>

<join id="2">
            <conditions type="OR">
                <condition type="beanshell">
                    <arg name="script">
                        <![CDATA[
     "Finished".equals(jn.getStep(2).getStatus()) &&"fail".equals(propertySet.getString("action1"))
      ]]>
                    </arg>
                </condition>
                <condition type="beanshell">
                    <arg name="script">
                        <![CDATA[
    
        "Finished".equals(jn.getStep(3).getStatus())&&"fail".equals(propertySet.getString("action2"))
      ]]>
                    </arg>
                </condition>
            </conditions>
            <unconditional-result old-status="Finished" step="4"
                status="Queued">
                <post-functions>
                    <function type="class">
                        <arg name="class.name">
                            net.rubyeye.leavesys.service.workflow.SendRemindInfFunction
                        </arg>
                        <arg name="groupName">
                            AND GROUPNAME='employee' 
                        </arg>
                        <arg name="content">
                            you leveamsg is fail!!!
                        </arg>
                    </function>
                </post-functions>
            </unconditional-result>
        </join>
    </joins>
</workflow>

请注意,我们在许可或者通过的时候propertySet.setString("action2",......),propertySet.setString("action3",......),然后在join点判断,如果两个都是success,流程结束;如果一个是fail,就发送一个消息给员工。

发送消息的function像这样:

package net.rubyeye.leavesys.service.workflow;

import java.sql.SQLException;
import java.util.Map;

import net.rubyeye.leavesys.domain.RemindInf;
import net.rubyeye.leavesys.service.ManagerFactory;

import com.opensymphony.module.propertyset.PropertySet;
import com.opensymphony.workflow.FunctionProvider;
import com.opensymphony.workflow.WorkflowException;

public class SendRemindInfFunction implements FunctionProvider {

public void execute(Map transientVars, Map args, PropertySet ps)
            throws WorkflowException {
        String groupName = (String) args.get("groupName");
        String content = (String) args.get("content");
        RemindInf remindInf = new RemindInf();
        remindInf.setContent(content);
        try {
            ManagerFactory.getRemindService().addRemindInfByGroupName(
                    groupName, remindInf);
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

}

文章转自庄周梦蝶  ,原文发布时间5.17

得到两个参数groupName和content(消息内容),调用业务对象发送消息。

完整代码下载在《LeaveSystem》

代码用到了自己过去写的一个MVC框架和持久层,对此有兴趣的参考这三篇文章:
《设计自己的MVC框架》
《设计模式之事务处理》
《使用Annotation设计持久层》

如果仅仅是想了解osworkflow的应用,建议您跑下流程,读读相关几个业务类(LeaveServiceImpl.java,SendRemindInfFunction.java,service包下)即可。解压缩后的文件可以直接导入myeclipse工程,部署在tomcat下,数据库用的是oracle。跑起来以后可以用3个用户登录,test是雇员组,dennis是部门经理组,jordan是公司经理,都不需要密码。写的比较简单,只是实验性质,见谅。

我认为使用osworkflow,只要了解了它的表结构和主要原理,根据你的业务需要结合几张主要表(os_wfentry,os_currentstep,os_historystep等)合理设计数据库和业务流程,可以省去过去为每个业务流程对象创建的一大堆flag(标志,目前的流程状态)的累赘,充分利用工作流的威力。比如为部门经理和人力资源部经理显示不同的需要审批的假单列表,只要结合os_historystep表进行联合查询,部门经理的应该是执行了未执行acion2,step在3的;而人力资源部经理得到的同样是step在3,action未执行3的。

手痒痒,很想把去年为一家公司写的绩效考核系统改写一下,当时设计的一个contract对象拥有7,8个flag来标志合约状态(直接上级审核,人力资源评价,KPI评价等),搞的非常混乱,而且流程写死在代码里,如果以后要改变考核流程,只有重新写过一套。不过那家公司是国有企业,每年的固定的预算费用一定要花掉,反正大家一起赚国家的钱嘛。

用osworkflow写一个请假例子相关推荐

  1. 写一个饿汉单例模式的例子_你写的单例模式,能防止反序列化和反射吗?

    推荐学习 "23种设计模式知识要点"都没读通过,还有脸说摸不清搞不懂? 玩转JAVA筑基之Netty.并发编程与设计模式,打好基础备战春招 前言 说起单例模式,相信大家都不会陌生. ...

  2. 如何写一个简单java接口的例子(内容详细,适合初学者)

    这里说一个简单的java接口的小例子(一个接口类,两个实现类) 先新建一个动态web工程: 我的项目目录是这样子的(接口写完之后目录) 先在test0609_test1包下new 一个interfac ...

  3. 【微博SDK调用逻辑】微博SDK的调用逻辑,最好自己还是写一个例子,试一下!!!...

    逻辑是这样的,谢谢给我讲东西的开发哥哥,嘻嘻~~~ 1.点击微博登录,SDK会打开微博客户端,然后点击登陆(如果已经登录了会出现一个当前app跟微博交互的图片界面,然后提示"正在获取授权信息 ...

  4. python 请假审批系统_菜鸟也要懂点设计模式|用Python设计一个请假模式

    很多同学学Python一段时间了,但是总感觉自己的写代码不好维护,或者时间长了一旦增加需求或者需要扩展功能,发现自己写的代码就是一团糟!尽管也代码不断的重构了,好像也遵循了PEP8的风格,为啥代码量一 ...

  5. 一个请假单流程的实现(struts2.1.8+spring2.5+hibernate3集成jbpm4.3

    先说明这个只是一个例子而已,简单的介绍了一些写法,你真的理解了以后完全可以写出比这个更好的代码来. 网上随便找了个请假的流程图,在此先谢谢提供图片的人: 使用jbpm工具画出流程图,中文好像是乱码,所 ...

  6. 大神教你如何给脚本写一个守护进程

    在我们日常运维中,写脚本监控一个进程是比较常见的操作,比如我要监控mysql进程是否消失,如果消失就重启mysql. 用下面这段代码就可以实现: #!/bin/shDate=` date '+%c'` ...

  7. php日历如何写,如何写一个好看的实用的日历

    本文发布在我的博客如何写一个日历组件 许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者.众所周知,虽然javascript中关于时间的API有不少,我们可以通过方法单独 ...

  8. 正则表达式限定长度_自己写一个通用的邮箱正则表达式

    今天把正则又复习了一遍,为了加深记忆,自己写一个邮箱的正则表达式 咱们先来看几个合法的邮箱地址 hd33322@nat123.com maksim.kim.82@d-link.ua vova_laza ...

  9. SAP MM采购定价过程的一个简单例子

    SAP MM采购定价过程的一个简单例子 本文以一个简单的例子阐述了SAP MM模块中采购定价的基本原理.本例中,假定采购订单里输入的是含税采购价,然后系统自动计算出物料最终的采购价格(含税价-税额=采 ...

最新文章

  1. mysql字符串相加函数concat()
  2. hashMap死循环
  3. 【Android 插件化】Hook 插件化框架 ( Hook 实现思路 | Hook 按钮点击事件 )
  4. 在Windows操作系统下,由操作系统分配的内存就叫做堆
  5. 3.3.1网络原理数据链路层之差错控制(检错编码和纠错编码)-(奇偶校验码、CRC循环冗余码、海明码)
  6. c语言怎么在win7上运行,C语言做的中国象棋,分享,问怎么在WIN7下运行
  7. java学习(117):list迭代器和包含方法
  8. 分组数据方差公式_连续变量假设检验 之 单因素方差检验
  9. ajax跨域,json,jsonp
  10. Canvas递归画一棵树
  11. 神剑轩辕java,上古十大神剑有哪些 有一把居然是专门用来弑君杀父的
  12. 【java】JavaFX从零开始实现拼图小游戏
  13. webpack-dev-server的代理(proxy)
  14. 小白终是踏上了这条不归路----小文的mysql学习笔记(6)----连接查询-----等值连接、非等值连接、自链接、外连接、交叉连接
  15. 485、CAN、单总线、SPI、I2C的概念,特点,协议,使用方法及通信方式,还有它们之间的区别
  16. 楼层部分的计算机术语大全,计算机术语(大全)
  17. Collection的概念
  18. 什么是边缘节点服务?
  19. 电脑版微信防撤回怎么设置?
  20. 破解mifare Classic(M1)非接触式射频IC卡--Mifare crack Hack 笔记一

热门文章

  1. 【深度学习之美02】深度学习的方法论是什么?
  2. 数学物理方法·基础⑤复数序列
  3. 怎么创建mysql文件_怎样创建数据库?
  4. 浅谈Wireshark的使用
  5. 微信小程序导入demon
  6. 【设计模式】工厂设计模式
  7. Elasticsearch 实战(二、简单检索)
  8. Hive的安装与配置——第1关:Hive的安装与配置
  9. 【b站求职笔记】行路院-王贺 2020年12月笔记
  10. 谈下微软企业生产力大学的Sharepoint Service 2010 的3天培训