ホームページ >Java >&#&チュートリアル >Java スクリプト プログラミング ガイドのコード例を共有する

Java スクリプト プログラミング ガイドのコード例を共有する

黄舟
黄舟オリジナル
2017-03-20 10:24:322075ブラウズ

Java スクリプト API誰のためのものですか?

スクリプト言語の便利な機能は次のとおりです:

  • 利便性: ほとんどのスクリプト言語は動的に型指定されます。通常、変数の型を宣言しなくても新しい変数を作成でき、変数を再利用してさまざまな型のオブジェクトを格納できます。さらに、スクリプト言語は、必要に応じて数字の 10 を「10」に変換するなど、さまざまな種類の変換を自動的に実行する傾向があります。

  • ラピッドプロトタイプの開発: 編集コンパイルの実行サイクルを回避し、「編集実行」だけを使用できます。

  • アプリの拡張/カスタマイズ: 一部の構成スクリプト、ビジネス ロジック/ルール、金融アプリケーションの数式など、アプリケーションの一部を「具体化」できます。

  • デバッグ、ランタイム構成/デプロイ時間のためにアプリケーションにコマンドラインモードを追加します。最近のほとんどのアプリケーションには、Web ベースの GUI 構成ツールが備わっています。ただし、システム管理者や導入担当者はコマンド ライン ツールを好むことがよくあります。この目的を達成するには、アドホックなスクリプト言語を発明するのではなく、「標準」スクリプト言語を使用できます。

Java Script API は、Java コードのスクリプト エンジンを使用する、フレームワークに依存しないスクリプト言語です。 Java Scripting API を使用すると、Java 言語を使用してカスタム/拡張可能なアプリケーションを作成し、カスタム スクリプト言語の選択をエンド ユーザーに任せることができます。 Java アプリケーション開発者は、開発中に拡張言語を選択する必要はありません。 JSR-223 API を使用してアプリケーションを作成する場合、ユーザーは JSR-223 準拠のスクリプト言語を使用できます。

スクリプトパッケージ

Java スクリプト機能は javax.script パッケージにあります。これは比較的小さく、単純な API です。スクリプトの開始点は ScriptEngineManager クラスです。 ScriptEngineManager オブジェクトは、jar ファイルのサービス検出メカニズムを通じてスクリプト エンジンを検出できます。また、スクリプト エンジンをインスタンス化して、特定のスクリプト言語で書かれたスクリプトを解釈することもできます。スクリプト インターフェイスを使用する最も簡単な方法は次のとおりです。

  1. ScriptEngineManager オブジェクトを作成します ScriptEngineManager  对象

  2. 从 ScriptEngineManager  获取 ScriptEngine  对象

  3. 使用 ScriptEngine的eval方法执行脚本

现在,是时候看一些样本代码了。了解一些JavaScript有助于阅读这些例子,但不是强制的。

实例

“Hello,World”

从ScriptEngineManager实例中,我们通过 getEngineByName

ScriptEngineManager から ScriptEngine オブジェクトを取得します>

ScriptEngine の eval メソッドを使用してスクリプトを実行します

次に、サンプル コードを見てみましょう。これらの例を読む際には、JavaScript

について知っておくと役立ちますが、必須ではありません。

インスタンス

「Hello, World」

ScriptEngineManager インスタンスから、getEngineByName メソッドを通じて JavaScript エンジン インスタンスを取得します。スクリプト エンジンの 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')");
    }
}
スクリプトファイルを実行する

この例では、入力ソースとして java.io.Reader を受け取るために eval メソッドを呼び出します。読み込まれたスクリプトが実行されます。このメソッドは、スクリプトをファイルとして実行し、関連する入力ストリーム オブジェクトを使用して 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 EvalFile test.js

スクリプト変数

Java アプリケーションにスクリプトが埋め込まれている場合、エンジンとスクリプトを使用する場合、アプリケーション オブジェクトをグローバル変数としてスクリプトに公開することができます。この例では、アプリケーション オブジェクトをグローバル変数としてスクリプトに公開する方法を示します。アプリケーション内のグローバル変数として java.io.File オブジェクトを 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 で呼び出す代わりに、スクリプト関数またはメソッドを使用して Java インターフェイスを実装すると便利な場合があります。同時に、インターフェイスを通じて、多くの場所で javax.script API インターフェイスの使用を回避できます。インターフェイス実装オブジェクトを取得して、それをさまざまな Java API に渡すことができます。次の例は、スクリプトを使用して 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();
    }
}

脚本的多作用域

在 script variables 例子中,我们看到怎样将应用对象暴露为脚本的全局变量。它有可能暴露为多个全局的作用域 。 单作用域是javax.script.Bindings的实例中. 这个借口派生至java.util.Map994a833a6ffa28d85b72cb15422c29d6。 scope 键值对的集合,其中键为非空、非空字符串。 多scopes 是 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"
    }
}

JavaScript 脚本引擎

Sun的JDK 6中包含了一个基于 Mozilla Rhino JavaScript 脚本引擎。 这个引擎是基于版本为1.6R2的Mozilla Rhino 。多数 Rhino 实现都被包含在内。少部分组件由于大小和安全原因被排除了:

  1. JavaScript转字节码编译 (也称 ”优化器”).。此功能依赖一个类生成库。 去掉本功能意味着:JavaScript是解释执行,且不影响脚本执行,因为优化器是透明的。

  2. Rhino的JavaAdapter 也被去掉了。 JavaAdapter是一个JavaScript可扩展Java类和JavaScript可实现Java接口功能。此功能也是需要类生成库的。我们把Rhino的JavaAdapter替换为Sun实现的JavaAdapter。在Sun的实现中,仅仅实现了JavaScript对象可实现Java单接口功能。例如,下面的代码会正确执行。

           var v = new java.lang.Runnable() {
                        run: function() { print('hello'); }
                   }
           v.run();

    在大多数情况下,JavaAdapter是采用匿名类语法来实现单接口。 使用JavaAdapter来扩展Java类或实现多接口并不常见。

  3. E4X (ECMAScript for XML – ECMA Standard 357) 被去掉了. 使用XML JavaScript代码会产生一个语法错误. 请注意,E4X支持ECMAScript标准是可选的-省略E4X的实现是被支持也是兼容 ECMAScript 。

  4. Rhino的命令行工具 (Rhino shell, debugger 等) 没有被包含在内。但你可以用使用 jrunscript来代替。

JavaScript与Java的通信

在大多数情况下,访问Java类、对象和方法很简单。从JavaScript中访问属性和方法与同Java中一样。这里,我们突出JavaScript Java访问的重要方面.。下面是一些JavaScript访问Java的代码片段。本节需要一些JavaScript知识。如果你打算使用JSR-223中非JavaScript脚本语言,那么本节可以跳过。

引入Java 包, 类

内置的函数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);

全局变量Packages也可以用于访问Java包。例如: Packages.java.util.VectorPackages.javax.swing.JFrame. 请注意: ”java” 是 “Packages.java”的快捷引用。还有一些等价的快捷引用前缀 : javax, org, edu, com, net, 所以几乎所有的 JDK 平台下的类都可以不使用”Packages” 前缀而访问到。

请注意,java.lang不是默认引入的 (与Java不同),因为会与 JavaScript’s 内置的 Object, Boolean, Math 等冲突。

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");
}

C创建和使用Java的数组

在JavaScript中,创建一个对象时与Java中一样,而创建Java数组时需要显式的使用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匿名类语法形式实现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");

自定义脚本引擎

我们不会覆盖的JSR-223兼容脚本引擎实现细节. 至少, 您需要实现javax.script.ScriptEngine 和javax.script.ScriptEngineFactory 接口。 抽象类javax.script.AbstractScriptEngine 提供了一些ScriptEngine 接口中定义的方法。

在开始实现 JSR-223 引擎之前,您可能需要下载。这个工程维护了一些流行的开源脚本语言的 JSR-223 实现。

以上がJava スクリプト プログラミング ガイドのコード例を共有するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。