graalvm使用实战:在java中执行js脚本

1.背景

前几周接到一个需求,需要做一个业务逻辑判断:根据的订单属性,走不同的业务逻辑。由于这个判断配置很多变,业务希望交由他们自己来管理配置。

那么我就在思考一个问题,有什么方法可以做到逻辑代码是免编译的,写完之后就能立马生效的。答案是有的,就是JS,因为JS是动态语言,不需要编译,因此可以通过JS动态改变程序执行逻辑。那么我又在想,那Java中可以执行JS嘛?一查还真的可以。

如果你的项目是 JDK 8之前的,可以使用Rhino;如果是8的,可以使用Nashorn,但需要特别注意的是,Nashorn在 JDK 11 中被标记为废弃,并在 JDK 15 中被彻底移除。因此到了 JDK17、21、24这样的版本,就需要用到graalvm了。

2.介绍graalvm

GraalVM 多语言 API(js、ruby、python、java) 允许您在基于 JVM 的宿主应用程序中嵌入并运行来自其他语言的代码。

3.实战

3.1环境配置(可选)

如果是开发环境,可以直接使用openjdk即可进行开发,本步骤可忽视。

如果是生产环境,则必须要配置graalvmjdk,这个jdk是graalvm官方的二次开发,能提高graalvm的运行性能。

下载地址:https://graalvm.java.net.cn/downloads/#

3.2依赖导入

graalvm.polyglot.version可以选定一个适合自己的版本。

xml 复制代码
<dependency>
	<groupId>org.graalvm.polyglot</groupId>
	<artifactId>polyglot</artifactId>
	<version>${graalvm.polyglot.version}</version>
</dependency>
<dependency>
	<groupId>org.graalvm.polyglot</groupId>
	<!-- Select a language: js, ruby, python, java, llvm, wasm, languages-->
	<artifactId>js</artifactId>
	<version>${graalvm.polyglot.version}</version>
	<type>pom</type>
</dependency>

3.3代码编写

这里我把js单独存放到数据库中,然后在对js做增删改查,提供给业务做管理。

java层代码:

java 复制代码
	public String checkCanPushBack(String entityId, Order order) {
        CSRJSScriptBase goscjsScript = csrjsScriptFunctionService.getGOSCJSScript(entityId);
        String jsCode = goscjsScript.getJsCode();

        if (StrUtil.isNotEmpty(jsCode)){
            try(Context context = Context.newBuilder().allowAllAccess(true).build()){
                //给js的变量注入对象
                Value bindings = context.getBindings("js");
                bindings.putMember("order", order);

                //执行js脚本
                Value result = context.eval("js", jsCode);

                log.info("js脚本执行结果是:{}",  result);

                return result.asString();
            }
        }
        return "G7";
    }

js逻辑判断代码:

js 复制代码
/*
  以下对象可直接引用
  order

  result:脚本返回的结果
*/
var Coating2 = order.getCoatingWaterMark();
var AR = order.getCoating2();
var Lab = order.getWaterMark();
var index = order.getRefractionIndex();

//默认是G7
var result = "G7";

if (Coating2 == 'BV47' || ['BP', 'DD', 'HB'].includes(AR)) {
    //不支持退单
    result = 'false';
} else if (Coating2 == 'BV47') {
    //走G1逻辑
    result = 'G1';
} else if (Lab.includes('GZ') {
    //走G2逻辑
    result = 'G2';
} else if (Lab.includes('GZ') && index == 1.74) {
    //发G3逻辑
    result = 'G3';
}

//返回结果
result;

4.参考

官方文档:https://www.graalvm.org/jdk21/reference-manual/embed-languages/

相关推荐
古法安卓6 小时前
Android-日志系统源码解析
android·java·android studio
专业抄代码选手6 小时前
08|Fiber 上的 `useState`:状态终于属于具体组件
前端·javascript·react.js
默_笙6 小时前
😭 Vibe Coding 翻车实录:AI 编程为什么必须先写"剧本"
前端·javascript
lerhxx7 小时前
我用 R3F 手搓了一个能走进去的 3D 迷宫简历(上):从选型架构到迷宫生成算法
前端·javascript·three.js
小夏coding7 小时前
从"一把梭"到"精妙拆解" —— 滑动窗口计时框架的设计演进
java·后端
MacroZheng8 小时前
同事问我:"Claude Code经常失忆,不怕它把项目搞炸?",我:"怕,三个Markdown文件给它装个永不丢失的外置大脑!"
java·人工智能·后端
十年Java程序媛10 小时前
深度实战:JDK21 虚拟线程 + HikariCP 生产正确配比、坑点、监控全套
java·spring boot
xiaoqiMikko10 小时前
有人在搜一个不存在的 Tomcat 版本
java·tomcat
鹏多多12 小时前
PC 网站接入微信登录,这 10 个坑我替你踩完了!
前端·javascript·vue.js
用户31268748772013 小时前
ConcurrentHashMap 怎么保证线程安全?从分段锁到 CAS+synchronized
java