2025-08-19 16:15:06 +08:00

77 lines
3.3 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.wflow.workflow.execute;
import lombok.extern.slf4j.Slf4j;
import org.graalvm.polyglot.Context;
import org.graalvm.polyglot.HostAccess;
import org.graalvm.polyglot.Value;
import java.util.Objects;
import java.util.concurrent.ExecutorService;
/**
* @author : willian fu
* @date : 2023/10/28
*/
@Slf4j
public class JsExecute {
private static final Class[] alowJsCallJavaClass = new Class[]{
//HttpRequest.class, System.class
// GraalVM的HostAccess默认允许访问一些常见的类例如System
// 如果你需要访问自定义的类,你需要在这里配置
};
private static Context context;
// 使用 Context.Builder 来创建和配置沙箱环境
public JsExecute(ExecutorService executorService) {
if (Objects.isNull(context)) {
// 使用 Context.Builder 来创建和配置 GraalVM 沙箱
context = Context.newBuilder("js")
.allowHostAccess(HostAccess.ALL) // 允许访问所有Java对象
// 如果只想允许特定类可以使用HostAccess.newBuilder()
.allowHostClassLookup(s -> true) // 允许查找所有Java类
// 如果只想允许特定类,可以配置如下:
// .allowHostClassLookup(className -> {
// return className.equals("com.yourpackage.HttpRequest") || className.equals("java.lang.System");
// })
.allowAllAccess(true) // 允许所有访问包括I/O、线程等
.option("engine.WarnInterpreterOnly", "false") // 忽略解释器模式警告
.build();
// GraalVM的资源限制配置有所不同通常是在创建context时设置或者通过线程池等外部方式管理。
// 例如CPU时间限制等需要通过更复杂的机制实现Context.Builder不直接支持MaxCPUTime等。
// 内存限制通常通过JVM的-Xmx参数来控制。
// 你可以继续使用你传入的ExecutorService来控制并发。
}
}
public <T> T execute(String func, String script, Class<T> resultType, Object... args) {
try {
// 注意GraalVM 的 Context.eval() 有两种重载,
// 一种是直接执行,另一种是带源文件名的,这里简化使用
context.eval("js", script);
// 获取 JavaScript 函数
Value function = context.getBindings("js").getMember(func);
if (function == null || !function.canExecute()) {
throw new NoSuchMethodException("Function " + func + " not found or not executable.");
}
// 执行函数并获取结果
Value result = function.execute(args);
// 使用 Value.as() 方法进行类型转换,这是 GraalVM 推荐的方式
return result.as(resultType);
} catch (Exception e) {
log.error("js 函数[{}] [{}]执行异常: [{}]", func, script, e.getMessage());
throw new RuntimeException("js函数解析执行异常:" + e.getMessage(), e);
}
}
public void executeVoid(String func, String script, Object... args) {
execute(func, script, Object.class, args);
}
}