用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();
        }
    }

}

得到两个参数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写一个请假例子)