Кодирование JavaScript на JVM

Что такое Нашорн?

Nashorn - это движок JavaScript для JVM, выпущенный вместе с Java 8. Nashorn состоит из встроенного интерпретатора JavaScript и инструмента командной строки. Задача Nashorn - реализовать высокопроизводительную среду выполнения JavaScript на Java с собственной JVM. Используя Nashorn, разработчик может встраивать JavaScript в приложение Java, а также вызывать методы и классы Java из кода JavaScript, обеспечивая бесшовную интеграцию между двумя языками.

Роль Нэшорна в сценариях на стороне сервера

написание серверного JS в настоящее время является обычным требованием. Поскольку JavaScript становится популярным в серверном программировании - например, Node.js, Nashorn обеспечивает интеграцию приложений JavaScript и Java путем доступа к функциям JavaScript в Java и наоборот. Он напрямую компилирует код JavaScript в памяти и передает байт-код Java в JVM. Добавляя поддержку серверных сценариев к вашим продуктам с помощью Nashorn, мы можем легко настроить продукт в соответствии с различными требованиями без необходимости каждый раз перекомпилировать.

Теперь давайте посмотрим на некоторые функции Nashorn.

Вызов функций JavaScript из Java

Простой пример hello world.

ScriptEngine nashorn = new ScriptEngineManager().getEngineByName
("nashorn");
nashorn.eval("print('Hello, world')");

Мы можем передать весь файл .js в метод .eval () для более серьезных случаев использования следующим образом.

ScriptEngine engine = new ScriptEngineManager().getEngineByName ("nashorn");
engine.eval(new FileReader("script.js"));

Передача объектов Java в качестве аргументов функции и возвращаемых значений из функции JS в вызывающий метод Java

  • приведите механизм сценария к Invocable, чтобы иметь возможность вызывать функцию.
  • NashornScriptEngine определяет метод invokeFunction для вызова функции JavaScript для заданного имени.
String script = "function var printHello = function(name) {
  print('Hello, ' + name);
  return 'hello from Javascript';
};";
ScriptEngine engine = new ScriptEngineManager().getEngineByName ("nashorn");
Invocable invocable = (Invocable) engine;
 Object result = invocable.invokeFunction("printHello", "Sathya");

Вызов методов Java из JavaScript

Мы можем ссылаться на классы Java из JavaScript, используя расширение API Java.type. Это похоже на импорт классов в коде Java.

var MyJavaClass = Java.type (‘com.test.JavaScriptTest’);
var result = MyJavaClass.func1 (‘Sathya’); //call a function named 'func1'
print (result);

Вызов API Java из JavaScript

Вариант 1 - укажите полное имя, то есть имя пакета

var joinString=Java.type (“java.lang.String”)
 joinString.join (“ “, “Hello”, “World”)

Вариант 2. Доступ к глобальным объектам, определенным для API Java, по имени пакета.

java.lang.String.join (“ “,”Hello”,”World”)

ScriptObjectMirror

ScriptObjectMirror является частью jdk.nashorn.api и предназначен для использования в клиентском коде вместо внутренних классов.

Этот зеркальный объект является представлением базового объекта JavaScript и обеспечивает доступ к нему, его методам и свойствам.

ScriptObjectMirror реализует интерфейс Map.

Облегчает вызов функций-членов для объектов JavaScript из Java. Пример будет следующим.

/*Person is a JavaScript type with some properties and a function.*/
function Person(firstName, lastName) { 
  this.firstName = firstName;
  this.lastName = lastName;
  this.getFullName = function() {
    return this.firstName + ' ' + this.lastName;
  }
}

Функцию getFullName() можно вызвать на ScriptObjectMirror через callMember()

public static void getFullName(ScriptObjectMirror person) {
    System.out.println("Full name is: " + person.callMember("getFullName"));
}

Привязки / Контекст

ScriptContext содержит одну или несколько привязок, каждая из которых связана с областью. По умолчанию есть две области:
ENGINE_SCOPE
GLOBAL_SCOPE

Когда создается движок Nashorn, он создает контекст по умолчанию:
ScriptContext defaultContext = engine.getContext();

ENGINE_SCOPE контекста по умолчанию - это область, в которой хранятся «глобальные» объекты и функции (Object, Function, Math, RegExp, parseInt и т. Д.).

GLOBAL_SCOPE используется всеми движками, созданными одним и тем же ScriptEngineManager.

Вы можете хранить переменные в контексте (использование области необязательно, по умолчанию ENGINE_SCOPE):

ScriptContext context = engine.getContext();
// stores an object under the key `myKey` in the (engine scoped) context
context.setAttribute("myKey", object, ScriptContext.ENGINE_SCOPE);
// retrieves the object with key `myKey` from (engine scoped) context
context.getAttribute("myKey", ScriptContext.ENGINE_SCOPE);
Bindings b = context.getBindings(ScriptContext.ENGINE_SCOPE);
b.get("Object");    // gets ECMAScript "Object" constructor
b.get("undefined"); // ECMAScript 'undefined' value

Если переменная не найдена в ENGINE_SCOPE, выполняется поиск GLOBAL_SCOPE привязок.

Java Beans

С Nashorn вы получаете прямой доступ к свойствам Java-бина, больше не нужно использовать геттеры и сеттеры:

var Date = Java.type('java.util.Date');
var date = new Date();
date.year += 1900; // -> no setter!
print(date.year);  /

Свойства привязки

Вы можете привязать свойства одного объекта к другому:

var o1 = {};
var o2 = { foo: 'bar' };
Object.bindProperties(o1, o2);
print(o1.foo);   
o1.foo = 'John';
print(o2.foo);

Чтобы получить полный список возможностей Nashorn, вы можете обратиться к [1].

Пример использования Nashorn

Предположим, у нас есть IAM-решение, обеспечивающее адаптивную схему аутентификации, написанную исключительно на Java.

В адаптивной схеме аутентификации мы привязываем процесс аутентификации к внешним параметрам. Например, контекстуальные факты - сколько раз пользователь пытался войти в систему, специфические атрибуты пользователя - IP-адрес пользователя, местоположение, устройство, набор привилегий и т. Д. В этой схеме администраторы должны иметь возможность изменять потоки входа и аутентификации на основе это динамические данные.

Теперь предположим, что вы хотите продать это программное обеспечение нескольким клиентам. У каждого клиента могут быть разные требования, и может потребоваться настройка вашего решения. Если все решение реализовано на Java, нам может быть сложно изменить бизнес-логику в соответствии с требованиями каждого клиента, и это потребует серьезных изменений уровня кода и перекомпиляции. Наряду с этим идут обширные циклы тестирования изменений на уровне кода. Это может стать обузой для разработчика программного обеспечения и, несомненно, потребует большей части его ресурсов - времени, усилий, оборудования и т. Д.

В качестве решения вместо написания программного обеспечения исключительно на Java мы можем добавить в продукт поддержку сценариев с использованием Nashorn. С помощью сценариев Nashorn мы предоставляем клиентам, для которых мы пишем это программное обеспечение, возможность настраивать бизнес-логику под требования каждого клиента без перекомпиляции кода.

Теперь мы можем легко продавать программное обеспечение нескольким клиентам и подробно рассказывать о его функциях. Клиенты могут реализовать свою собственную логику с привлечением пользовательских сценариев, написав небольшой фрагмент кода JavaScript с бизнес-правилами, зависящими от клиента, и их требования будут удовлетворены за счет минимального участия разработчика решения. Во время выполнения Nashorn будет выполнять эти сценарии, включая динамические параметры.

Плюсы

  • Добавьте в свои продукты поддержку сценариев, которые позволят вам или вашим пользователям быстро разрабатывать и изменять продукт в соответствии с различными потребностями без необходимости перекомпилировать или изучать внутреннюю работу продукта.
  • Предоставляет возможность изменять бизнес-логику вашего программного обеспечения на лету без изменения кода Java и перекомпиляции кода в соответствии с требованиями каждого клиента.
  • Повышение настраиваемости приложений. возможность реализации основных частей бизнес-логики и точек расширения, поскольку JavaScript упрощает изменение во время выполнения.
  • Такое разделение частей приложения может позволить гораздо быстрее исправить ошибки и добавить дополнительные функции.
  • Сокращает общий цикл DTAP программного обеспечения
  • Обеспечивает гораздо более быстрое выполнение и многопоточность JavaScript при работе в Java JRE.
  • Обеспечение доступа ко всем преимуществам Java - обширным библиотекам, оптимизации кода, обширным сетям поддержки и т. Д.
  • Возможность использования гибкого языка с динамической типизацией, с которым уже знакомы многие программисты.
  • Значительные улучшения производительности по сравнению с Mozilla's Rhino.
  • Nashorn очень легко интегрируется и используется с JavaFX. Пользователи могут очень легко интерпретировать приложение-скрипт JavaFX с помощью Nashorn с помощью инструмента командной строки jjs.