1. 程式人生 > >Java8 Nashorn實現Java呼叫javascript程式碼

Java8 Nashorn實現Java呼叫javascript程式碼

1.從列印Hello World開始

Java8 引入Nashorn實現javascript呼叫,比如使用java執行一段js實現“Hello World”列印:

package com.iflytek.research.jsdemo;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

public class NashornTest {
    
    public static void main(String[] args) {
        // 載入nashorn執行引擎
        ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
        try {
            engine.eval("var str = 'Hello World';"
                    + "print(str);");
        } catch (ScriptException e) {
            e.printStackTrace();
        }
    }
    
}

上述程式碼成功列印了“Hello World”, 現實場景中,script程式碼大多來自檔案,編輯test.js

var str = 'Hello World';
print(str);

將java讀取方式改為從檔案載入

// 載入nashorn執行引擎
        ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
        try {
            FileReader scriptFile = new FileReader("test.js");
            engine.eval(scriptFile);
        } catch (ScriptException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

執行後,仍然能正常列印

2.傳遞引數給javascript程式碼

可以使用SimpleBindings類來實現引數傳遞,改寫test.js

var str = 'Hello ';
print(str + name);

上述程式碼name變數就可以使用SimpleBindings來傳遞,具體實現

// 載入nashorn執行引擎
        ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
        try {
            FileReader scriptFile = new FileReader("test.js");
            SimpleBindings simpleBindings = new SimpleBindings(); 
            simpleBindings.put("name", "Nashorn");
            engine.eval(scriptFile, simpleBindings);
        } catch (ScriptException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

再次執行程式碼 列印

Hello Nashorn

這個引數在js中是全域性可見的,比如將它放到函式作用域中也可以正常讀取到

var good = function() {
    return name + ' is Good';
}
print(good());

列印結果

Nashorn is Good

指定呼叫的函式

在載入js檔案後,可以使用Invocable介面的invokeFunction方法, 修改js檔案

var good = function(name) {
    print(name + ' is Good');
}

在給函式傳參直接在invokeFunction方法新增引數即可,不再需要使用SimpleBindings

public static void main(String[] args) {
        // 載入nashorn執行引擎
        ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
        try {
            FileReader scriptFile = new FileReader("test.js");
            engine.eval(scriptFile);
            Invocable in = (Invocable) engine;
             in.invokeFunction("good","Nashorn");
        } catch (ScriptException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
    }

如果要傳遞物件也是妥妥的

var good = function(person) {
    print( 'name: ' + person.name);
}
Map<String,Object> person = new HashMap<>();
            person.put("name", "nashorn");
             in.invokeFunction("good",person);

獲取js返回值