Как я могу добавить методы из класса Java в качестве глобальных функций в Javascript, используя Rhino? - PullRequest
13 голосов
/ 31 марта 2010

У меня есть простой класс 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 ]

7 голосов
/ 31 марта 2010

Я не очень знаком с 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, но мне пришлось устанавливать утилиты в привязках, а не на движке, как в вашем коде:

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()))
4 голосов
/ 31 марта 2010

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

0 голосов
/ 05 октября 2013

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

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...