Springboot 集成graalvm.js 执行JavaScript

首先在pom文件中添加依赖

<!-- 添加 graalvm js-->
       
<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>
集成依赖后我们就可以在项目中使用相关的功能
controller内容

import com.exam.service.JavaScriptService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class JsController {

    @Autowired
    private JavaScriptService jsService;

    @GetMapping("/add")
    public Object add(@RequestParam double a, @RequestParam double b) {
        String script = "function add(a, b) { return a + b; }";
        return jsService.executeJavaScript(script, "add", a, b);
    }

    @GetMapping("/greet")
    public Object greet(@RequestParam String name) {
        String script = "function greet(name) { return 'Hello, ' + name + '!'; }";
        return jsService.executeJavaScript(script, "greet", name);
    }
}

Service内容


import com.exam.service.JavaScriptService;
import org.graalvm.polyglot.Context;
import org.graalvm.polyglot.Value;
import org.springframework.stereotype.Service;

@Service
public class JavaScriptServiceImpl implements JavaScriptService {
    @Override
    public Object executeJavaScript(String script, String functionName, Object... args) {
        try (Context context = Context.create("js")) {

            // 执行整个脚本
            context.eval("js", script);

            // 获取函数
            Value function = context.getBindings("js").getMember(functionName);
            if (function != null && function.canExecute()) {
                return function.execute(args).as(Object.class);
            } else {
                throw new RuntimeException("Function " + functionName + " not found or not executable.");
            }

        } catch (Exception e) {
            throw new RuntimeException("Error executing JavaScript: " + e.getMessage(), e);
        }
    }
}

测试结果

 可以优化controller中方法,直接将方法和script传入

    @PostMapping("/execute")
    public ResponseEntity<?> executeScript(@RequestBody Map<String, Object> request) {
        try {
            String script = (String) request.get("script");
            String functionName = (String) request.get("functionName");
            List<Object> args = (List<Object>) request.getOrDefault("args", new ArrayList<>());

            Object result = jsService.executeJavaScript(script, functionName, args.toArray());
            return ResponseEntity.ok(result);
        } catch (Exception e) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.getMessage());
        }
    }

### 如何在 GraalVM 中使用 JavaScript 执行异步操作 #### 使用 `Promise` 和 `async/await` 为了实现异步编程模式,可以利用 JavaScript 的原生特性——Promises以及基于其上的`async/await`语法糖来简化代码逻辑。当这些功能被引入到支持多语言环境下的 GraalVM 时,开发者能够更加方便地编写非阻塞式的程序[^1]。 下面是一个简单的例子展示如何创建并处理一个返回字符串 `'foo'` 的异步函数: ```javascript // 定义了一个名为 getFoo 的异步函数 async function getFoo() { return 'foo'; } // 测试该异步方法是否能正确解析为预期的结果 describe('#getFoo', () => { it('resolves with foo', async () => { const result = await getFoo(); assert.equal(result, 'foo'); }); }); ``` 这段测试案例通过 Mocha 框架验证了 `getFoo()` 函数的行为,其中包含了对异步调用的支持。 对于更复杂的场景,比如网络请求或其他 I/O 密集型任务,在 GraalVM 上运行的 JavaScript 应用同样可以通过 Polyglot API 或者集成特定库的方式发起 HTTP 请求,并等待响应完成后再继续执行后续的操作。例如,如果要模拟抓取网页数据并通过浏览器自动化工具切换页面,则可能涉及到如下形式的脚本片段[^4]: ```javascript const jsExecutor = session.getJavaScriptExecutor(); jsExecutor.executeScript( ` (function(){ let promise = new Promise((resolve,reject)=>{ window.addEventListener('load',(event)=>{ resolve(document.body.innerHTML); }) }); return promise; })(); ` ); // 假设此处有进一步处理获取到的内容... ``` 上述代码展示了怎样借助于 `JavaScriptExecutor` 接口捕获加载事件之后整个文档对象模型的状态变化情况,从而实现了跨页导航的同时保持良好的用户体验。 值得注意的是,尽管传统版本的 JavaScript 并不具备块级作用域内的局部变量声明机制,这可能会导致意外行为的发生;然而现代 ECMAScript 版本已经加入了诸如 `let` 和 `const` 关键字用于限定变量的作用范围,有效解决了这一类问题带来的困扰[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值