Переход от Носорога до Нашорна
У меня есть проект Java 7, который много использует Javascript для написания различных функций. До сих пор я использовал Rhino как движок script. Теперь я хотел бы перейти на Java 8, что также означает, что я заменил Rhino на Nashorn.
Насколько совместим Нашорн с Носорогом? Могу ли я использовать его в качестве замены для замены, или я могу ожидать, что некоторые из моих скриптов больше не будут работать, и их нужно будет портировать на новый движок? Существуют ли обычно используемые функции Rhino, которые не поддерживаются Nashorn?
Ответы
Ответ 1
Одна из проблем заключается в том, что Nashorn уже не может по умолчанию импортировать целые пакеты Java в глобальную область с помощью importPackage(com.organization.project.package);
Существует, однако, простой способ: добавив эту строку в свой script, вы можете включить старое поведение Rhino:
load("nashorn:mozilla_compat.js");
Другая проблема, с которой я столкнулся, заключается в том, что определенные преобразования типов при передаче данных между java и javascript работают по-другому. Например, объект, который появляется при передаче массива Javascript на Java, больше не может быть перенесен в List
, но его можно отнести к Map<String, Object>
. В качестве обходного пути вы можете преобразовать массив Javascript в список Java в коде Javascript, используя Java.to(array, Java.type("java.util.List"))
Ответ 2
Чтобы использовать метод importClass на JDK 8, нам нужно добавить следующую команду:
load("nashorn:mozilla_compat.js");
Однако это изменение влияет на выполнение на JDK 7 (JDK не поддерживает метод загрузки).
Чтобы поддерживать совместимость для обоих SDK, я решил эту проблему, добавив предложение try/catch:
try{
load("nashorn:mozilla_compat.js");
}catch(e){
}
Ответ 3
Nashorn не может получить доступ к внутреннему классу, когда этот внутренний класс объявлен частным, что Rhino смог сделать:
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
public class Test {
public static void main(String[] args) {
Test test = new Test();
test.run();
}
public void run() {
ScriptEngineManager factory = new ScriptEngineManager();
ScriptEngine engine = factory.getEngineByName("JavaScript");
Inner inner = new Inner();
engine.put("inner", inner);
try {
engine.eval("function run(inner){inner.foo(\"test\");} run(inner);");
} catch (ScriptException e) {
e.printStackTrace();
}
}
private class Inner {
public void foo(String msg) {
System.out.println(msg);
}
}
}
В Java8 этот код генерирует следующее исключение:
javax.script.ScriptException: TypeError: [email protected] has no such function "foo" in <eval> at line number 1
at jdk.nashorn.api.scripting.NashornScriptEngine.throwAsScriptException(NashornScriptEngine.java:564)
at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:548)
Ответ 4
Я заметил, что у Rhino не было проблемы с функцией "in()" (хотя "in" - это зарезервированное ключевое слово JavaScript).
Ношорн, однако, выдает ошибку.
Ответ 5
Nashorn не может вызывать статические методы для экземпляров! Rhino сделал это, поэтому нам пришлось заложить Rhino на Java 8 (здесь короткое резюме: http://andreas.haufler.info/2015/04/using-rhino-with-java-8.html)
Ответ 6
Nashorn на Java8 не поддерживает АСТ. Поэтому, если у вас есть Java-код, который проверяет исходное дерево JS с использованием механизма Rhino AST, вам, возможно, придется переписать его (возможно, с помощью регулярного выражения), как только вы портируете код для использования Nashorn.
Я говорю об этом API https://mozilla.github.io/rhino/javadoc/org/mozilla/javascript/ast/AstNode.html
Nashorn на Java9 поддерживает AST, хотя.
Ответ 7
я использовал Mozilla Rhino в java6, и я переносил свой проект в java8 Nashorn и хотел использовать rhino, я добавил требуемый оператор в свой код загрузки java ("nashorn: mozilla_compat.js");
Но проблема, с которой я столкнулся при импорте меток классов. Мне нужно импортировать пару классов из моего файла JAR, который я использую в файле JS. importClass работает нормально для класса пакета java/javax, как. importClass (java.util.HashSet);
Но я не могу сделать импорт метки класса из другого файла класса jar файла, который присутствует в пути к классам. например importClass (Packages.mypack.ABC);
Тот же код работал нормально, когда я использовал java6/Rhino, Appriciate, если кто-то может мне помочь с этим.
Ответ 8
Одна функция, которая находится в Rhino, а не в Nashorn: отображение статических элементов через экземпляры.
От http://nashorn-dev.openjdk.java.narkive.com/n0jtdHc9/bug-report-can-t-call-static-methods-on-a-java-class-instance:"
Моя убежденность в том, что разоблачение статических элементов через экземпляры - это небрежное затирание в противном случае отдельных пространств имен, следовательно, я решил не включать его.
Я думаю, что это глубоко неправильно. До тех пор, пока мы должны использовать две разные конструкции для доступа к одному и тому же объекту java и без необходимости использовать объявления в javascript, код становится сложнее читать и писать, потому что увеличивается когнитивная нагрузка. Я скорее буду придерживаться Rhino.
Я еще не нашел обходного пути для этой очевидной "дизайнерской ошибки".