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