Spec-Zone .ru
спецификации, руководства, описания, API
|
JavaTM, Пишущий сценарий API, является языком сценариев indepedent платформа для того, чтобы использовать механизмы выполнения сценария от кода Java. С API Сценариев Java возможно записать настраиваемые/растяжимые приложения на языке Java и оставить выбор языка сценариев настройки до конца пользователем. Разработчик приложений Java не должен выбрать язык расширения во время разработки. Если Вы пишете свое приложение с API JSR-223, то Ваши пользователи могут использовать любой совместимый язык сценариев JSR-223.
вершинаФункциональность Сценариев Java находится в javax.script
пакет. Это - относительно маленький, простой API. Начальная точка API сценариев ScriptEngineManager
класс. Объект ScriptEngineManager может обнаружить механизмы выполнения сценария через механизм открытия файловой службы фляги. Это может также инстанцировать объектов ScriptEngine, которые интерпретируют сценарии, записанные в определенном языке сценариев. Самый простой способ использовать API сценариев следующие:
ScriptEngineManager
объект.ScriptEngine
объект от менеджера.ScriptEngine
's eval
методы.Теперь, пора смотреть на некоторый пример кода. В то время как это не обязательно, может быть полезно знать, что немного JavaScript читает эти примеры.
вершинаОт ScriptEngineManager
экземпляр, мы запрашиваем использование экземпляра механизма JavaScript getEngineByName
метод. На механизме выполнения сценария, eval
метод вызывают, чтобы выполнить данную Строку как код JavaScript! Для краткости, в этом так же как в последующих примерах, мы не показали обработку исключений. Там проверяются и исключения на этапе выполнения, брошенные от javax.script
API. Само собой разумеется необходимо обработать исключения соответственно.
import javax.script.*;
public class EvalScript {
public static void main(String[] args) throws Exception {
// create a script engine manager
ScriptEngineManager factory = new ScriptEngineManager();
// create a JavaScript engine
ScriptEngine engine = factory.getEngineByName("JavaScript");
// evaluate JavaScript code from String
engine.eval("print('Hello, World')");
}
}
вершина
В этом примере мы вызываем eval
метод, который принимает java.io.Reader
для входного источника. Сценарий, считанный данным читателем, выполняется. Этим путем возможно выполнить сценарии от файлов, URL и ресурсов, обертывая соответствующие входные потоковые объекты как читатели.
import javax.script.*;
public class EvalFile {
public static void main(String[] args) throws Exception {
// create a script engine manager
ScriptEngineManager factory = new ScriptEngineManager();
// create JavaScript engine
ScriptEngine engine = factory.getEngineByName("JavaScript");
// evaluate JavaScript code from given file - specified by first argument
engine.eval(new java.io.FileReader(args[0]));
}
}
Давайте предполагать, что у нас есть файл, названный "test.js" со следующим текстом:
println("This is hello from test.js");
Мы можем выполнить вышеупомянутый Java как
java EvalFile test.js
вершина
Когда Вы встраиваете механизмы выполнения сценария и сценарии с Вашим приложением Java, можно хотеть представить свои объекты приложения как глобальные переменные к сценариям. Этот пример демонстрирует, как можно представить свои объекты приложения как глобальные переменные к сценарию. Мы создаем a java.io.File
в приложении и представляют то же самое как глобальную переменную с именем "файл". Сценарий может получить доступ к переменной - например, это может вызвать открытые методы для этого. Отметьте, что синтаксис, чтобы получить доступ к объектам Java, методам и полям зависит от языка сценариев. JavaScript поддерживает самый "естественный" Подобный Java синтаксис.
public class ScriptVars {
public static void main(String[] args) throws Exception {
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("JavaScript");
File f = new File("test.txt");
// expose File object as variable to script
engine.put("file", f);
// evaluate a script string. The script accesses "file"
// variable and calls method on it
engine.eval("print(file.getAbsolutePath())");
}
}
вершина
Иногда можно хотеть вызвать определенную функцию сценариев неоднократно - например, Ваша функциональность меню приложения могла бы быть реализована сценарием. В обработчике событий действия Вашего меню можно хотеть вызвать определенную функцию сценария. Следующий пример демонстрирует, как вызывать определенную функцию сценария от кода Java.
import javax.script.*; public class InvokeScriptFunction { public static void main(String[] args) throws Exception { ScriptEngineManager manager = new ScriptEngineManager(); ScriptEngine engine = manager.getEngineByName("JavaScript"); // JavaScript code in a String String script = "function hello(name) { print('Hello, ' + name); }"; // evaluate script engine.eval(script); // javax.script.Invocable is an optional interface. // Check whether your script engine implements or not! // Note that the JavaScript engine implements Invocable interface. Invocable inv = (Invocable) engine; // invoke the global function named "hello" inv.invokeFunction("hello", "Scripting!!" ); } }
Если Ваш язык сценариев является основанным на объектах (как JavaScript) или объектно-ориентированным, то можно вызвать метод сценария на объект сценария.
import javax.script.*;
public class InvokeScriptMethod {
public static void main(String[] args) throws Exception {
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("JavaScript");
// JavaScript code in a String. This code defines a script object 'obj'
// with one method called 'hello'.
String script = "var obj = new Object(); obj.hello = function(name) { print('Hello, ' + name); }";
// evaluate script
engine.eval(script);
// javax.script.Invocable
is an optional interface.
// Check whether your script engine implements or not!
// Note that the JavaScript engine implements Invocable interface.
Invocable inv = (Invocable) engine;
// get script object on which we want to call the method
Object obj = engine.get("obj");
// invoke the method named "hello" on the script object "obj"
inv.invokeMethod(obj, "hello", "Script Method !!" );
}
}
вершина
Вместо того, чтобы вызвать определенные функции сценария от Java, иногда удобно реализовать интерфейс Java функциями сценария или методами. Кроме того, при использовании интерфейсов мы можем избежать иметь необходимость использовать javax.script
API во многих местах. Мы можем получить интерфейсный объект конструктора и передать его к различным API Java. Следующий пример демонстрирует, как реализовывать java.lang.Runnable
интерфейс со сценарием.
import javax.script.*;
public class RunnableImpl {
public static void main(String[] args) throws Exception {
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("JavaScript");
// JavaScript code in a String
String script = "function run() { println('run called'); }";
// evaluate script
engine.eval(script);
Invocable inv = (Invocable) engine;
// get Runnable interface object from engine. This interface methods
// are implemented by script functions with the matching name.
Runnable r = inv.getInterface(Runnable.class);
// start a new thread that runs the script implemented
// runnable interface
Thread th = new Thread(r);
th.start();
}
}
Если Ваш язык сценариев основан на объектах или объектно-ориентирован, возможно реализовать интерфейс Java методами сценария на объектах сценария. Это избегает иметь необходимость вызвать глобальные функции сценария для интерфейсных методов. Объект сценария может сохранить "состояние", связанное интерфейсным конструктором.
import javax.script.*;
public class RunnableImplObject {
public static void main(String[] args) throws Exception {
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("JavaScript");
// JavaScript code in a String
String script = "var obj = new Object(); obj.run = function() { println('run method called'); }";
// evaluate script
engine.eval(script);
// get script object on which we want to implement the interface with
Object obj = engine.get("obj");
Invocable inv = (Invocable) engine;
// get Runnable interface object from engine. This interface methods
// are implemented by script methods of object 'obj'
Runnable r = inv.getInterface(obj, Runnable.class);
// start a new thread that runs the script implemented
// runnable interface
Thread th = new Thread(r);
th.start();
}
}
вершина
В примере переменных сценария мы видели, как представить объекты приложения как глобальные переменные сценария. Возможно представить многократную глобальную переменную "контексты" для сценариев. Единственный контекст является экземпляром javax.script.Bindings
. Этот интерфейс получается из java.util.Map<String, Object>
. Ряд контекста пар значение-имя, где имя является любой непустой, непустой строкой. Многократные контексты поддерживаются javax.script.ScriptContext
интерфейс. Контекст сценария поддерживает один или более контекстов со связанной Привязкой для каждого контекста. По умолчанию у каждого механизма выполнения сценария есть контекст сценария по умолчанию. У контекста сценария по умолчанию есть по крайней мере один контекст под названием "ENGINE_SCOPE". Различные контексты, поддерживаемые контекстом сценария, доступны через getScopes
метод.
import javax.script.*;
public class MultiScopes {
public static void main(String[] args) throws Exception {
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("JavaScript");
engine.put("x", "hello");
// print global variable "x"
engine.eval("println(x);");
// the above line prints "hello"
// Now, pass a different script context
ScriptContext newContext = new SimpleScriptContext();
Bindings engineScope = newContext.getBindings(ScriptContext.ENGINE_SCOPE);
// add new variable "x" to the new engineScope
engineScope.put("x", "world");
// execute the same script - but this time pass a different script context
engine.eval("println(x);", newContext);
// the above line prints "world"
}
}
вершина
Реализация Oracle JDK 7 cо-связывается
Этот каталог и подкаталоги содержат источники Носорога с изменениями Oracle. Источники Носорога Mozilla лицензируются под Mozilla Public License Version 1.1. Можно получить копию этой Лицензии в http://www.mozilla.org/MPL
. Пожалуйста, отметьте что источники в com.sun.script
пакет и подпакеты не покрываются под MPL.
var v = new java.lang.Runnable() { run: function() { print('hello'); } } v.run();В большинстве случаев JavaAdapter используется, чтобы реализовать единственный интерфейс с программой сохранения анонимности Java подобный классу синтаксис. Использование JavaAdapter, чтобы расширить класс Java или реализовать многократные интерфейсы очень редко.
По большей части, получая доступ к классам Java, объекты и методы являются прямыми. В определенном поле и доступе метода от JavaScript то же самое, как это от Java. Мы выделяем важные аспекты доступа Java JavaScript здесь. Для получения дополнительной информации, пожалуйста, обратитесь к
Встроенные функции importPackage
и importClass
может использоваться, чтобы импортировать пакеты Java и классы.
// Import Java packages and classes
// like import package.*; in Java
importPackage(java.awt);
// like import java.awt.Frame in Java
importClass(java.awt.Frame);
// Create Java Objects by "new ClassName"
var frame = new java.awt.Frame("hello");
// Call Java public methods from script
frame.setVisible(true);
// Access "JavaBean" properties like "fields"
print(frame.title);
Глобальная переменная Пакетов может привыкнуть к пакетам Java доступа. Примеры: Packages.java.util.Vector
, Packages.javax.swing.JFrame
. Пожалуйста, отметьте, что "java" является ярлыком для "Packages.java". Есть эквивалентные ярлыки для javax, org, edu, com, сетевых префиксов, таким образом, к pratically все классы платформы JDK можно получить доступ без префикса "Пакетов".
Отметьте, что java.lang не импортируется по умолчанию (в отличие от Java), потому что это привело бы к конфликтам со встроенным Объектом JavaScript, Булевской переменной, Математикой и так далее.
importPackage
и importClass
функции "загрязняют" контекст глобальной переменной JavaScript. Избегать, чтобы, можно было использовать JavaImporter.
// create JavaImporter with specific packages and classes to import
var SwingGui = new JavaImporter(javax.swing,
javax.swing.event,
javax.swing.border,
java.awt.event);
with (SwingGui) {
// within this 'with' statement, we can access Swing and AWT
// classes by unqualified (simple) names.
var mybutton = new JButton("test");
var myframe = new JFrame("test");
}
вершина
В то время как создание объекта Java является тем же самым как в Java, чтобы создать массивы Java в JavaScript, мы должны использовать отражение Java явно. Но когда-то создаваемый доступ доступа или длины элемента является тем же самым как в Java. Кроме того, массив сценария может использоваться, когда метод Java ожидает массив Java (автоматическое преобразование). Так в большинстве случаев мы не должны создать массивы Java явно.
// create Java String array of 5 elements
var a = java.lang.reflect.Array.newInstance(java.lang.String, 5);
// Accessing elements and length access is by usual Java syntax
a[0] = "scripting is great!";
print(a.length);
вершина
Интерфейс Java может быть реализован в JavaScript при использовании Java анонимный подобный классу синтаксис:
var r = new java.lang.Runnable() {
run: function() {
print("running...\n");
}
};
// "r" can be passed to Java methods that expect java.lang.Runnable
var th = new java.lang.Thread(r);
th.start();
Когда интерфейс с единственным методом ожидается, можно передать функцию сценария непосредственно. (автоматическое преобразование)
function func() {
print("I am func!");
}
// pass script function for java.lang.Runnable argument
var th = new java.lang.Thread(func);
th.start();
вершина
Методы Java могут быть перегружены типами параметра. В Java разрешение перегрузки происходит во время компиляции (выполняемый javac). Вызывая методы Java из сценария, интерпретатор/компилятор сценария должен выбрать соответствующий метод. С механизмом JavaScript Вы не должны сделать ничего специального - корректная разновидность перегрузки метода Java выбирается основанная на типах параметра. Но, иногда можно хотеть (или иметь) явно выбрать определенную разновидность перегрузки.
var out = java.lang.System.out;
// select a particular println function
out["println(java.lang.Object)"]("hello");
Больше деталей о разрешении перегрузки метода Java JavaScript в
Мы не будем покрывать реализацию совместимых механизмов выполнения сценария JSR-223 подробно. Минимально, Вы должны реализовать javax.script.ScriptEngine
и javax.script.ScriptEngineFactory
интерфейсы. Абстрактный класс javax.script.AbstractScriptEngine
обеспечивает полезные значения по умолчанию для нескольких методов ScriptEngine
интерфейс.
Прежде, чем начать реализовывать механизм JSR-223, можно хотеть проверить