上几天和
jindw讨论时,
他提到想在他的一个开源项目重用CommonTemplate(
http://www.commontemplate.org)的EL (Expression Language),
问我是否可以抽取使用,我觉得这是一个很好的想法,
为此重构了一下CommonTemplate,以使EL分离于TL (Template Language),可以单独使用。
因为原始设计就将EL单独设计的,只是为了和TL统一,有些范围未最小化控制,
重构如下:
将Expression的求值过程所依赖Context改成VariableResolver,即:
Object evaluate(Context context);
改成:
Object evaluate(VariableResolver variableResolver);
加入接口VariableResolver:
public interface VariableResolver {
Object lookupVariable(String name) throw VariableException;
}
并让Context继承于VariableResolver,保持指令可以使用原有的expression.evaluate(context)调用表达式求值,
(实际继承关系是Context -> LocalContext -> VariableStorage -> VariableResolver)
这样,单独使用EL时,就不用实现整个Context,只需实现最简单的VariableResolver就行了,
实现上面重构后,单独使用EL的体系为:
org.commontemplate.core.VariableResolver
org.commontemplate.core.Expression
org.commontemplate.cofig.ExpressionConfiguration
org.commontemplate.engine.expression.ExpressionEngine
org.commontemplate.standard.ExpressionSetting
第三方只需要重新实现org.commontemplate.core.VariableResolver,
其它都可以直接使用,如:
// 创建配置,
// 这里用的org.commontemplate.util包内置的IoC配置工具,
// 也可以编程一个个setXXX,或用其它IoC容器创建,
BeanFactory beanFactory = new PropertiesBeanFactory("commontemplate-expression.properties");
ExpressionSetting setting = (ExpressionSetting)beanFactory.createBean(ExpressionSetting.class);
VariableResolver variableResolver = ... //自行实现
// 通过配置创建
ExpressionEngine engine = new ExpressionEngine(setting);
// 解析表达式
String expr = "1 + 1"; // 待求值的表达式
Expression expression = engine.parseExpression("1 + 1");
// 运行求值
Objecct result = expression.evaluate(variableResolver);
System.out.println(expr + " = " + result);
应该重用方式已经非常简单了,
当然可以加几个工具类,把配置再封装一下,
或再提供一个用Map实现的最简单VariableResolver等,
但这些都不是必需的,
另外,是否应该将el相关的放到一个package下,我觉得没必要,
那会影响整个项目的package层级关系,
倒是可以写一个Ant脚本,抽取相关类,打包成commontemplate-el.jar