spring 或者 java执行JavaScript脚本方式

简单示例

public static void test10(){
        // 创建JavaScript引擎
        ScriptEngine jsEngine = new ScriptEngineManager().getEngineByName("js");
//        ScriptEngine jsEngine = new ScriptEngineManager().getEngineByExtension("js");
//        ScriptEngine jsEngine = new ScriptEngineManager().getEngineByMimeType("text/javascript");
        // 方式一,默认设置变量
        jsEngine.put("hello", "jack");
        // 方式二,使用binding设置变量
        SimpleBindings bindings = new SimpleBindings();
        bindings.put("hello","world");
        jsEngine.setBindings(bindings, ScriptContext.GLOBAL_SCOPE);
        // 方式三,使用Context设置变量
        ScriptContext scriptContext = jsEngine.getContext();
        scriptContext.setAttribute("hello", "polo", ScriptContext.ENGINE_SCOPE);
        try {
            // 方式一,直接调用
            jsEngine.eval("print(hello)");
            // 方式二,编译调用(需要重复调用,建议先编译后调用)
            if (jsEngine instanceof Compilable){
                CompiledScript compileScript = ((Compilable) jsEngine).compile("print(hello)");
                if (compileScript != null){
                    for (int i = 0; i < 10; i++) {
                        compileScript.eval();
                    }
                }
            }
            Invocable invocable = ((Invocable)jsEngine);
            // 方式三,使用JavaScript中的顶层方法
            jsEngine.eval("function greet(name) { print('Hello, ' + name); } ");
            invocable.invokeFunction("greet", "tom");
            // 方式四,使用某个对象的方法
            jsEngine.eval("var obj = { getGreeting: function(name){ return 'hello, ' + name; } } ");
            Object obj = jsEngine.get("obj");
            Object result = invocable.invokeMethod(obj, "getGreeting", "kitty");
            System.out.println(result);
            // 方法五, 指定脚本中的方法为Java接口的实现
            jsEngine.eval("function getGreeting(name) { return 'Hello, ' + name; } ");
            Greet greet = invocable.getInterface(Greet.class);
            String result2 = greet.getGreeting("Alex");
            System.out.println(result2);
        } catch (ScriptException | NoSuchMethodException e) {
            e.printStackTrace();
        }
    }

相关测试Demo

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import javax.script.Bindings;
import javax.script.Invocable;
import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.SimpleScriptContext;

import org.junit.Test;


public class JavaScriptFunction {

    @Test
    public void print() throws Exception{
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("JavaScript");
        engine.eval("print('hello word!!')");
    }
    
    @Test
    public void obj() throws Exception {
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("JavaScript");
        StringBuffer script = new StringBuffer();
        script.append("var obj = new Object();");
        script.append("obj.hello = function(name){print('hello, '+name);}");
        //执行这段script脚本
        engine.eval(script.toString());
        // javax.script.Invocable 是一个可选的接口
        // 检查你的script engine 接口是否已实现!
        // 注意:JavaScript engine实现了Invocable接口
        Invocable inv = (Invocable) engine;
        // 获取我们想调用那个方法所属的js对象
        Object obj = engine.get("obj");
        // 执行obj对象的名为hello的方法
        inv.invokeMethod(obj, "hello", "Script Method !!" );
    }
    
    @Test
    public void file() throws Exception{
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("JavaScript");
        engine.eval(new java.io.FileReader(new File("F:/test/test.js")));
        Invocable inv = (Invocable) engine;
        Object obj = engine.get("obj");
        inv.invokeMethod(obj, "name", "知道了" );
    }
    
    
    /**
     * 脚本变量
     * @throws Exception 
     */
    @Test
    public void scriptVar() throws Exception{
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("JavaScript");
        File file = new File("F:/test/test.txt");
        //将File对象f直接注入到js脚本中并可以作为全局变量使用
        engine.put("files", file);
        engine.eval("print(files.getPath());print(files.getName());");
    }
    
    /**
     *  使用Script实现java接口
     * @throws Exception 
     */
    public void runnableImpl() throws Exception{
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("JavaScript");
        
        // String里定义一段JavaScript代码脚本
        String script = "function run() { print('run called'); }";
        // 执行这个脚本
        engine.eval(script);
        
        // 从脚本引擎中获取Runnable接口对象(实例). 该接口方法由具有相匹配名称的脚本函数实现。
        Invocable inv = (Invocable) engine;
        // 在上面的脚本中,我们已经实现了Runnable接口的run()方法
        Runnable runnable = inv.getInterface(Runnable.class);
        
        // 启动一个线程运行上面的实现了runnable接口的script脚本
        Thread thread = new Thread(runnable);
        thread.start();
    }
    
    /**
     * 脚本引擎的多个scope
     * @throws Exception 
     */
    @Test
    public void multiScopes() throws Exception{
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("nashorn");
        // 打印全局变量 "x"
        engine.put("x", "hello word!!");
        engine.eval("print(x);");
        // 上面的代码会打印"hello word!!"
        
        // 现在,传入另一个不同的script context
        ScriptContext context = new SimpleScriptContext();
        //新的Script context绑定ScriptContext的ENGINE_SCOPE
        Bindings bindings = context.getBindings(ScriptContext.ENGINE_SCOPE);
        
        // 增加一个新变脸到新的范围 engineScope 中
        bindings.put("x", "word hello!!");
        // 执行同一个脚本 - 但这次传入一个不同的script context
        engine.eval("print(x);", bindings);
        engine.eval("print(x);");
    }
    
    
    
    public static void main(String[] args) throws Exception {
        new JavaScriptFunction().runnableImpl();
        
        List list = new ArrayList();
        list.add("1");
        list.add("1");
        list.add("1");
        
        for (Object object : list) {
            System.out.println(object);
        }
        
    }
}
View Code

常见问题

  •  Nashorn engine is planned to be removed from a future JDK release

pom依赖

<properties>
        <graalvm.version>21.1.0</graalvm.version>
    </properties>
    <dependencies>

<!--javascript运行环境-->
        <dependency>
            <groupId>org.graalvm.sdk</groupId>
            <artifactId>graal-sdk</artifactId>
            <version>${graalvm.version}</version>
        </dependency>
        <dependency>
            <groupId>org.graalvm.js</groupId>
            <artifactId>js</artifactId>
            <version>${graalvm.version}</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.graalvm.js</groupId>
            <artifactId>js-scriptengine</artifactId>
            <version>${graalvm.version}</version>
        </dependency>
        <!--javascript end-->
</dependencies>

使用方法

ScriptEngineManager manager = new ScriptEngineManager();
            ScriptEngine engine = manager.getEngineByName("graal.js");

 

posted @ 2022-06-08 16:25  浅笑19  阅读(1888)  评论(0编辑  收藏  举报