Как добавить методы из класса Java в качестве глобальных функций в Javascript с помощью Rhino?

у меня есть простой класс 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());

и затем использовать utils.deal(...) в коде Javascript. Я также могу писать функции-оболочки в Javascript для каждого метода, но должен быть более простой способ сделать это автоматически для всех открытые методы класса.

3 ответов


Я не очень знаком с 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, и для каждого, который является функцией, создайте глобальную функцию, которая вызывает ее.

EDIT: я получил это работает в Заводном скрипте, но я должен был установить 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()))

Я не уверен, как это будет работать с помощью API JSR-223, но с API Rhino вы можете создать 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.

для доступа к FunctionObject класс, и я не уверен, как вы получили бы scope объект с API JSR-223 (хотя, возможно, что null будет работать).


Это возможно, если вы используете API rhino, а не API ScriptEngine, как описано в этом ответе:https://stackoverflow.com/a/16479685/1089998.

Я предпочитаю этот подход ответу Ноя, поскольку это означает, что вам не нужно выполнять случайный код javascript перед каждым выполнением.

У меня есть рабочий пример здесь:

https://github.com/plasma147/rhino-play