如何使用 Rhino 在 Javascript 中添加 Java 类中的方法作为全局函数?

2022-09-04 22:04:31

我有一个简单的Java类,它有一些方法:

public class Utils {
    public void deal(String price, int amount) {
        // ....
    }
    public void bid(String price, int amount) {
        // ....
    }
    public void offer(String price, int amount) {
        // ....
    }
}

我想创建这个类的一个实例,并允许Javascript代码直接调用这些方法,如下所示:

deal("1.3736", 100000);
bid("1.3735", 500000);

我现在能弄清楚的唯一方法是使用

ScriptEngine engine = new ScriptEngineManager().getEngineByName("js");
engine.put("utils", new Utils());

然后在 Javascript 代码中使用。我还可以用Javascript为每个方法编写包装器函数,但是应该有一种更简单的方法可以自动为类的所有公共方法执行此操作。utils.deal(...)


答案 1

我对Rhino不是很熟悉,但这样的东西应该有效:

for(var fn in utils) {
  if(typeof utils[fn] === 'function') {
    this[fn] = (function() {
      var method = utils[fn];
      return function() {
         return method.apply(utils,arguments);
      };
    })();
  }
}

只需循环访问 的属性,对于每个函数,创建一个调用它的全局函数。utils

编辑:我在Groovy脚本中得到了这个工作,但我必须在绑定中设置utils,而不是像在你的代码中那样在引擎上设置:

import javax.script.*

class Utils {
   void foo(String bar) {
      println bar
   }   
}

ScriptEngine engine = new ScriptEngineManager().getEngineByName("js");

engine.eval("""
for(var fn in utils) {
  if(typeof utils[fn] === 'function') {
    this[fn] = (function() {
      var method = utils[fn];
      return function() {
         return method.apply(utils,arguments);
      };
    })();
  }
}

foo('foo'); // prints foo, sure enough
""",new SimpleBindings("utils":new Utils()))

答案 2

我不确定使用JSR-223 API将如何工作,但是使用Rhino API,您可以使用要添加的方法创建一个如下所示的方法。FunctionObject

Class[] parameters = new Class[] { String.class, Integer.class };
Method dealMethod = Utils.class.getMethod("deal", parameters);
engine.put("deal", new FunctionObject("deal", dealMethod, scope));

该文档可在 https://www.mozilla.org/rhino/apidocs/org/mozilla/javascript/FunctionObject.html 获得。

你可能需要引用 Rhino 库来访问该类,我不确定如何使用 JSR-223 API 获取对象(尽管这有可能有效)。FunctionObjectscopenull