有点标题党的嫌疑
本文不涉及工作流中的环节(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!
本文介绍了一种在责任链模式中引入脚本控制的方法,通过脚本表达式决定链中命令的执行与否,实现了根据不同条件动态调整命令执行流程的功能。
4580

被折叠的 条评论
为什么被折叠?



