Java使用JS引擎小记

最近做了一个小需求,需要解析js文件,获取一些配置项信息,并转存为properteis的格式。
目前技术栈是JDK15,并且因为这个版本踩了不少坑,记录一下。

nashorn在jdk15被遗弃

nashorn是JDK 15之前默认的js引擎,可以看看stackoverflow的这个讨论。

nashorn 不支持 es6语法

JDK 17虽然不提供nashorn,但是可以单独增加依赖。我有尝试单独安装了nashorn的依赖,但是在解析的时候发现会因为const报错,我在openjdk官网查到了这个JDK-8024712bug,另外还在w3schools确认了一下,确实不支持,所以就放弃了nashorn

在网上查了一下可以使用GraalVM JavaScript Implementation作为替代品。

GraalVM JavaScript Implementation 最低支持JDK 17

可以从官网查到其最低都是JDK 17了

但是我目前技术栈选型的问题,没办法直接升JDK版本,会带来更多的问题,所以只能作罢。

结论

最终是用的低版本的GraalVM JavaScript Implementation,包名和版本号和JDK 17的都有差别,对应的应该是

1
2
implementation 'org.graalvm.js:js:20.2.0'  
implementation 'org.graalvm.js:js-scriptengine:20.2.0'

demo:

代码是在原来的基础上做了大量简化和脱敏,不保证可以直接运行哈

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package com.baofeidyz.demo;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.Feature;
import org.graalvm.polyglot.Context;
import org.graalvm.polyglot.Value;

class Demo {

public Map<String, Object> parse(String content) {
try (
Context context = Context.newBuilder("js")
.allowAllAccess(true)
.build()) {
// 手动定义 module 和 exports (这是因为我解析的js文件是配置文件,没有module和exports,为了避免报错,所以手动加了)
context.getBindings("js").putMember("module", context.eval("js", "({})"));
context.getBindings("js").putMember("exports", context.eval("js", "({})"));
// 执行 JavaScript 代码
context.eval("js", content);
// 获取 exports 对象
Value exports = context.getBindings("js").getMember("GLOBAL_CONFIG");
// 解析 JSON 字符串
return JSONObject.parseObject(exports.toString(), Feature.OrderedField);
}
}
}

其他

我有注意到hutools也有提供一些类和方法去调用js引擎,前期我确实是想通过hutools套一下的,后面觉得意义不是特别大,就直接用了。