脚本引擎发现和元数据:为脚本 API 编写的应用程序可能对脚本引擎有特定的要求。一些可能需要特定的脚本语言和/或版本,而另一些可能需要特定的实现引擎和/或版本。脚本引擎是以指定方式打包的,从而可以在运行时被发现,并可以查询属性。Engine 发现机制基于Jar 文件规范中描述的 Service 发现机制。脚本引擎实现类打包在 jar 文件中,这些文件包含一个名为META-INF/services/javax.script.ScriptEngineFactory 的文本资源。此资源必须为打包在 jar 文件中的每个ScriptEngineFactory 包含一个行。ScriptEngineManager 包括getEngineFactories 方法,该方法用于获取所有使用此机制发现的ScriptEngineFactory 实例。ScriptEngineFactory 拥有用于查询关于脚本引擎的属性的方法。
在了解完上面之后,查看下有那些类实现了ScriptEngineFactory , 只有一个NashornScriptEngineFactory。
看了下源码 默认是不支持python的,找了一下使用Jython还是可以解决这个问题的。
根据上面 5.Engine 发现机制基于 Jar 文件规范中描述的 Service 发现机制。脚本引擎实现类打包在 jar 文件中,这些文件包含一个名为 META-INF/services/javax.script.ScriptEngineFactory 的文本资源。
下完包后
还是发现了这个家伙,这样就确定其他所有的脚本引擎都是使用这种方式找到的。
先看下ScriptEngineFactory
看到有个Jdk的,还有一个pyhton的。
下面就开始上代码了
来到PyScriptEngineFactory getNames 中 可以支持使用python 和jython 来获取引擎
public class testPython {
private Invocable invocableEngine = null; // 执行引擎
private Compilable compEngine = null; // 编译引擎
private Map compiledScripts = null; // 编译结果的脚本
@Test
public void testPython() {
// 1.创建一个脚本引擎管理器
ScriptEngineManager scriptManager = new ScriptEngineManager();
// 2.根据名称获取对应的脚本引擎
ScriptEngine engine = scriptManager.getEngineByName("python");
if (engine != null) {
if (engine instanceof Invocable) {
invocableEngine = (Invocable) engine;
}
if (engine instanceof Compilable) {
compEngine = (Compilable) engine;
}
compiledScripts = new HashMap();
String script;
try {
// 加载文件内容
String fileName = "script/a.py";
String methodName = "main";
script = Loader.load(new File(fileName), "UTF-8");
if (script != null && script.length() > 0) {
// 注册脚本
if (register(fileName, script)) {
// 执行脚本
execScript(fileName, methodName, this);
}
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/**
* 注册一个脚本文件
*
* @param fileName
* 脚本文件
* @param script
* 脚本文件内容
* @return
*/
public boolean register(String fileName, String script) {
try {
// 这里就不判断路径这些了
if (fileName != null && script != null) {
CompiledScript cs = compEngine.compile(script);
compiledScripts.put(fileName, cs);
}
return true;
} catch (ScriptException e) {
System.out.println(e);
}
return false;
}
/**
* 执行脚本
*
* @param filename
* 文件名
* @param methodName
* 方法名
* @param objs
* 参数
* @return
*/
public Object execScript(String filename, String methodName, Object... objs) {
Object retValue = null;
try {
CompiledScript cs = compiledScripts.get(filename);
if (cs != null) {
cs.eval(); // 执行脚本
// 调用Python中的方法
retValue = invocableEngine.invokeFunction(methodName, objs);
}
} catch (ScriptException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
return retValue;
}
public void addPlayer(Player p) {
if (p != null) {
System.out.println(p.getAge());
}
}
}
a.py文件内容
from script import Player
def main(testPython):
# 创建Java中的对象
p = Player()
p.setAge(12)
print 'hello world'
# 调用testPython.java的方法 在Python 中空值是None
testPython.addPlayer(p)
return