JDK1.6开始,Java引入了jsr223,就是可以用一致的形式在JVM上执行一些脚本语言,如js。先来一个简单的例子以对在jvm上运行脚本有个初步的认识。
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
public class TestScript1 {
public static void main(String[] args) throws Exception {
ScriptEngineManager scriptEngineManager = new ScriptEngineManager();
ScriptEngine scriptEngine = scriptEngineManager.getEngineByName("javascript");
String exp = "2*6-(6+5)";
Object result = scriptEngine.eval(exp);
System.out.println(exp + "=" + result);
}
}
上面的例子是用来计算2*6-(6+5)这个表达式的值,使用了js引擎来计算,非常方便。另外,在工作流中,通常使用脚本引擎来计算一个节点到另一个节点之间的条件是否通过。如果不用脚本/表达式引擎,那就需要自己解析脚本了,若是算术算式,通常是构造成一个逆波兰式,这不是本文重点,就不展开了。
上面计算的表达式是“常量”,还可以计算带有变量的,如下:
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
public class TestScript3 {
public static void main(String[] args) throws Exception {
ScriptEngineManager scriptEngineManager = new ScriptEngineManager();
ScriptEngine scriptEngine = scriptEngineManager.getEngineByName("javascript");
String exp = "a+b";
scriptEngine.put("a", 4);
scriptEngine.put("b", 15);
Object result = scriptEngine.eval(exp);
System.out.println(exp + "=" + result);
}
}
那么,一种JVM究竟支持哪些脚本引擎呢?可以通过下面的代码枚举出来。
import java.util.List;
import javax.script.ScriptEngineFactory;
import javax.script.ScriptEngineManager;
public class TestScript2 {
public static void main(String[] args) throws Exception {
ScriptEngineManager scriptEngineManager = new ScriptEngineManager();
List engineFactories = scriptEngineManager.getEngineFactories();
if(engineFactories.size() == 0) {
System.out.println("本JVM尚不支持任何脚本引擎");
return;
}
System.out.println("本JVM支持的脚本引擎有:");
for(ScriptEngineFactory engineFactory : engineFactories) {
System.out.println("引擎名称:" + engineFactory.getEngineName());
System.out.println("\t可被ScriptEngineManager识别的名称:" + engineFactory.getNames());
System.out.println("\t该引擎支持的脚本语言名称:" + engineFactory.getLanguageName());
System.out.println("\t是否线程安全:" + engineFactory.getParameter("THREADING"));
}
}
}
在我的环境中,运行结果如下:
本JVM支持的脚本引擎有:
引擎名称:JEXL Engine
可被ScriptEngineManager识别的名称:[JEXL, Jexl, jexl]
该引擎支持的脚本语言名称:JEXL
是否线程安全:null
引擎名称:Mozilla Rhino
可被ScriptEngineManager识别的名称:
该引擎支持的脚本语言名称:ECMAScript
是否线程安全:MULTITHREADED
各位看官的运行结果未必与我的相同,“是否线程安全”一项的解释在后文有说明。
至此,已经对脚本引擎有了个初步的认识,那么jsr223究竟是个什么东西?说通俗了,就是为各脚本引擎提供了统一的接口、统一的访问模式。在jsr223出现以前,如jdk1.4中,就已经可以直接调用js引擎(可从http://www.mozilla.org/rhino/下载)来运行js脚本了,只不过调用的时候是与js引擎的实现息息相关的,jsr223的引入,调用者与具体脚本引擎解耦了,调用类里,不再需要引入具体引擎相关的类。如果有两个脚本引擎所支持的语言语法相似,还可以直接更换scriptEngineManager.getEngineByName(“javascript”)中的引擎名称,以方便的切换引擎。