Подтвердить что ты не робот

Как добавить методы из класса 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 для каждого метода, но должен быть более простой способ сделать это автоматически для всех общедоступных методов класса.

4b9b3361

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

EDIT: Я получил эту работу в Groovy script, но мне пришлось устанавливать 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 для доступа к классу FunctionObject, и я не уверен, как вы получите объект scope с API JSR-223 (хотя возможно, что null работа).

Ответ 3

Это возможно, если вы используете API-интерфейс rhino, а не API ScriptEngine, как описано в этом ответе: fooobar.com/info/425086/....

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

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

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