2019独角兽企业重金招聘Python工程师标准>>>
在有些情况下需要在java里面执行javascript,这时rhino就可以帮忙了。mozilla的一个开源产品。
官网https://developer.mozilla.org/en-US/docs/Rhino
之前的一篇博客http://my.oschina.net/yybear/blog/101493里面介绍的事件模块处理程序就有利用javascript定义eventHandler,然后解释javascript执行。
先看一个简单的应用:
public class JavaScriptHandle {private Scriptable global;private int optimizationLevel = -1; // 介于-1到9之间,负值表示使用解释性执行,不会生成classprivate Script script;void handle() {Context ctx = Context.enter();try {ctx.setOptimizationLevel(optimizationLevel);if (script == null) {script = ctx.compileString("var str = 'xx'", "firstRhino", 0, null);}Scriptable scope = new NativeObject();scope.setParentScope(global);script.exec(ctx, scope);} finally {Context.exit();}}public static void main(String[] args) {JavaScriptHandle jsh = new JavaScriptHandle();jsh.handle();}
}
还是很简单的,只有传入一个javascript的字符串就可以了。但是更多时候我们希望在javascript里面也能调用java。比如我们希望执行这样的javascript
var s ='xx';$console.print(s);
$console表示java里面的标准输出。这时需要先创建一个类
public class ConsoleScriptable extends ScriptableObject {private static final long serialVersionUID = 1L;private PrintStream printStream;public void setPrintStream(PrintStream printStream) {this.printStream = printStream;}public ConsoleScriptable() {super();// TODO Auto-generated constructor stub}@Overridepublic String getClassName() {return ConsoleScriptable.class.getSimpleName();}@JSFunctionpublic static void print(Context cx, Scriptable thisObj, Object[] args, Function funObj) {print0(thisObj, args, false);}@JSFunctionpublic static void println(Context cx, Scriptable thisObj, Object[] args, Function funObj) {print0(thisObj, args, true);}private static void print0(Scriptable thisObj, Object[] args, boolean eol) {PrintStream printStream = checkInstance(thisObj).printStream;for (Object arg : args) {printStream.print(Context.toString(arg));}if (eol) {printStream.println();}}private static ConsoleScriptable checkInstance(Scriptable obj) {if (obj == null || !(obj instanceof ConsoleScriptable)) {throw Context.reportRuntimeError("called on incompatible object");}return (ConsoleScriptable) obj;}
这个类就是实现了$console打印字符的功能。使用时先要在rhino里面注册下这个类:JavaScriptHandle() {// 初始化Context ctx = Context.enter();global = ctx.initStandardObjects();try {ScriptableObject.defineClass(global, ConsoleScriptable.class);} catch (IllegalAccessException e) {e.printStackTrace();} catch (InstantiationException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();} finally {Context.exit();}}
使用代码:void handle() {Context ctx = Context.enter();try {ctx.setOptimizationLevel(optimizationLevel);if (script == null) {script = ctx.compileString("$console.print('xx');", "firstRhino", 0, null);}Scriptable scope = new NativeObject();scope.setParentScope(global);// 将$console设置标准输出ConsoleScriptable $console = (ConsoleScriptable) ctx.newObject(scope, ConsoleScriptable.class.getSimpleName());$console.setPrintStream(System.out);ScriptableObject.putProperty(scope, "$console", $console); // 设置属性script.exec(ctx, scope);} finally {Context.exit();}}
这样javascript里面就可以使用$console了。