77 lines
3.3 KiB
Java
Raw Normal View History

2024-08-10 14:12:47 +08:00
package com.wflow.workflow.execute;
import lombok.extern.slf4j.Slf4j;
2025-08-19 16:15:06 +08:00
import org.graalvm.polyglot.Context;
import org.graalvm.polyglot.HostAccess;
import org.graalvm.polyglot.Value;
2024-08-10 14:12:47 +08:00
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[]{
2025-08-19 16:15:06 +08:00
//HttpRequest.class, System.class
// GraalVM的HostAccess默认允许访问一些常见的类例如System
// 如果你需要访问自定义的类,你需要在这里配置
2024-08-10 14:12:47 +08:00
};
2025-08-19 16:15:06 +08:00
private static Context context;
2024-08-10 14:12:47 +08:00
2025-08-19 16:15:06 +08:00
// 使用 Context.Builder 来创建和配置沙箱环境
2024-08-10 14:12:47 +08:00
public JsExecute(ExecutorService executorService) {
2025-08-19 16:15:06 +08:00
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来控制并发。
2024-08-10 14:12:47 +08:00
}
}
public <T> T execute(String func, String script, Class<T> resultType, Object... args) {
try {
2025-08-19 16:15:06 +08:00
// 注意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.");
2024-08-10 14:12:47 +08:00
}
2025-08-19 16:15:06 +08:00
// 执行函数并获取结果
Value result = function.execute(args);
// 使用 Value.as() 方法进行类型转换,这是 GraalVM 推荐的方式
return result.as(resultType);
} catch (Exception e) {
2024-08-10 14:12:47 +08:00
log.error("js 函数[{}] [{}]执行异常: [{}]", func, script, e.getMessage());
2025-08-19 16:15:06 +08:00
throw new RuntimeException("js函数解析执行异常:" + e.getMessage(), e);
2024-08-10 14:12:47 +08:00
}
}
public void executeVoid(String func, String script, Object... args) {
execute(func, script, Object.class, args);
}
}