跳到主要内容

8.5 JSR-223

dataql-engine 提供 JDK javax.script 接口,可通过 ScriptEngineManager 发现引擎,支持脚本执行和 Compilable 预编译。

执行脚本​

Jsr223Example.java
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import net.hasor.dataql.kernel.QueryResult;

public class Jsr223Example {
public static void main(String[] args) throws Exception {
ScriptEngine engine = new ScriptEngineManager().getEngineByName("dataql");
if (engine == null) {
throw new IllegalStateException("dataql-engine is missing from the runtime classpath");
}
engine.put("name", "DataQL");
QueryResult result = (QueryResult) engine.eval("return ${name};");
System.out.println(result.getData().unwrap());
}
}

输出为 DataQL。eval 返回 QueryResult,通过 getData().unwrap() 读取实际结果。也可按扩展名 dql 或媒体类型 application/x-dataql 查找引擎。

预编译与按次传参​

以下代码接续上例的 engine,编译一次,使用独立上下文执行两次:

import javax.script.Compilable;
import javax.script.CompiledScript;
import javax.script.ScriptContext;
import net.hasor.dataql.host.jsr223.QueryScriptContext;
import net.hasor.dataql.kernel.QueryResult;

CompiledScript compiled = ((Compilable) engine).compile("return ${name};");
QueryScriptContext defaults = (QueryScriptContext) engine.getContext();

for (String name : new String[] {"Alice", "Bob"}) {
QueryScriptContext context = new QueryScriptContext(defaults.getHostContext());
context.setAttribute("name", name, ScriptContext.ENGINE_SCOPE);
QueryResult result = (QueryResult) compiled.eval(context);
System.out.println(result.getData().unwrap());
}

输出为 Alice、Bob。上下文必须使用 QueryScriptContext,并与引擎共享同一个 HostContext。当前实现不接受普通 SimpleScriptContext,eval(script, bindings) 和 compiled.eval(bindings) 也不支持;按次传参使用上述方式。

参数与配置​

  • engine.put(...) 写入 ENGINE_SCOPE。取参数时先合并 GLOBAL_SCOPE,再由 ENGINE_SCOPE 覆盖同名值;$、@、# 读取相同的合并结果。
  • GLOBAL_SCOPE 的键还会声明为共享变量,可在脚本中直接使用变量名;这些键应在编译前设置。新建上下文需要自行设置所需的全局 Bindings。
  • 通过 ((QueryScriptContext) engine.getContext()).getConfiguration() 获取 HostConfiguration,按核心接口注册扩展。
  • 引擎实现 Compilable,未实现 Invocable。运行阶段的 QueryRuntimeException 包装为 ScriptException,语法或编译错误可能直接抛出对应异常。