rhino-java中调用javascript

无人久伴 提交于 2019-12-09 17:28:57

在有些情况下需要在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之间,负值表示使用解释性执行,不会生成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

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
	}

	@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了。
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!