最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

java中如何調(diào)用js

 更新時間:2025年01月23日 11:08:08   作者:java_monkey_110  
Nashorn是Java8中引入的一個新的JavaScript引擎,它允許在JVM上運(yùn)行JavaScript代碼,并且可以與Java代碼相互調(diào)用,Nashorn遵循JSR233規(guī)范,是一個純Java實現(xiàn)的JavaScript引擎,可以與Java程序無縫集成,提供動態(tài)腳本執(zhí)行和靈活性

java中調(diào)用js

我們都知道腳本語言非常靈活,在處理某些問題的時候 Java 實現(xiàn)用十幾行來寫,用 js 可能不到十行就寫完,并且非常簡潔,那么有沒有一種優(yōu)雅的方式將 Java 與腳本語言結(jié)合呢,在 Java SE6(代號 Mustang)中,這將成為現(xiàn)實。

Nashorn,一個新的 JavaScript 引擎隨著 Java 8 一起公諸于世,它允許在 JVM 上開發(fā)運(yùn)行某些 JavaScript 應(yīng)用。Nashorn 就是 javax.script.ScriptEngine 的另一種實現(xiàn),并且它們倆遵循相同的規(guī)則,允許 Java 與 JavaScript 相互調(diào)用。

Mustang 的腳本引擎

JSR 233 為 Java 設(shè)計了一套腳本語言 API。這一套 API 提供了在 Java 程序中調(diào)用各種腳本語言引擎的接口

任何實現(xiàn)了這一接口的腳本語言引擎都可以在 Java 程序中被調(diào)用。在 Mustang 的發(fā)行版本中包括了一個基于 Mozilla Rhino 的 JavaScript 腳本引擎,也就是說在 JavaSE6+ 的版本默認(rèn)可以直接調(diào)用執(zhí)行 JavaScript。

Mozilla Rhino

Rhino 是一個純 Java 的開源的 JavaScript 實現(xiàn)。他的名字來源于 O’Reilly 關(guān)于 JavaScript 的書的封面,是的,就是那本犀牛書…

Rhino 項目可以追朔到 1997 年,當(dāng)時 Netscape 計劃開發(fā)一個純 Java 實現(xiàn)的 Navigator,為此需要一個 Java 實現(xiàn)的 JavaScript —— Javagator。

它也就是 Rhino 的前身。起初 Rhino 將 JavaScript 編譯成 Java 的二進(jìn)制代碼執(zhí)行,這樣它會有最好的性能。后來由于編譯執(zhí)行的方式存在垃圾收集的問題并且編譯和裝載過程的開銷過大,不能滿足一些項目的需求,Rhino 提供了解釋執(zhí)行的方式。

隨著 Rhino 開放源代碼,越來越多的用戶在自己的產(chǎn)品中使用了 Rhino,同時也有越來越多的開發(fā)者參與了 Rhino 的開發(fā)并做出了很大的貢獻(xiàn)。如今 Rhino 將被包含在 Java SE 中發(fā)行,更多的 Java 開發(fā)者將從中獲益。

Rhino 提供了如下功能:

  • 對 JavaScript 1.5+ 的完全支持
  • 直接在 Java 中使用 JavaScript 的功能
  • 一個 JavaScript shell 用于運(yùn)行 JavaScript 腳本
  • 一個 JavaScript 的編譯器,用于將 JavaScript 編譯成 Java 二進(jìn)制文件

支持的腳本語言

在 dev.java.net 可以找到官方的腳本引擎的實現(xiàn)項目。這一項目基于BSD License ,表示這些腳本引擎的使用將十分自由。

目前該項目已對包括 Groovy, JavaScript, Python, Ruby, PHP 在內(nèi)的二十多種腳本語言提供了支持。這一支持列表還將不斷擴(kuò)大。

在Java中的基本使用

在 Mustang 中對腳本引擎的檢索使用了工廠模式。

首先需要實例化一個工廠 : ScriptEngineManager

ScriptEngineManager factory = new ScriptEngineManager();

ScriptEngineManager 將在 Thread Context ClassLoader 的 Classpath 中根據(jù) jar 文件的 META-INF 來查找可用的腳本引擎。

它提供了 3 種方法來檢索腳本引擎:

// create engine by name
ScriptEngine engine = factory.getEngineByName ("JavaScript");
// create engine by name
ScriptEngine engine = factory.getEngineByExtension ("js");
// create engine by name
ScriptEngine engine = factory.getEngineByMimeType ("application/javascript");

下面的代碼將會打印出當(dāng)前的 JDK 所支持的所有腳本引擎:

ScriptEngineManager factory = new ScriptEngineManager();
for (ScriptEngineFactory available : factory.getEngineFactories()) {
  System.out.println(available.getEngineName());
  // 打印腳本具體名稱信息
  System.out.println(available.getNames());
}

即可看到 [nashorn, Nashorn, js, JS, JavaScript, javascript, ECMAScript, ecmascript] 等輸出,說明可執(zhí)行 Js 腳本

執(zhí)行Js腳本

啥也別說了,都知道要干嘛,來打印句 HelloWorld 再說:

public class RunJavaScript {
  public static void main(String[] args){
    ScriptEngineManager factory = new ScriptEngineManager();
    ScriptEngine engine = factory.getEngineByName ("JavaScript");
    engine.eval("print('Hello World')");
  }
}

如果你的 Js 有語法錯誤,就會拋出 javax.script.ScriptException 異常

如果我們要解釋一些更復(fù)雜的腳本語言,或者想在運(yùn)行時改變該腳本該如何做呢?腳本引擎支持一個重載的 eval 方法,它可以從一個 Reader 讀入所需的腳本,或者得到 Js 文件的絕對路徑,直接用自帶的 load 函數(shù)讀?。?/p>

ScriptEngineManager factory = new ScriptEngineManager();
ScriptEngine engine = factory.getEngineByName ("JavaScript");
engine.eval(new Reader("HelloWorld.js"));


File file = new File(Main.class.getClassLoader().getResource("test.js").getFile());
engine.eval(new FileReader(file));

String scriptPath = Main.class.getClassLoader().getResource("test.js").getPath();
engine.eval("load('" + scriptPath + "')");

這里注意下 FileReader 中相對路徑到底是相對誰的(JVM 啟動的位置),可使用 ClassLoader 讀取 src 下的文件

Java 程序?qū)討B(tài)的去讀取腳本文件并解釋執(zhí)行,這意味著,在程序運(yùn)行中你可以隨意修改 Js 文件里的代碼,會得到實時修改結(jié)果。

對于這一簡單的 Hello World 腳本來說,IO 操作將比直接執(zhí)行腳本損失 20% 左右的性能(SE6 時,個人測試),但他帶來的靈活性 — 在運(yùn)行時動態(tài)改變代碼的能力,在某些場合是十分激動人心的。

最后來看看完整的測試代碼:

package com.bfchengnuo.javascript;

import javax.script.*;
import java.io.FileNotFoundException;

/**
 * Created by 冰封承諾Andy on 2017/12/30.
 */
public class Main {
  public static void main(String[] args) throws ScriptException, NoSuchMethodException, FileNotFoundException {
    ScriptEngineManager manager = new ScriptEngineManager();

    System.out.println("當(dāng)前 JDK 支持的腳本語言引擎:");
    for (ScriptEngineFactory available : manager.getEngineFactories()) {
      System.out.println(available.getEngineName());
      System.out.println(available.getNames());
    }

    ScriptEngine engine = manager.getEngineByName("JavaScript");
    if (!(engine instanceof Invocable)) {
      System.out.println("Invoking methods is not supported.");
      return;
    }
    engine.eval("print('Hello World')");

    Invocable inv = (Invocable) engine;

    // File file = new File(Main.class.getClassLoader().getResource("test.js").getFile());
    // engine.eval(new FileReader(file));
    String scriptPath = Main.class.getClassLoader().getResource("test.js").getPath();
    engine.eval("load('" + scriptPath + "')");

    // 獲取對象
    Object calculator = engine.get("calculator");

    int x = 3;
    int y = 4;
    Object addResult = inv.invokeMethod(calculator, "add", x, y);
    Object subResult = inv.invokeMethod(calculator, "subtract", x, y);
    Object mulResult = inv.invokeMethod(calculator, "multiply", x, y);
    Object divResult = inv.invokeMethod(calculator, "divide", x, y);

    System.out.println(addResult);
    System.out.println(subResult);
    System.out.println(mulResult);
    System.out.println(divResult);
  }
}

對應(yīng)的 Js 文件:

var calculator = {};

calculator.add = function (n1, n2) { return n1 + n2};
calculator.subtract = function (n1, n2) {return n1 - n2};
calculator.multiply = function (n1, n2) {return n1 * n2};
calculator.divide = function (n1, n2) {return n1 / n2};

腳本語言與 Java 的通信

ScriptEngine 的 put 方法用于將一個 Java 對象映射成一個腳本語言的變量?,F(xiàn)在有一個 Java Class,它只有一個方法:

public class HelloWorld {
  String s = "Hello World";
  public void sayHello(){
    System.out.println(s);
  }
}

接下來就是讓 Js 使用這個類!還是看代碼最實在:

public class TestPut {
  public static void main(String[] args) throws ScriptException {
    ScriptEngineManager factory = new ScriptEngineManager();
    ScriptEngine engine = factory.getEngineByName("JavaScript");
    HelloWorld hello = new HelloWorld();
    engine.put("script_hello", hello);
    engine.eval("script_hello.sayHello()");
  }
}

首先我們實例化一個 HelloWorld,然后用 put 方法將這個實例映射為腳本語言的變量 script_hello。那么我們就可以在 eval() 函數(shù)中像 Java 程序中同樣的方式來調(diào)用這個實例的方法。

使用 invokeFunction 來執(zhí)行 Js 函數(shù):

public class TestInv {
  public static void main(String[] args) throws Exception {
    ScriptEngineManager factory = new ScriptEngineManager();
    ScriptEngine engine = factory.getEngineByName("JavaScript");
    String script = "function say(first,second) { print(first +' '+ second); }";
    engine.eval(script);
    Invocable inv = (Invocable) engine;
    inv.invokeFunction("say", "Hello", "Tony");
  }
}

這里使用了 ScriptEngine 的兩個可選接口之一 : Invocable,Invocable 表示當(dāng)前的 engine 可以作為函數(shù)被調(diào)用。

這里我們將 engine 強(qiáng)制轉(zhuǎn)換為 Invocable 類型,使用 invokeFunction 方法將參數(shù)傳遞給腳本引擎。invokeFunction 這個方法使用了可變參數(shù)的定義方式,可以一次傳遞多個參數(shù),并且將腳本語言的返回值作為它的返回值。

Invocable 接口還有一個方法用于從一個 engine 中得到一個 Java Interface 的實例,它接受一個 Java 的 Interface 類型作為參數(shù),返回這個 Interface 的一個實例。

也就是說你可以完全用腳本語言來寫一個 Java Interface 的所有實現(xiàn)!然后直接調(diào)用使用返回的實現(xiàn)類就可以了!

engine.eval(script);
Invocable inv = (Invocable) engine;
MaxMin maxMin = inv.getInterface(MaxMin.class);

java 處理js返回值

  • JDK11之前版本
package io.icefox;

import java.util.Map;
import java.util.TreeMap;

import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.SimpleBindings;

import jdk.nashorn.api.scripting.ScriptObjectMirror;

public class JSTest {
    public static ScriptEngine engine;
    private static String str;
    
    public static void main(String[] args) throws Exception {
        //獲取js引擎實例
        ScriptEngineManager sem = new ScriptEngineManager();
        engine=sem.getEngineByName("javascript");
        getJsValue();
        getObject();
        putValue();
        callJsFunction();
    }
    //該函數(shù)測試Java獲取JS變量值的能力
    public static void getJsValue() throws Exception{
        str = "  var msg='hello';          "
                + "  var number = 123;         "
                + "  var array=['A','B','C'];  "
                + "  var json={                "
                + "      'name':'pd',          "
                + "      'subjson':{           "
                + "           'subname':'spd'  "
                + "           ,'id':123        "
                + "           }                "
                + "      };                    ";
        //執(zhí)行語句
        engine.eval(str);
        str="msg+=' world';number+=5";
        //再次執(zhí)行
        engine.eval(str);
        //獲取js變量msg(String類型)
        System.out.println(engine.get("msg"));
        //獲取js變量msg(int類型)
        System.out.println(engine.get("number"));
        //獲取js變量array(數(shù)組)
        ScriptObjectMirror array=(ScriptObjectMirror) engine.get("array");
        //getSlot(int index)函數(shù)用于獲取下標(biāo)為index的值
        System.out.println(array.getSlot(0));
        //獲取js變量json(json類型)
        ScriptObjectMirror json=(ScriptObjectMirror) engine.get("json");
        //get(String key)函數(shù)用于鍵key的值
        System.out.println(json.get("name"));
        //獲取js變量subjson(嵌套json類型)
        ScriptObjectMirror subjson=(ScriptObjectMirror)json.get("subjson");
        System.out.println(subjson.get("subname"));
    }
    //該函數(shù)測試Java與js對象
    public static void getObject() throws Exception{
        str = "  var obj=new Object();     "
                + "  obj.info='hello world';   "
                + "  obj.getInfo=function(){   "
                + "        return this.info;   "
                + "  };                        ";
        engine.eval(str);
        //獲取對象
        ScriptObjectMirror obj=(ScriptObjectMirror) engine.get("obj");
        //輸出屬性
        System.out.println(obj.get("info"));
        System.out.println(obj.get("getInfo"));
        str="obj.getInfo()";
        //執(zhí)行方法
        System.out.println(engine.eval(str));
    }
    //java將變量導(dǎo)入js腳本
    public static void putValue() throws Exception{
        str="Math.pow(a,b)";
        Map<String, Object>input=new TreeMap<>();
        input.put("a",2);
        input.put("b",8);
        System.out.println(engine.eval(str,new SimpleBindings(input)));
    }
    //調(diào)用js函數(shù)
    public static void callJsFunction() throws Exception{
        engine.eval("function add (a, b) {return a+b; }");
        Invocable jsInvoke = (Invocable) engine;
        Object res = jsInvoke.invokeFunction("add", new Object[] { 10, 5 });
        System.out.println(res);
    }
 
}
  • JDK11之后版本
package io.icefox;

import org.openjdk.nashorn.api.scripting.ScriptObjectMirror;

import java.util.Map;
import java.util.TreeMap;

import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.SimpleBindings;


public class JSTest {
    public static ScriptEngine engine;
    private static String str;
    //該函數(shù)測試Java獲取JS變量值的能力
    public static void getJsValue() throws Exception{
        str = "  var msg='hello';          "
                + "  var number = 123;         "
                + "  var array=['A','B','C'];  "
                + "  var json={                "
                + "      'name':'pd',          "
                + "      'subjson':{           "
                + "           'subname':'spd'  "
                + "           ,'id':123        "
                + "           }                "
                + "      };                    ";
        //執(zhí)行語句
        engine.eval(str);
        str="msg+=' world';number+=5";
        //再次執(zhí)行
        engine.eval(str);
        //獲取js變量msg(String類型)
        System.out.println(engine.get("msg"));
        //獲取js變量msg(int類型)
        System.out.println(engine.get("number"));
        //獲取js變量array(數(shù)組)
        ScriptObjectMirror array=(ScriptObjectMirror) engine.get("array");
        //getSlot(int index)函數(shù)用于獲取下標(biāo)為index的值
        System.out.println(array.getSlot(0));
        //獲取js變量json(json類型)
        ScriptObjectMirror json=(ScriptObjectMirror) engine.get("json");
        //get(String key)函數(shù)用于鍵key的值
        System.out.println(json.get("name"));
        //獲取js變量subjson(嵌套json類型)
        ScriptObjectMirror subjson=(ScriptObjectMirror)json.get("subjson");
        System.out.println(subjson.get("subname"));
    }
    //該函數(shù)測試Java與js對象
    public static void getObject() throws Exception{
        str = "  var obj=new Object();     "
                + "  obj.info='hello world';   "
                + "  obj.getInfo=function(){   "
                + "        return this.info;   "
                + "  };                        ";
        engine.eval(str);
        //獲取對象
        ScriptObjectMirror obj=(ScriptObjectMirror) engine.get("obj");
        //輸出屬性
        System.out.println(obj.get("info"));
        System.out.println(obj.get("getInfo"));
        str="obj.getInfo()";
        //執(zhí)行方法
        System.out.println(engine.eval(str));
    }
    //java將變量導(dǎo)入js腳本
    public static void putValue() throws Exception{
        str="Math.pow(a,b)";
        Map<String, Object>input=new TreeMap<>();
        input.put("a",2);
        input.put("b",8);
        System.out.println(engine.eval(str,new SimpleBindings(input)));
    }
    //調(diào)用js函數(shù)
    public static void callJsFunction() throws Exception{
        engine.eval("function add (a, b) {return a+b; }");
        Invocable jsInvoke = (Invocable) engine;
        Object res = jsInvoke.invokeFunction("add", new Object[] { 10, 5 });
        System.out.println(res);
    }
    public static void main(String[] args) throws Exception {
        //獲取js引擎實例
        ScriptEngineManager sem = new ScriptEngineManager();
        engine=sem.getEngineByName("javascript");
        getJsValue();
        getObject();
        putValue();
        callJsFunction();
    }
}
  • JDK11之后移除了
jdk.nashorn.api.scripting.ScriptObjectMirror

使用JDK15之后版本需要添加maven依賴

使用org.openjdk.nashorn.api.scripting.ScriptObjectMirror

  <dependency>
      <groupId>org.openjdk.nashorn</groupId>
      <artifactId>nashorn-core</artifactId>
      <version>15.3</version>
  </dependency>

其他

其他的還可以對 Js 進(jìn)行編譯、在 Js 中調(diào)用 Java 的代碼,但感覺用的不多,最常用的還是 Java 調(diào)用 Js 的方法

總結(jié)

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java基于Runtime調(diào)用外部程序出現(xiàn)阻塞的解決方法

    Java基于Runtime調(diào)用外部程序出現(xiàn)阻塞的解決方法

    這篇文章主要介紹了Java基于Runtime調(diào)用外部程序出現(xiàn)阻塞的解決方法,是一個非常實用的技巧,需要的朋友可以參考下
    2014-09-09
  • java集合Collection常用方法解讀

    java集合Collection常用方法解讀

    這篇文章主要介紹了java集合Collection常用方法解讀,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • java開發(fā)ExecutorService監(jiān)控實現(xiàn)示例詳解

    java開發(fā)ExecutorService監(jiān)控實現(xiàn)示例詳解

    這篇文章主要為大家介紹了java開發(fā)ExecutorService監(jiān)控實現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-07-07
  • 詳解Spring Security的formLogin登錄認(rèn)證模式

    詳解Spring Security的formLogin登錄認(rèn)證模式

    對于一個完整的應(yīng)用系統(tǒng),與登錄驗證相關(guān)的頁面都是高度定制化的,非常美觀而且提供多種登錄方式。這就需要Spring Security支持我們自己定制登錄頁面,也就是本文給大家介紹的formLogin模式登錄認(rèn)證模式,感興趣的朋友跟隨小編一起看看吧
    2019-11-11
  • Java基礎(chǔ)之選擇結(jié)構(gòu)與循環(huán)結(jié)構(gòu)

    Java基礎(chǔ)之選擇結(jié)構(gòu)與循環(huán)結(jié)構(gòu)

    這篇文章主要介紹了Java基礎(chǔ)之選擇結(jié)構(gòu)與循環(huán)結(jié)構(gòu),文中有非常詳細(xì)的代碼示例,對正在學(xué)習(xí)java基礎(chǔ)的小伙伴們有非常好的幫助,需要的朋友可以參考下
    2021-04-04
  • Java通過調(diào)用FFMPEG獲取視頻時長

    Java通過調(diào)用FFMPEG獲取視頻時長

    這篇文章主要為大家詳細(xì)介紹了Java通過調(diào)用FFMPEG獲取視頻時長,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-04-04
  • 詳解Spring MVC4 純注解配置教程

    詳解Spring MVC4 純注解配置教程

    本篇文章主要介紹了Spring MVC4 純注解配置教程,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-04-04
  • IDEA2023.1.3安裝教程及下載(圖文)

    IDEA2023.1.3安裝教程及下載(圖文)

    最新變化是在IDEA?2023.1中,對新UI做出了大量改進(jìn),本文主要介紹了IDEA2023.1.3安裝教程及下載,具有一定的參考價值,感興趣的可以了解一下
    2023-10-10
  • idea、pycharm使用后占用C盤空間,修改安裝位置的方式

    idea、pycharm使用后占用C盤空間,修改安裝位置的方式

    這篇文章主要介紹了idea、pycharm使用后占用C盤空間,修改安裝位置的方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2025-05-05
  • Java代碼實現(xiàn)從HTML文件中提取純文本內(nèi)容

    Java代碼實現(xiàn)從HTML文件中提取純文本內(nèi)容

    在?Java?數(shù)據(jù)處理、文本清洗、內(nèi)容解析等開發(fā)場景中,從?HTML?文件中剔除標(biāo)簽、樣式、腳本等冗余格式,提取核心純文本是高頻需求,下面我們就來看看如何使用Java實現(xiàn)從HTML文件中提取純文本內(nèi)容吧
    2026-04-04

最新評論

封丘县| 呼图壁县| 罗定市| 井研县| 司法| 缙云县| 仁布县| 隆化县| 东乌珠穆沁旗| 四川省| 衡东县| 武陟县| 海宁市| 谷城县| 蕲春县| 库车县| 新田县| 微山县| 密山市| 桦川县| 五家渠市| 伊通| 沭阳县| 库尔勒市| 喀什市| 滨海县| 紫金县| 巴南区| 闸北区| 剑阁县| 清水县| 长泰县| 会理县| 西城区| 阿拉善左旗| 黎川县| 阿鲁科尔沁旗| 汉沽区| 乌拉特中旗| 留坝县| 吉木萨尔县|