【技巧】ScriptEngine--Java動態(tài)執(zhí)行JS Javascript腳本(可調用java的方法) 擴展性很強
JS引擎Nashorn
開發(fā)手冊
Java Platform, Standard Edition Nashorn User's Guide, Release 14
用戶手冊
Nashorn User's Guide (oracle.com)
https://docs.oracle.com/en/java/javase/14/nashorn/
甚至可以讓前端來寫后端業(yè)務代碼
可以通過js調用java的方法, 通過傳參的方式將java對象傳給js
可以單獨寫個JsUtil 讓js來調用 里邊寫常用的方法 統(tǒng)一管理
也可以直接通過Spring去拿到對應的實例
JDK9+ 需要單獨依賴
<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
<version>3.6</version>
</dependency>
相關工具類
<!-- hutool工具類-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.20</version>
</dependency>
代碼例子
package com.xx.study.Script.Javascript;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.hutool.script.ScriptUtil;
import org.junit.jupiter.api.Test;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import java.util.HashMap;
import java.util.Map;
public class JavascriptDemo {
private final static String js = """
function test(){
var a = 1;
var b = 3;
return a+b;
}
function 加法(a, b){
return a+b;
}
function MAP傳參(map){
return map['a']+map['b'];
}
function 獲取json(){
var json = {
最大值:10,
最小值:3,
說明:'測試js方法'
};
return JSON.stringify(json);
}
""";
/**
* 可以考慮結合業(yè)務做成動態(tài)參數(shù)等
* 將js存到數(shù)據(jù)庫進行管理 也可以維護到redis緩存等
* @param args
*/
public static void main(String[] args) {
Object test結果 = ScriptUtil.invoke(js, "test");
System.out.println("test:================================");
//4.0
System.out.println(test結果);
Object 加法結果 = ScriptUtil.invoke(js, "加法", 100, 200);
System.out.println("加法:==============================");
//300.0
System.out.println(加法結果);
Map<String, Integer> MAP參數(shù) = new HashMap<>();
MAP參數(shù).put("a", 500);
MAP參數(shù).put("b", 500);
Object MAP傳參結果 = ScriptUtil.invoke(js, "MAP傳參", MAP參數(shù));
System.out.println("MAP傳參:======================================");
//1000.0
System.out.println(MAP傳參結果);
Object 獲取json結果 = ScriptUtil.invoke(js, "獲取json");
JSONObject entries = JSONUtil.parseObj(獲取json結果.toString());
System.out.println("獲取json:======================================");
//10
System.out.println(entries.getInt("最大值"));
//測試js方法
System.out.println(entries.getStr("說明"));
//{"最大值":10,"最小值":3,"說明":"測試js方法"}
System.out.println(entries);
}
/**
* ScriptEngine.eval()
*/
@Test
public void jsEngineEvalTest() {
ScriptEngineManager sem = new ScriptEngineManager();
//查找并為給定的擴展創(chuàng)建ScriptEngine。也可用getEngineByName,查找并為給定名稱創(chuàng)建ScriptEngine
ScriptEngine jsEngine = sem.getEngineByExtension("js");
try {
jsEngine.eval("var array = [1, 2, 3, 4, 5];for (var i = 0; i < array.length; i++) {print('index:' + i + ',value:' + array[i]);}");
} catch (ScriptException e) {
e.printStackTrace();
}
}
}
/**
* ScriptEngine.eval()
*/
@Test
public void jsEngineEvalTest() {
ScriptEngineManager sem = new ScriptEngineManager();
//查找并為給定的擴展創(chuàng)建ScriptEngine。也可用getEngineByName,查找并為給定名稱創(chuàng)建ScriptEngine
ScriptEngine jsEngine = sem.getEngineByExtension("js");
try {
jsEngine.eval("var array = [1, 2, 3, 4, 5];for (var i = 0; i < array.length; i++) {print('index:' + i + ',value:' + array[i]);}");
} catch (ScriptException e) {
e.printStackTrace();
}
}
通過js創(chuàng)建java對象
jjs> var HashMap = Java.type("java.util.HashMap")
jjs> var mapDef = new HashMap()
jjs> var map100 = new HashMap(100)
訪問類和實例成員
jjs> Java.type("java.lang.Math").PI
3.141592653589793
jjs> Java.type("java.lang.System").currentTimeMillis()
1375813353330
jjs> Java.type("java.util.Map").Entry
[JavaClass java.util.Map$Entry]
內部類也可以使用內部表示來訪問,其中美元符號 () 作為分隔符或點,這與 Java 一致:$
jjs> Java.type("java.util.Map$Entry")
[JavaClass java.util.Map$Entry]
jjs> Java.type("java.util.Map.Entry")
[JavaClass java.util.Map$Entry]
要調用實例方法或訪問對象的實例字段,請使用點運算符,類似于在 Java 中完成的方式。下面的示例演示如何在對象上調用該方法:toUpperCase()
String
jjs> var String = Java.type("java.lang.String")
jjs> var str = new String("Hello")
jjs> str
Hello
jjs> var upper = str.toUpperCase()
jjs> upper
HELLO
使用 JavaBeans
Nashorn 使您能夠將 JavaBeans 中的訪問器和突變器方法視為等效的 JavaScript 屬性。屬性的名稱是不帶 or 后綴的 JavaBean 方法的名稱,并以小寫字母開頭。get
set
例如,您可以使用屬性調用對象中的 and 方法,如下所示:getYear()
setYear()
java.util.Date
year
jjs> var Date = Java.type("java.util.Date")
jjs> var date = new Date()
jjs> date.year + 1900
2013
jjs> date.year = 2014 - 1900
114
jjs> date.year + 1900
2014
擴展 Java 類
您可以使用將 Java 類型作為第一個參數(shù)的函數(shù)和將方法實現(xiàn)(以 JavaScript 函數(shù)的形式)作為其他參數(shù)的函數(shù)來擴展類。Java.extend()
以下腳本擴展接口并使用它來構造新對象:java.lang.Runnable
java.lang.Thread
var Run = Java.type("java.lang.Runnable");
var MyRun = Java.extend(Run, {
run: function() {
print("Run in separate thread");
}
});
var Thread = Java.type("java.lang.Thread");
var th = new Thread(new MyRun());
訪問 Java 類
使用 Nashorn 訪問包和類有兩種方法:傳統(tǒng)方法是使用全局對象,推薦的方法是使用全局對象。本節(jié)介紹這兩種方法。Packages
Java
預定義的頂級對象使您能夠使用完全限定的名稱訪問 Java 包和類,就好像它們是對象的屬性一樣。以下示例演示如何訪問包及其類(如果位于類路徑中):Packages
Packages
MyPackage
MyClass
MyPackage.jar
jjs> Packages.MyPackage
[JavaPackage MyPackage]
jjs> Packages.MyPackage.MyClass
[JavaClass MyPackage.MyClass]
訪問標準 Java 包和類比訪問定制包和類更簡單。為方便起見,為每個標準 Java 包定義了全局對象:、、、 和 。它們具有與對象的屬性相對應的別名。下面的示例演示如何訪問包和類:com
edu
java
javax
org
Packages
java.lang
java.lang.System
jjs> java.lang
[JavaPackage java.lang]
jjs> typeof java.lang
object
jjs> java.lang.System
[JavaClass java.lang.System]
jjs> typeof java.lang.System
function
報錯
java.lang.NullPointerException: Script for [js] not support !
Cannot invoke "javax.script.ScriptEngine.eval(String)" because "jsEngine" is
項目中使用了?com.github.whvcse包的easy-captcha
?驗證碼依賴,升級至Jdk17后,驗證碼接口報錯:Cannot invoke "javax.script.ScriptEngine.eval(String)" because "engine" is null
,錯誤原因很明顯腳本引擎執(zhí)行腳本語句報錯,因為執(zhí)行引擎為空。查詢相關資料Jdk8自帶的JavaScript引擎?nashorn
?再升級到Jdk9后就被移除了,從而導致報錯
解決辦法:添加JavaScript引擎?nashorn
依賴
<dependency>
<groupId>org.openjdk.nashorn</groupId>
<artifactId>nashorn-core</artifactId>
<version>15.4</version>
</dependency>
動態(tài)代碼 預留js hook文章來源:http://www.zghlxwxcb.cn/news/detail-788576.html
通過js動態(tài)調整業(yè)務邏輯? 處理數(shù)據(jù)等? js代碼存到數(shù)據(jù)庫 或 緩存文章來源地址http://www.zghlxwxcb.cn/news/detail-788576.html
到了這里,關于【技巧】ScriptEngine--Java動態(tài)執(zhí)行JS Javascript腳本(可調用java的方法)的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!