Graal JS绑定Java API:实现JS变量自动调用数据库取值
实现GraalJS中直接访问变量自动调用Java数据库查询
需求背景
现有GraalJS调用Java的代码,希望在JS脚本中直接使用变量名(如name)时,自动调用Java类AccessDataBase的getVakueFromDb方法获取对应键的数据库值,无需显式在JS中实例化Java类并调用方法。
解决方案:自定义Bindings实现自动查询
通过重写JSR-223规范中的Bindings对象的get方法,让脚本引擎在JS访问变量时自动触发数据库查询逻辑。
步骤1:修改Java主类代码
import com.oracle.truffle.js.scriptengine.GraalJSScriptEngine; import org.graalvm.polyglot.Context; import javax.script.*; public class Main { public static void main(String[] args) throws ScriptException, CompilableScriptException { // 初始化数据库访问实例 AccessDataBase dbAccessor = new AccessDataBase(); // 创建GraalJS上下文配置 Context.Builder contextBuilder = Context.newBuilder("js") .allowAllAccess(true) .option("js.nashorn-compat", "true"); GraalJSScriptEngine graalJSScriptEngine = GraalJSScriptEngine.create(null, contextBuilder); // 自定义Bindings,拦截变量访问请求 Bindings customBindings = new SimpleBindings() { @Override public Object get(Object key) { if (key instanceof String) { // 自动调用数据库查询方法获取变量值 return dbAccessor.getVakueFromDb((String) key); } // 非字符串键或内置变量,按默认逻辑处理 return super.get(key); } }; // 将自定义Bindings绑定到脚本引擎的全局作用域 graalJSScriptEngine.setBindings(customBindings, ScriptContext.ENGINE_SCOPE); // 测试脚本:直接访问name变量 String script = "function accessKey(){ return name; }; accessKey();"; Compilable compilable = (Compilable) graalJSScriptEngine; CompiledScript compiledScript = compilable.compile(script); Object result = compiledScript.eval(); System.out.println("查询到的name值:" + result); } }
步骤2:数据库访问类(保留原有逻辑)
public class AccessDataBase { public Object getVakueFromDb(String key){ // 替换为实际数据库查询逻辑 if ("name".equals(key)) { return "GraalJS自动绑定测试值"; } return "默认值"; } }
原理说明
- 当JS脚本中访问某个变量(如
name)时,GraalJS引擎会调用绑定的Bindings对象的get方法,传入变量名作为参数。 - 重写的
get方法会将变量名传递给AccessDataBase.getVakueFromDb,返回数据库查询结果,实现变量的自动解析。
扩展优化点
- 若需要支持变量写入数据库,可重写
Bindings.put方法,在JS赋值时触发数据库写入逻辑。 - 添加异常处理:在
get方法中捕获数据库查询异常,返回默认值或抛出脚本可处理的错误。 - 内置变量过滤:对于JS内置对象(如
console、Date),可在get方法中先判断,避免不必要的数据库查询。
内容的提问来源于stack exchange,提问作者Mangesh Darekar
相关产品推荐
相关产品推荐

