山寨版工作流:groovy控制的责任链


有点标题党的嫌疑
本文不涉及工作流中的环节(step)、条件(conditions)、循环(loops)、分支(spilts)、合并(joins)、角色(roles)等等。


不涉及工作流。


呵呵,说白了, 就是在责任链中加入脚本控制。

扩展自apache common chain:
http://commons.apache.org/chain/

比如有如下chain:描述我工作日的生活:早餐,去公司,工作,午餐, 工作, 回家

<catalog>
    <chain name="my working day life">
        <command id="breakfast" className="co.command.BreakfastCommand" />
        <command id="go-to-company" className="co.command.GotoCompanyCommand" />
    <command id="work" className="co.command.WorkCommand" />
        <command id="lunch" className="co.command.LunchCommand" />
    <command id="work" className="co.command.WorkCommand" />
        <command id="go-home" className="co.command.GohomeCommand" />
    </chain>
</catalog>

 


如果是假期, 那我的生活或许是这样的: 早餐,出去high, 回家

<catalog>
    <chain name="my holiday life">
        <command id="breakfast" className="co.command.BreakfastCommand" />
        <command id="play" className="co.command.PlayCommand" />
        <command id="go-home" className="co.command.GohomeCommand" />
    </chain>
</catalog>
 


好了, 我现在有一个需求, 需要在chain的配置中, 加入脚本功能, 以控制command是否应该执行。
如果有了这个功能, 以上的两个chain就可以合并为一个:

<catalog>
    <chain name="my working day life">
        <command id="breakfast" className="co.command.BreakfastCommand" />
    <script expression="context.isHoliday()">
        <command id="play" className="co.command.PlayCommand" />
    </script>
    <script expression="!context.isHoliday()">
        <command id="go-to-company" className="co.command.GotoCompanyCommand" />
        <command id="work" className="co.command.WorkCommand" />
        <command id="lunch" className="co.command.LunchCommand" />
        <command id="work" className="co.command.WorkCommand" />
    </script>
        <command id="go-home" className="co.command.GohomeCommand" />
    </chain>
</catalog>
 


有了流程控制, 实现了command的流转。

具体如何实现的呢?
我为没一个command增加了一个expression属性(即脚本内容):
在<script>...</script>节点包含的每个command中,有相同的expression属性.

比如:

    <script expression="!context.isHoliday()">
        <command id="go-to-company" className="co.command.GotoCompanyCommand" />
        <command id="work" className="co.command.WorkCommand" />
        <command id="lunch" className="co.command.LunchCommand" />
        <command id="work" className="co.command.WorkCommand" />
    </script>
 


这是个command,每个command的expression值都为:"!context.isHoliday()"


来一个command的基类:
在运行商业逻辑(action)之前, 运行一下expression, 如果为true,就执行action, 否则, 继续下一个command:

public abstract class BaseCommand implements org.apache.commons.chain.Command
{
    private String expression;
   
    private ScriptEngine scriptEngine;
   
    public final boolean execute(Context context) throws Exception
    {
        if(this.isRunable(context))
        {
            return this.action(context);
        }
        return false;
    }

    private boolean isRunable(Context context)
    {
        if(!StringUtils.hasText(this.expression))
            return true;
        return ((Boolean)scriptEngine.run(this.expression, context)).booleanValue();
    }

    public void setScriptEngine(ScriptEngine scriptEngine)
    {
        this.scriptEngine = scriptEngine;
   
    }

    public String getExpression()
    {
        return expression;
    }

    public void setExpression(String expression)
    {
        this.expression = expression;
    }
   
    public abstract boolean action(Context context) throws Exception;

}
 



ScriptEngine是一个script 引擎接口:

public interface ScriptEngine
{
    public Object run(String express, Object context);
}
 



给一个groovy的实现:

public class GroovyExpressionEngine implements ScriptEngine
{
    public Object run(String express, Object context)
    {
       ClassLoader cl = GroovyExpressionEngine.class.getClassLoader();
       GroovyClassLoader groovyCl = new GroovyClassLoader(cl);
       Class groovyClass = groovyCl.parseClass(express);
       Script sc;
        try
        {
            sc = (Script)groovyClass.newInstance();
        }
        catch (Exception e)
        {
            throw new RuntimeException(e.getMessage(), e);
        }

       Binding binding = new Binding();
       binding.setVariable("context", context);
       sc.setBinding(binding);
       return sc.run(); 
     }
}

 

Game over!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值