Spring boot 集成GraalVM JS引擎快速入门demo

一、GraalVM.js介绍

是一款 JavaScript 解释器/编译器,能够在 JVM 上运行 Node.js 应用;

主要应用场景

因为JS是动态语言,不需要编译,因此可以通过JS动态改变程序执行逻辑,比如:风控规则,服务编排等等

二、代码工程

pom.xml

    
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0"         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">    <parent>        <artifactId>springboot-demo</artifactId>        <groupId>com.et</groupId>        <version>1.0-SNAPSHOT</version>    </parent>    <modelVersion>4.0.0</modelVersion>
<artifactId>graalvm-js</artifactId>
<properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> </properties> <dependencies>
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-autoconfigure</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency>
<dependency> <groupId>org.graalvm.js</groupId> <artifactId>js-scriptengine</artifactId> <version>20.2.0</version> </dependency> <dependency> <groupId>org.graalvm.js</groupId> <artifactId>js</artifactId> <version>20.2.0</version> </dependency>
</dependencies>
</project>

属性文件

    
server:  port: 8088

启动类

    
package com.et.graalvm.js;
import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplicationpublic class DemoApplication {
public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); }}

代码仓库

  • https://github.com/Harries/springboot-demo

三、测试

本地调用

    
package com.et.graalvm.js;
import org.junit.Test;
import javax.script.*;
/** * @author liuhaihua * @version 1.0 * @ClassName com.et.graalvm.js.JSTest * @Description todo * @date 2024年03月07日 9:47 */
public class JSTest { @Test public void test10(){ // 创建JavaScript引擎 ScriptEngine jsEngine = new ScriptEngineManager().getEngineByName("js");// ScriptEngine jsEngine = new ScriptEngineManager().getEngineByExtension("js");// ScriptEngine jsEngine = new ScriptEngineManager().getEngineByMimeType("text/javascript"); // 方式一,默认设置变量 jsEngine.put("hello", "jack"); // 方式二,使用binding设置变量 SimpleBindings bindings = new SimpleBindings(); bindings.put("hello","world"); jsEngine.setBindings(bindings, ScriptContext.GLOBAL_SCOPE); // 方式三,使用Context设置变量 ScriptContext scriptContext = jsEngine.getContext(); scriptContext.setAttribute("hello", "polo", ScriptContext.ENGINE_SCOPE); try { // 方式一,直接调用 jsEngine.eval("print(hello)"); // 方式二,编译调用(需要重复调用,建议先编译后调用) if (jsEngine instanceof Compilable){ CompiledScript compileScript = ((Compilable) jsEngine).compile("print(hello)"); if (compileScript != null){ for (int i = 0; i < 10; i++) { compileScript.eval(); } } } Invocable invocable = ((Invocable)jsEngine); // 方式三,使用JavaScript中的顶层方法 jsEngine.eval("function greet(name) { print('Hello, ' + name); } "); invocable.invokeFunction("greet", "tom"); // 方式四,使用某个对象的方法 jsEngine.eval("var obj = { getGreeting: function(name){ return 'hello, ' + name; } } "); Object obj = jsEngine.get("obj"); Object result = invocable.invokeMethod(obj, "getGreeting", "kitty"); System.out.println(result);
} catch (ScriptException | NoSuchMethodException e) { e.printStackTrace(); } }}

远程调用

    
package com.et.graalvm.js;
import java.io.InputStream;import java.io.InputStreamReader;import java.io.BufferedReader;import java.io.IOException;import java.net.URL;import java.net.URLConnection;import javax.script.ScriptEngine;import javax.script.ScriptEngineManager;import javax.script.ScriptException;
public class RemoteJSTest { public static void main(String[] args) throws IOException, ScriptException { URL jsUrl = new URL("https://example.com/script.js"); // js文件的URL URLConnection connection = jsUrl.openConnection(); InputStream inputStream = connection.getInputStream(); // 获取js文件的流
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); StringBuilder sb = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { sb.append(line).append("\n"); // 将js文件的内容存入StringBuilder } reader.close(); inputStream.close();
ScriptEngineManager engineManager = new ScriptEngineManager(); ScriptEngine engine = engineManager.getEngineByName("nashorn"); // 获取Nashorn引擎 String script = sb.toString(); // js文件的内容 engine.eval(script); // 运行js文件
Object result = engine.eval("hello()"); // 调用js文件中名为"hello"的函数 System.out.println(result); // 输出结果 }}

四、引用

  • https://www.graalvm.org/reference-manual/js/JavaInteroperability/

  • https://github.com/graalvm/graaljs/blob/master/docs/user/JavaScriptCompatibility.md

  • http://www.liuhaihua.cn/archives/710296.html

相关推荐

  • 如果让你实现实时消息推送你会用什么技术?轮询、websocket还是sse
  • 2024年,大模型这些方向再次卷疯了!
  • 前端最能打的本地存储方案
  • 使用租户ID,实现一个企业级的SaaS系统,完整方案来了!
  • 面试官:一千万的数据,你是怎么查询的?
  • 10 个 Java Stream 顶级技巧,大量简化代码!
  • 为什么阿里巴巴修正了HashMap关于1024个元素扩容的次数?(典藏版)
  • 某女程序员失业半年,某央企答应给offer,本以为她已婚已孕,结果发现真相后......
  • 如何避免 PostgreSQL RDS 的陷阱:一份大数据解决方案的实践指南
  • 雷军:一定把小米汽车干好、干成;QQ测试AI聊天搭子,再战AI社交;零一万物宣布开源Yi-9B模型 | 极客头条
  • 竞赛中的一些花式Finetune方法。
  • CKA考试必备:解锁Pod封装多容器的高级技巧!
  • 阿里面试官: 说说你知道的移动端适配方式?
  • 生来取代Docker、JS,谷歌力推,这项技术发布7年后,现状如何?
  • 招商银行内推。。。
  • 聊聊MySQL的锁
  • 上来就对标 20k Star 的开源项目,是自不量力还是后起之秀?
  • 18.7 k 一款媲美飞书的团队协作利器,开源了!
  • Stable Diffusion 3论文终于发布,架构细节大揭秘,对复现Sora有帮助?
  • 院士委员:“破五唯”似乎越“破”越“唯”,“帽子”比以前更多了,建议将青年科技人员帽子和待遇脱钩,避免把人分为三六九等