用osworkflow写一个请假例子

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评价等),搞的非常混乱,而且流程写死在代码里,如果以后要改变考核流程,只有重新写过一套。不过那家公司是国有企业,每年的固定的预算费用一定要花掉,反正大家一起赚国家的钱嘛。

时间: 2024-09-17 09:04:11

用osworkflow写一个请假例子的相关文章

java-求一个接口例子, 别人可以调用,各个类或者实现都怎么写

问题描述 求一个接口例子, 别人可以调用,各个类或者实现都怎么写 求一个接口例子, 别人可以调用,各个类或者实现都怎么写,谢谢了 解决方案 http://blog.csdn.net/yu555666/article/details/1515674 解决方案二: http://blog.csdn.net/liujun13579/article/details/7736116 解决方案三: 写的一个简简单单的php数据库调用类和调用例子.

web.config文件自定义配置节的使用方法的一个简单例子

web web.config文件自定义配置节的使用方法的一个简单例子用来演示的程序名为MyApp,Namespace也是MyApp 1.编辑web.config文件 添加以下内容,声明一个Section <configSections>    <section name="AppConfig" type="MyApp.AppConfig, MyApp" /> </configSections>   声明了一个叫AppConfig的

JSP中读文件和写文件的例子

js 读文件的例子***************************************************<%@ page contentType="text/html;charset=gb2312"%><%//变量声明\java.lang.String strFileName; //文件名java.io.File objFile; //文件对象java.io.FileReader objFileReader; //读文件对象char[] chrBuff

socket通信-用vc写一个socket程序 实现两个客户端通过一个服务器的对话

问题描述 用vc写一个socket程序 实现两个客户端通过一个服务器的对话 初学socket 求详细教程,最好有C++源码 感激不尽 解决方案 孙鑫的VC视频教程中就有这样的例子程序,可以参考一下.

写一个触发器,要求达到目标如下:

问题描述 写一个触发器,要求达到目标如下: 1. zk.cm_user_his新增加记录的时候,判断region_code的值,如果是770的,把号码写到zk.temp_test_user_0770的表(没表的话,自己建表) 如果是771的话写到k.temp_test_user_0771,依次类推. 2.zk.cm_user_his是更新记录的操作,也把号码保存到zk.temp_test_user_077x的表. 3.zk.cm_user_his是删除记录的操作,也把号码保存到zk.temp_t

能不能用c帮忙写一个旅游管理的源代码,

问题描述 能不能用c帮忙写一个旅游管理的源代码, 数据描述:旅游景点名称,所在省,特色,交通方式,天数,收费标准程序完成功能:浏览数据,增加数据,修改数据,查询数据(按旅游景点,按天数),退出 解决方案 给你个例子,参考改改吧: #include <stdio.h>#include <stdlib.h>#include <string.h>typedef struct STUDENT{ char id[20]; char name[20]; char major[20]

分布式系统中的RPC请求经常出现乱序的情况 写一个算法来将一个乱序的序列保序输出

分布式系统中的RPC请求经常出现乱序的情况.  写一个算法来将一个乱序的序列保序输出.例如,假设起始序号是1,对于(1, 2, 5, 8, 10, 4, 3, 6, 9, 7)这个序列,输出是:  1  2  3, 4, 5  6  7, 8, 9, 10 上述例子中,3到来的时候会发现4,5已经在了.因此将已经满足顺序的整个序列(3, 4, 5)输出为一行. 要求:  1. 写一个高效的算法完成上述功能,实现要尽可能的健壮.易于维护  2. 为该算法设计并实现单元测试 我的思路是:  假设输入

c#写一个“足球比赛积分的输入、查询数据库”

问题描述 c#写一个"足球比赛积分的输入.查询数据库"?? 解决方案 解决方案二:只是录入和查询吗?那不就是简单的MIS,最多麻烦点在数据库的设计上解决方案三:那你就写呗,技术上有难点.还是其他神马情况?解决方案四:楼主是忘记留邮箱了吧.有问题就具体的问.没人有空发个例子到你邮箱给你参考.解决方案五:可以发到1787022729@qq.com吗?解决方案六:请人么?解决方案七:说得好空泛,请问有没有具体要求?解决方案八:引用2楼lovelj2012的回复: 那你就写呗,技术上有难点.还

asp.net-C# 由于项目特许 全部用sql 直接拼接的 能否写一个过滤器去掉特殊字符

问题描述 C# 由于项目特许 全部用sql 直接拼接的 能否写一个过滤器去掉特殊字符 http://localhost:14220/Login.aspx? EquipType='iPhone&Soft=+zb.s20140213092229565 asp.net 能否写一个过滤器 过滤掉里面传的特殊字符 那样我就不用到每个页面去加 过滤了 解决方案 上面例子哪些要去掉?