如何将类型和函数传递给JSR-223脚本? [英] How to pass types and functions to a JSR-223 script?

查看:288
本文介绍了如何将类型和函数传递给JSR-223脚本?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

典型的 JSR-223 脚本将从一系列代理导入开始像这样(出于示例目的选择了JavaScript + Nashorn):

A typical JSR-223 script would begin with a series of surrogate imports like this (JavaScript+Nashorn chosen for example purposes):

// "import" classes and static methods
var Foo = Java.type("my.package.Foo"); // application classes require Java.type() use
var bar = Foo.bar; // static method
var Logger = java.util.logging.Logger; // system classes can be accessed directly
var sin = java.lang.Math.sin; // the same for static methods

// use them
var foo = new Foo();
print(bar());
var log = Logger.getLogger("foo");
print(sin(42));

我想通过为脚本模拟类似于导入的功能来摆脱那些替代.这意味着,我想通过我的Java代码预先创建全局对象(如上例中的FoobarLoggersin).这应该会自动使一组通用的导入可用于多个脚本.

I want to get rid of those surrogates by emulating an import-like functionality for scripts. That means, I want to have global objects (like Foo, bar, Logger and sin in the example above) pre-created by my Java code. This should automatically make a common set of imports available for multiple scripts.

我发现使用Nashorn的两种方法:

I have found two methods for doing that with Nashorn:

方法1 :生成脚本前奏,并在主脚本前生成eval().从字面上看,这就是上面示例代码的前半部分.

Method 1: Generate a script prelude and eval() it before the main script. That would be literally the first half of the example code above.

方法2 :从ScriptEngine获取类和方法引用,对其进行缓存并用于后续的脚本调用:

Method 2: Obtain class and method references from a ScriptEngine, cache them and use for subsequent script invocations:

ScriptEngineManager sem = new ScriptEngineManager();
ScriptEngine nashorn = sem.getEngineByName("nashorn");

Object fooClass = nashorn.eval("Java.type('my.package.Foo')"); // instance of jdk.internal.dynalink.beans.StaticClass
Object loggerClass = nashorn.eval("java.util.logging.Logger"); // the same

Object barFunction = nashorn.eval("Java.type('my.package.Foo').bar"); // instance of jdk.internal.dynalink.beans.SimpleDynamicMethod
Object sinFunction = nashorn.eval("java.lang.Math.sin"); // the same

ScriptEngine nashorn1 = sem.getEngineByName("nashorn");

nashorn1.put("Foo", fooClass);
nashorn1.put("bar", barFunction);
nashorn1.put("Logger", loggerClass);
nashorn1.put("sin", sinFunction);
nashorn1.eval("var foo = new Foo(); bar(); var log = Logger.getLogger('foo'); print(sin(42));");

很显然,这些方法都不能用于任何其他JSR-223引擎.有没有办法以可移植的方式实现相同的目标?

Obviously, none of those methods would work for any other JSR-223 engine. Is there a way to implement the same in a portable manner?

推荐答案

我不知道如何解决有关新操作的问题(如何避免调用Java.type()).

I have no idea on how to solve the issue regarding the new operation (how to avoid the calls to Java.type()).

但是在编译脚本时,可以将方法分配为lambda:

But when you compile your script, you can assign methods as lambdas:

ScriptEngineManager scriptEngineManager = new ScriptEngineManager();
Compilable nashorn = (Compilable) scriptEngineManager.getEngineByName( "Nashorn" );

CompiledScript script = nashorn.compile( "print( sin( 3.14 ) ); var log = getLogger( 'foo' );" );

Bindings bindings = new SimpleBindings();
bindings.put( "sin", (DoubleFunction<Double>) Math::sin );
bindings.put( "getLogger", (Function<String,Logger>) Logger::getLogger );

script.eval( bindings );

对于方法void bar()(没有参数,没有返回值),您必须提供自己的功能接口,因为java.util.function程序包没有针对该方法的软件包.

For the method void bar() (no arguments, no return value), you have to provide your own functional interface, as the java.util.function package does not have one for that kind of method.

不幸的是,这种方法似乎不适用于未编译的脚本.并且它不适用于所有类型的lambda(功能接口).我做了一些实验,但是找不到一种模式,什么有效,什么无效.可以肯定的是,定义方法引发检查异常的功能接口不能以这种方式工作.同样,如果功能接口不是公共的而是私有的内部接口.

Unfortunately, this approach seems not to work for not-compiled scripts. And it does not work for all types of lambdas (functional interfaces). I did some experiments, but could not find a pattern yet what works and what not. It is for sure that functional interfaces that define a method throwing a checked exception do not work this way. Also if the functional interface is not public but a private inner interface.

很明显,我从上面的示例代码中省略了其他必要的错误处理和try-catch块.

这篇关于如何将类型和函数传递给JSR-223脚本?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆