Java表达式语言方案探究
【引言】
Java统一表达式语言是一种特殊用途的编程语言,主要用于Java Web应用中,用于将表达式嵌入到网页中。Java规范的编写者和Java Web层技术的专家小组研究了统一表达式语言,该语言首先被包含在JSP 2.1规范(JSR-245)中,后来在Java EE 7的一部分JSR-341中自行指定。
经过多年的发展,表达式语言已经发展到包含了更多的高级功能,它被纳入到JSP 2.0规范中。对于那些对Java语言的核心知识很少或几乎不懂的Web内容设计者来说,脚本语言的出现使其变得更加容易。这种脚本语言使JSP成为了真正意义上的脚本语言。在EL之前,JSP由一些特殊的标记组成,如scriptlets、expressions等,在这些标记中,Java代码被明确地写在其中。有了EL之后,Web内容设计者只需要知道如何正确调用核心Java方法就可以了。
EL在语法上和语义上都与JavaScript表达式相似。
l 没有显式类型转换
l 类型转换通常是隐含地进行的
l 双引号和单引号等价
l object.property与object['property'] 具有相同的含义
EL让程序员从一些具体的特殊性技术细节中解放出来。比如object.property的调用就是提取object对象中的property值,内部实现的方式很多,可能是object.get("property")或
object.getProperty("property")或object.getProperty()等。至于是哪一种,程序员不需要关心了。
3.0版本的表达式语言在JSR-341中开发了独立于JSP和JSF规范的标准。增加了一些新的功能,最明显的是Java 8的流和lambda表达式的EL等价物。
【Java Expression Language (JEXL)】
JEXL是一个旨在促进在用Java编写的应用程序和框架中实现动态和脚本功能的程序库。
JEXL程序库实现了基于JSTL表达式语言的一些扩展,支持shell-script或ECMAScript中的大部分实现。
它的目标是为技术操作人员或技术顾问提供有用的脚本功能为一些企业平台服务。
该库提供了短小精悍的API---核心功能只包含3个类和10个方法,
可以在各种条件下使用:
l 脚本功能。
n 你的应用程序可以让(高级)用户评估或定义一些简单的表达式,比如计算公式。
l 模块或组件配置。
n 你的应用程序有最终用户模块需要的配置文件,这些配置文件可以结合变量和表达式使用。
n 当依赖注入功能无法使用时。
l 接口和实现的松散耦合,或者说是填鸭式。
n 你有一些可选择的类,而你的代码不能将其作为编译依赖类。
n 你必须集成和调用 "遗留 "的代码,或者使用你不想强烈依赖的组件。
l 简单的模板功能。
n 你的应用有基本的模板需求,而JSP或Velocity会显得矫枉过正或不方便部署。
【JSTL表达式语言的扩展】
虽然JEXL类似于JSTL中定义的表达式语言,但它在语法上有几个方面的改进。
n 支持调用任何可访问的方法
n 支持设置/获取任何可访问的公共字段。
n 一个通用的new()方法,允许实例化对象。
n 一个通用的size()方法,可以用于:
u String---返回长度。
u Map---返回键值的个数。
u List --- 返回元素个数。
n 一个通用的empty()方法,可用于集合和字符串。
n 支持三元运算符 'a ? b : c' - 以及它的 GNU-C / "Elvis" 变体 'a ?: c'。
n 支持类似于 Perl 的 regex 匹配操作符 '=~' 和 '!~' 。
n 支持 CSS3 启发的 'startWith' 和 'endWith' 运算符 '=^' 和 '=$' 。
n 支持用户定义的函数。
n 其他事项: '+'已被重载,可作为字符串连接运算符使用。
【使用案例】
/// 创建或检索一个引擎
JexlEngine jexl = new JexlBuilder().create();
///创建一个表达式
String jexlExp = "foo.innerFoo.bar()";
JexlExpression e = jexl.createExpression(jexlExp);
///创建一个上下文并添加数据
JexlContext jc = new MapContext();
jc.set("foo", new Foo());
// 现在评估表达式,得到结果
Object o = e.evaluation(jc);
【License】
Apache License 2.0
【最新版本】
3.1于 2017年4月14日
【官方网站】
https://commons.apache.org/proper/commons-jexl/
【Java Unified Expression Language(JUEL)】
JUEL是统一表达式语言(EL)的开源实现。 作为JSP 2.1标准(JSR-245)的一部分,它被业界认为是稳定和功能完整的程序库。JUEL也适用于非JSP应用程序。
【使用案例】
工厂类和上下文对象
///ExpressionFactory的实现是de.dysseus.el.ExpressionFactoryImpl
ExpressionFactory factory = new de.dysseus.el.ExpressionFactoryImpl();
///包de.odysseus.el.util提供了一个随时可用的ELContext子类
de.dysseus.el.util.SimpleContext context = new de.dysseus.el.util.SimpleContext();
函数和变量
///将函数math:max(int, int)映射到java.lang.Math.max(int, int)
context.setFunction("math", "max", Math.class.getMethod("max", int.class, int.class, int.class));
///将变量foo映射为0
context.setVariable("foo", factory.createValueExpression(0, int.class));
解析和评估
///解析我们的表达式
ValueExpression e = factory.createValueExpression(context, "${math:max(foo,bar)}", int.class);
///将顶层属性 "bar "的值设置为1
factory.createValueExpression(context, "${bar}", int.class).setValue(context, 1);
///为我们的表达式获取值
System.out.println(e.getValue(context)); //--> 1
【License】
Apache License 2.0
【最新版本】
2.2.7于2014年2月6日
【官方网站】
【Apache Commons EL】
Apache Commons EL 是JSP 2.0 EL 解释器程序库。 JSP标准标签库(JSTL),1.0版引入了表达式语言(EL)的概念,其主要目的是为页面作者提供一种不需要使用脚本的情况下访问和操作应用程序数据的简便方法。
JSP 2.0采用了JSTL的EL规范,并扩大了其范围。EL表达式不再局限于JSTL动作属性,而是可以在任何声明接受运行时表达式的标准中或自定义动作属性中使用。此外,EL表达式现在也可以直接在任何动作之外的模板文本中使用。
JSP 2.0还为EL规范增加了一个重要的功能:EL函数,允许页面作者从EL表达式中调用Java类中的静态方法。此外,JSP 2.0允许通过一组标准接口和抽象类对EL评价器进行程序化访问和自定义。
【License】
Apache License 2.0
【最新版本】
1.0.1-SNAPSHOT于2013年2月26日
【官方网站】
https://commons.apache.org/dormant/commons-el/
【Object-Graph Navigation Language (OGNL)】
Object-Graph Navigation Language (OGNL)是Java的一种开源表达式语言(EL)程序库,它使用的表达式比Java语言所支持的全部表达式更简单,由于它允许获取和设置属性(通过定义的setProperty和getProperty方法),并执行Java类的方法。它还允许对数组进行更简单的操作。
【License】
Apache License 2.0
【最新版本】
3.0.8于2013年9月24日
【官方网站】
http://commons.apache.org/ognl/
【MVFLEX Expression Language (MVEL)】
MVFLEX表达式语言(MVEL)是在Java平台上的一种混合的动态/静态类型化的、可嵌入的表达式语言程序库。该项目最初是作为一个应用框架的实用程序语言开始的,现在完全独立开发。
MVEL通常用于通过XML文件或注释等配置向最终用户和程序员展示基本逻辑。它也可以用来解析简单的JavaBean表达式。
运行时允许MVEL表达式通过解释式执行,或者通过支持运行时字节码生成的预编译过程来消除开销。
由于MVEL的目的是为了增强基于Java的软件,所以它直接从Java编程语言中借用了大部分的语法,但有一些小的差异和额外的功能。例如:作为MVEL的类型化模型的一个副作用,MVEL将类和方法引用作为正则变量处理,因此可以同时使用类和函数应用(但仅限于静态方法)。
millis = System.currentTimeMillis;
///获取millis
time = millis()。
MVEL还允许用类似于Lisp的语法来表示集合的褶皱(或投影)。
namesOfParents = (parent.name in (children in employees)));
【使用案例】
你好世界的例子
System.out.println("Hello, world!");
快速排序示例
import java.util.*;
// the main quicksort algorithm
def quicksort(list) {
if (list.size() <= 1) {
list;
}
else {
pivot = list[0];
concat(quicksort(($ in list if $ < pivot)), pivot, quicksort(($ in list if $ > pivot)));
}
}
// define method to concatenate lists.
def concat(list1, pivot, list2) {
concatList = new ArrayList(list1);
concatList.add(pivot);
concatList.addAll(list2);
concatList;
}
// create a list to sort
list = [5,2,4,1,18,10,15,1,0];
// sort it!
quicksort(list);
【License】
Apache License 2.0
【最新版本】
2.3.0于2016年6月15日
【官方网站】
【Spring Expression Language (SpEL)】
Spring表达式语言(简称 "SpEL")是一种强大的表达式语言,支持在运行时查询和操作对象图。该语言的语法类似于Unified EL,但提供了额外的功能,最主要的是方法调用和基本的字符串模板化功能。
相比其他几种Java表达式语言,如OGNL、MVEL和JBoss EL等,Spring表达式语言的创建是为了给Spring社区提供一种单一的表达式语言,它可以在Spring组合中的所有产品中使用。它的语言功能是由Spring组合中的项目需求驱动的,包括在Spring Tools for Eclipse中支持代码完成的工具需求。
虽然SpEL作为Spring组合中表达式评估的基础,但它与Spring并不直接挂钩,可以独立使用。
【使用案例】
字符串解析示例
ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression("'Hello World'");
String message = (String) exp.getValue();
字符串链接示例
ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression("'Hello World'.concat('!')");
String message = (String) exp.getValue();
属性调用示例
ExpressionParser parser = new SpelExpressionParser();
// invokes 'getBytes()'
Expression exp = parser.parseExpression("'Hello World'.bytes");
byte[] bytes = (byte[]) exp.getValue();
方法调用示例
// string literal, evaluates to "bc"
String bc = parser.parseExpression("'abc'.substring(1, 3)").getValue(String.class);
// evaluates to true
boolean isMember = parser.parseExpression("isMember('Mihajlo Pupin')").getValue(societyContext, Boolean.class);
【License】
Apache License 2.0
【最新版本】
5.2.5 于2020年3月24日
【官方网站】
https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#expressions
【小结】
在本文中我们一共讨论了如下的表达式语言程序库:JXEL,JUEL, Apache Commons EL,OGNL,MVEL, SPEL。每个程序库都有各自的特点,在选取程序库的时候,我们要结合具体的业务应用场景,首先要确定哪些程序库是可以满足业务需求,在此基础上,我们要看社区活跃度。从维护活跃度上来看,SPEL是最活跃的,以后可以作为首选项。
- 点赞
- 收藏
- 关注作者
评论(0)