77 lines
3.3 KiB
Java
77 lines
3.3 KiB
Java
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);
|
||
}
|
||
}
|