目錄
API為誰準備? " >Java腳本化API為誰準備?
腳本套件
實例
「Hello,World」
執行一個腳本檔
腳本變數
函數和方法" >呼叫腳本函數和方法
透過腳本實作Java接口
脚本的多作用域
JavaScript 脚本引擎
JavaScript与Java的通信
引入Java 包, 类
C创建和使用Java的数组
实现Java 接口
重载" >重载
自定义脚本引擎
首頁 Java java教程 Java腳本化程式指南的程式碼實例分享

Java腳本化程式指南的程式碼實例分享

Mar 20, 2017 am 10:24 AM

Java腳本化API為誰準備?

腳本語言的一些有用的特性是:

  • 方便:大多數腳本語言都是動態類型的。您通常可以建立新的變量,而不聲明變數類型,並且可以重複使用變數來儲存不同類型的物件。此外,腳本語言往往會自動執行許多類型的轉換,例如, 必要時 將數字10轉換為「10」。

  • 開發快速原型:您可以避免編輯編譯運行週期,只使用「編輯運行」!

  • 應用程式/自訂:你可以「具體化」的部分應用程序,例如一些配置腳本,業務邏輯/規則和財務應用中的數學表達式 。

  • 為應用程式新增命令列模式,用於偵錯、執行時間配置/部署時間。現在大多數應用程式都有一個基於Web的GUI設定工具。但是系統管理員/部署人員常常喜歡命令列工具。一個「標準」的腳本語言可以用來實現這個目的,而不是發明特設的腳本語言。

Java 腳本 API 是一種獨立於框架的腳本語言,使用來自於Java程式碼的腳本引擎 。透過java腳本API,可以使用Java語言編寫自訂/可擴展的應用程式並將自訂腳本語言選擇留給最終用戶 。 Java 應用程式開發者不需要在開發過程中選擇擴充語言。如果你使用JSR-223 API來編寫應用,那麼你的使用者可以使用任何JSR-223相容的腳本語言。

腳本套件

Java 腳本功能是在 javax.script 套件中。這是一個比較小的,簡單的API。腳本的出發點是 ScriptEngineManager 類別。一個 ScriptEngineManager 物件可以透過jar檔案的服務發現機制發現腳本引擎。它也可以實例化腳本引擎來解釋使用特定的腳本語言編寫的腳本。使用腳本程式介面的最簡單的方法如下:

  1. 建立一個 ScriptEngineManager  物件

  2. 從 ScriptEngineManager   取得 ScriptEngine  物件

  3. #使用 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')");
    }
}
登入後複製

執行一個腳本檔

在這個範例中,我們呼叫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 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.Map<String, Object>。 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(&#39;hello&#39;); }
                   }
           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 包, 类

内置的函数importPackageimportClass 可以用于引入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.Vector, Packages.javax.swing.JFrame. 请注意: ”java” 是 “Packages.java”的快捷引用。还有一些等价的快捷引用前缀 : javax, org, edu, com, net, 所以几乎所有的 JDK 平台下的类都可以不使用”Packages” 前缀而访问到。

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

importPackageimportClass 函数”污染” 了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 &#39;with&#39; 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中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.聊天命令以及如何使用它們
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

Java 中的完美數 Java 中的完美數 Aug 30, 2024 pm 04:28 PM

Java 完美數指南。這裡我們討論定義,如何在 Java 中檢查完美數?

Java 中的隨機數產生器 Java 中的隨機數產生器 Aug 30, 2024 pm 04:27 PM

Java 隨機數產生器指南。在這裡,我們透過範例討論 Java 中的函數,並透過範例討論兩個不同的生成器。

Java中的Weka Java中的Weka Aug 30, 2024 pm 04:28 PM

Java 版 Weka 指南。這裡我們透過範例討論簡介、如何使用 weka java、平台類型和優點。

Java 中的史密斯數 Java 中的史密斯數 Aug 30, 2024 pm 04:28 PM

Java 史密斯數指南。這裡我們討論定義,如何在Java中檢查史密斯號?帶有程式碼實現的範例。

Java Spring 面試題 Java Spring 面試題 Aug 30, 2024 pm 04:29 PM

在本文中,我們保留了最常被問到的 Java Spring 面試問題及其詳細答案。這樣你就可以順利通過面試。

突破或從Java 8流返回? 突破或從Java 8流返回? Feb 07, 2025 pm 12:09 PM

Java 8引入了Stream API,提供了一種強大且表達力豐富的處理數據集合的方式。然而,使用Stream時,一個常見問題是:如何從forEach操作中中斷或返回? 傳統循環允許提前中斷或返回,但Stream的forEach方法並不直接支持這種方式。本文將解釋原因,並探討在Stream處理系統中實現提前終止的替代方法。 延伸閱讀: Java Stream API改進 理解Stream forEach forEach方法是一個終端操作,它對Stream中的每個元素執行一個操作。它的設計意圖是處

Java 中的時間戳至今 Java 中的時間戳至今 Aug 30, 2024 pm 04:28 PM

Java 中的時間戳記到日期指南。這裡我們也結合範例討論了介紹以及如何在java中將時間戳記轉換為日期。

Java程序查找膠囊的體積 Java程序查找膠囊的體積 Feb 07, 2025 am 11:37 AM

膠囊是一種三維幾何圖形,由一個圓柱體和兩端各一個半球體組成。膠囊的體積可以通過將圓柱體的體積和兩端半球體的體積相加來計算。本教程將討論如何使用不同的方法在Java中計算給定膠囊的體積。 膠囊體積公式 膠囊體積的公式如下: 膠囊體積 = 圓柱體體積 兩個半球體體積 其中, r: 半球體的半徑。 h: 圓柱體的高度(不包括半球體)。 例子 1 輸入 半徑 = 5 單位 高度 = 10 單位 輸出 體積 = 1570.8 立方單位 解釋 使用公式計算體積: 體積 = π × r2 × h (4

See all articles