Java中运行JavaScript

想要在Java中运行脚本语言,需要运行该脚本语言的特定的引擎,而JavaScript的引擎则是Nashorm,该引擎是jdk8默认集成的,可以直接使用。

ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("nashorn");
// 运行一个字符串脚本
String scriptString = "n = 3";
engine.eval(scriptString);
// 运行存储在文本文件中的脚本
BufferedReader reader = Files.newBufferedReader(Paths.get("test.txt"));
engine.eval(reader);
// 在同一个引擎上面运行过的脚本会保留到最后,比如这里使用了刚才定义的 n 参数
Object result = engine.eval("n + 1");
System.out.println("结果为 4 --------》 result = " + result);

对于Nashorm引擎,多线程是不安全的,不要在多线程的环境下使用。可以通过下面的方式查询一个引擎是否支持多线程环境。

  • null 不支持并发执行
  • MULTITHREADED 支持并发执行,多个线程之间效果可能可见
  • THREAD-ISOLATED 支持并发执行,为每一个线程创建独立的变量,不互相影响
  • STATELESS 支持并发执行,不创建独立变量,互相影响
System.out.println("是否支持多线程:" + engine.getFactory().getParameter("THREADING"));

关于变量的域,最大的是全局的域,添加到ScriptEngineManager中,对所有的引擎可见。比较常用的是引擎的域,就是一个引擎中可见。一个引擎中还可以继续细分成多个Binding域。

manager.put("param", 100);
engine.put("param", 80);
System.out.println("引擎域" + engine.get("param"));
Bindings bindings = engine.createBindings();
bindings.put("param", 60);
System.out.println("结果为binding的变量+1 -------> " + engine.eval("param + 1", bindings));

可以改变引擎的源输出流,把结果打印到其他地方,比如本地文件里面。

String outScript = "print(\"Hello\")";
BufferedWriter writer = Files.newBufferedWriter(Paths.get("out.txt"));
engine.getContext().setWriter(writer);
engine.eval(outScript);

nashorn引擎实现了Invocable接口,可以直接调用函数,调用的方式如下:

String funScript = "function sayHello(person){ return 'hello ' + person }";
engine.eval(funScript);
Object funResult = ((Invocable) engine).invokeFunction("sayHello", "zhangsan");
System.out.println(funResult);

调用对象中的函数:

String defineObj = "function Person(name){ this.name = name }";
String defineMethod =
        "Person.prototype.sayHello = function(other)" +
                "{ return this.name + ' say hello to ' + other }";
engine.eval(defineObj);
engine.eval(defineMethod);
Object obj = engine.eval("new Person('lisi')");
Object objResult = ((Invocable) engine).invokeMethod(obj, "sayHello", "zhangsan");
System.out.println(objResult);

使用脚本语言实现自己的接口也是可以的,接口的方法名称和脚本语言中定义的函数名称相同:

// 定义一个接口
public interface Person {
    String sayHello(String person);
}

------------------------------------

String funScript = "function sayHello(person){ return 'hello ' + person }";
engine.eval(funScript);
Person person = ((Invocable) engine).getInterface(Person.class);
System.out.println(person.sayHello("zhangsanJava"));

如果需要重复的运行一段脚本,可以把它编译成中间状态,然后就可以高效地执行脚本:

String funScript = "n + 1";
CompiledScript script = ((Compilable) engine).compile(funScript);
if (null != script) {
    script.eval();
} else {
    engine.eval(funScript);
}

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值