Javaでjavascriptコードを実行する(一)
41538 ワード
プロジェクト要件:
お客様は、温度が高すぎると警告されたり、デバイスのプロパティが変化したりするなど、ルールに基づいて警告注意の変化などの情報を生成するルールを動的に記入します.しかし、お客様の判断は、これらの変化のルールが絶えず変化しているため、動的な入力が必要です.jvmは複数の動的言語をサポートしており、javaからJavaScript、Groovy、Ruby、Scheme、Haskellが作成したスクリプトを呼び出すことができ、言語の流行度を考慮してjsを選択しました.
インスタンスコード:
このコードは主に『大忙しの人に読むJave SE 9コアテクノロジー』第14章から来ており、コンパイルとスクリプトです.
まず、スクリプト実行エンジンを取得する必要があります.スクリプト実行エンジンは、特定の言語でスクリプトを実行するクラスライブラリです.jvm起動はい、これらのスクリプトエンジンが起動します.new Script EngineManager()でスクリプトエンジンマネージャを取得し、getEngineByName(...)メソッドで取得した対応するスクリプトエンジン、JavaScript言語を使用するため、パラメータ「nashorn」を使用してScript Engineを取得します.
注意:There is no requirement for a given Java Virtual Machine(JVM)to include any engines by default,but the Oracle JVM(Java 6 and later)includes a JavaScript engine,based on Rhino version 1.6 R 2 before Java 8,and Nashorn since Java 8.
Java 8より前のjvmでJavaScriptのScript Engine name Rhino、後にnashorn
公式ドキュメント:https://jcp.org/aboutJava/communityprocess/final/jsr223/index.html Scripting for the JavaTM Platform
説明:1、demo.jsの内容はvar age=20です.2,demo 2.js内容はfunction myAdd(a,b){var sum=a+b;return sum;}
実行効果:
お客様は、温度が高すぎると警告されたり、デバイスのプロパティが変化したりするなど、ルールに基づいて警告注意の変化などの情報を生成するルールを動的に記入します.しかし、お客様の判断は、これらの変化のルールが絶えず変化しているため、動的な入力が必要です.jvmは複数の動的言語をサポートしており、javaからJavaScript、Groovy、Ruby、Scheme、Haskellが作成したスクリプトを呼び出すことができ、言語の流行度を考慮してjsを選択しました.
インスタンスコード:
このコードは主に『大忙しの人に読むJave SE 9コアテクノロジー』第14章から来ており、コンパイルとスクリプトです.
まず、スクリプト実行エンジンを取得する必要があります.スクリプト実行エンジンは、特定の言語でスクリプトを実行するクラスライブラリです.jvm起動はい、これらのスクリプトエンジンが起動します.new Script EngineManager()でスクリプトエンジンマネージャを取得し、getEngineByName(...)メソッドで取得した対応するスクリプトエンジン、JavaScript言語を使用するため、パラメータ「nashorn」を使用してScript Engineを取得します.
注意:There is no requirement for a given Java Virtual Machine(JVM)to include any engines by default,but the Oracle JVM(Java 6 and later)includes a JavaScript engine,based on Rhino version 1.6 R 2 before Java 8,and Nashorn since Java 8.
Java 8より前のjvmでJavaScriptのScript Engine name Rhino、後にnashorn
公式ドキュメント:https://jcp.org/aboutJava/communityprocess/final/jsr223/index.html Scripting for the JavaTM Platform
package com.yq.js;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.experimental.var;
import lombok.extern.slf4j.Slf4j;
import lombok.extern.java.Log;
import javax.script.Bindings;
import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import java.io.File;
import java.io.Reader;
import java.io.StringWriter;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
/**
* Simple to Introduction
* className: JavaJSDemo
*
* @author EricYang
* @version 2018/12/22 9:51
*/
@Slf4j
public class JavaJSDemo {
private static final String JS_ENGINE_NAME= "nashorn";
private final ScriptEngineManager sem = new ScriptEngineManager();
private final ScriptEngine engine = sem.getEngineByName(JS_ENGINE_NAME);
public static void main(String[] args) {
JavaJSDemo demo = new JavaJSDemo();
demo.bindingDemo();
demo.reDirectIODemo();
demo.invokeFunctionDemo();
demo.invokeFunctionByFileDemo();
}
public void bindingDemo() {
try {
engine.put("msg", "hello world!");
Object result = engine.eval("msg");
log.info("result=" + result);
engine.put("k", 20);
result = engine.eval("k + 1");
log.info("result=" + result);
result = engine.eval("n = 1738");
log.info("result=" + result);
result = engine.get("n");
log.info("result=" + result);
Bindings scope = engine.createBindings();
scope.put("key", " ");
result = engine.eval("key + ' '", scope);
log.info("result=" + result);
}
catch (ScriptException se) {
log.warn("binding demo exception.", se);
}
}
public void reDirectIODemo() {
log.info("--- redirect IO ---" );
try {
StringWriter writer = new StringWriter();
engine.getContext().setWriter(writer);
engine.put("msg", "hello world!");
// print writer
Object result = engine.eval("print(msg)");
log.info("result=" + result);
log.info("result=" + writer.toString());
//js java System.out.println
result = engine.eval("java.lang.System.out.println(msg)");
log.info("result=" + result);
log.info("result=" + writer.toString());
}
catch (ScriptException se) {
log.warn("binding demo exception.", se);
}
}
public boolean invokeFunctionDemo() {
log.info("--- invokeFunction ---" );
boolean result = true;
try {
engine.put("msg", "hello world!");
String str = "var user = {name:' ',age:18,city:[' ',' ']};";
engine.eval(str);
log.info("Get msg={}", engine.get("msg"));
//
engine.eval("var sum = eval('1 + 2 + 3*4');");
// js eval
log.info("get sum={}", engine.get("sum"));
JSONObject msg = new JSONObject();
msg.put("temperature", 125);
msg.put("humidity", 20);
msg.put("voltage", 220);
msg.put("electricity", 13);
JSONObject metadata = new JSONObject();
metadata.put("deviceName", " 01");
metadata.put("contacts", " ");
JSONObject msgType = new JSONObject();
//msgType.put("type", "deviceTelemetryData");
msgType.put("type", "deviceTelemetryData1");
//
String func = "var result = true; \r
" +
"if (msgType.type = 'deviceTelemetryData') { \r
" +
" if (msg.temperature >0 && msg.temperature < 33) {
result = true ;}
" +
" else {
result = false;}
" +
"} else {
result = false;
" +
" var errorMsg = msgType.type + ' is not deviceTelemetryData';
" +
" print(msgType.type)
}
" +
"return result";
log.info("func = {}", func);
engine.eval("function filter(msg, metadata, msgType){ " + func + "}");
// js
Invocable jsInvoke = (Invocable) engine;
Object obj = jsInvoke.invokeFunction("filter", msg, metadata, msgType);
// ,
log.info("function result={}", obj);
result = (Boolean)obj;
}
catch(Exception ex) {
log.warn("exception", ex);
result = false;
}
return result;
}
public int invokeFunctionByFileDemo() {
log.info("--- invokeFunction ---" );
int result = 0;
try {
log.info("Current dir={}", System.getProperty("user.dir"));
//\AkkaDemo\src\main\resources\demo.js
File file = new File("./AkkaDemo/src/main/resources/demo.js");
Reader reader = Files.newBufferedReader(file.toPath(), Charset.defaultCharset());
engine.put("user", "{name:' ',age:18,city:[' ',' ']};");
Object obj = engine.eval(reader);
log.info("get age={}", engine.get("age"));
log.info("function result={}", obj);
URL resource = this.getClass().getClassLoader().getResource("demo2.js");
FileReader fileReader = new FileReader(resource.getPath());
engine.eval(fileReader);
// js
Invocable jsInvoke = (Invocable)engine;
obj = jsInvoke.invokeFunction("myAdd", 1, 2);
log.info("myAdd obj={}", obj);
}
catch(Exception ex) {
log.warn("exception", ex);
}
return result;
}
}
説明:1、demo.jsの内容はvar age=20です.2,demo 2.js内容はfunction myAdd(a,b){var sum=a+b;return sum;}
実行効果:
11:34:26.170 [main] INFO com.yq.js.JavaJSDemo - result=hello world!
11:34:26.186 [main] INFO com.yq.js.JavaJSDemo - result=21.0
11:34:26.195 [main] INFO com.yq.js.JavaJSDemo - result=1738
11:34:26.195 [main] INFO com.yq.js.JavaJSDemo - result=1738
11:34:26.205 [main] INFO com.yq.js.JavaJSDemo - result=
11:34:26.205 [main] INFO com.yq.js.JavaJSDemo - --- redirect IO ---
11:34:26.212 [main] INFO com.yq.js.JavaJSDemo - result=null
11:34:26.213 [main] INFO com.yq.js.JavaJSDemo - result=hello world!
hello world!
11:34:26.253 [main] INFO com.yq.js.JavaJSDemo - result=null
11:34:26.253 [main] INFO com.yq.js.JavaJSDemo - result=hello world!
11:34:26.253 [main] INFO com.yq.js.JavaJSDemo - --- invokeFunction ---
11:34:26.261 [main] INFO com.yq.js.JavaJSDemo - Get msg=hello world!
11:34:26.272 [main] INFO com.yq.js.JavaJSDemo - get sum=15
11:34:26.280 [main] INFO com.yq.js.JavaJSDemo - func = var result = true;
if (msgType.type = 'deviceTelemetryData') {
if (msg.temperature >0 && msg.temperature < 33) {
result = true ;}
else {
result = false;}
} else {
result = false;
var errorMsg = msgType.type + ' is not deviceTelemetryData';
print(msgType.type)
}
return result
11:34:26.317 [main] INFO com.yq.js.JavaJSDemo - function result=false
11:34:26.317 [main] INFO com.yq.js.JavaJSDemo - --- invokeFunction ---
11:34:26.317 [main] INFO com.yq.js.JavaJSDemo - Current dir=D:\E\workspaceGitub\springboot
11:34:26.328 [main] INFO com.yq.js.JavaJSDemo - get age=20
11:34:26.328 [main] INFO com.yq.js.JavaJSDemo - function result=null
11:34:26.334 [main] INFO com.yq.js.JavaJSDemo - myAdd obj=3.0
Process finished with exit code 0