在有些狀況下須要在java裏面執行javascript,這時rhino就能夠幫忙了。mozilla的一個開源產品。 javascript
官網https://developer.mozilla.org/en-US/docs/Rhino java
以前的一篇博客http://my.oschina.net/yybear/blog/101493裏面介紹的事件模塊處理程序就有利用javascript定義eventHandler,而後解釋javascript執行。 ide
先看一個簡單的應用: this
public class JavaScriptHandle { private Scriptable global; private int optimizationLevel = -1; // 介於-1到9之間,負值表示使用解釋性執行,不會生成class private 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 spa
var s ='xx';$console.print(s);$console表示java裏面的標準輸出。
這時須要先建立一個類 .net
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 } @Override public String getClassName() { return ConsoleScriptable.class.getSimpleName(); } @JSFunction public static void print(Context cx, Scriptable thisObj, Object[] args, Function funObj) { print0(thisObj, args, false); } @JSFunction public 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了。