Java详解ScriptEngine接口动态执行JS脚本

 更新时间:2022年08月08日 11:10:09   作者:Cavewang  
ScriptEngine是基本接口,其方法必须在本规范的每个实现中完全起作用。这些方法提供基本脚本功能。 写入这个简单接口的应用程序可以在每个实现中进行最少的修改。 它包括执行脚本的方法,以及设置和获取值的方法

大多的方法描述都来自于jdk11API帮助文档,由于是机翻,可能有些难以理解,大家多多担待

简介

首先来看一下JDK11API文档中对ScriptEngine的描述

模块 java.scripting

软件包 javax.script

Interface ScriptEngin

public interface ScriptEngine

ScriptEngine是基本接口,其方法必须在本规范的每个实现中完全起作用。

这些方法提供基本脚本功能。 写入这个简单接口的应用程序可以在每个实现中进行最少的修改。 它包括执行脚本的方法,以及设置和获取值的方法。

值是两种类型的键/值对。 第一类对包括其密钥在本说明书中保留和定义的那些或由各个实现组成。 具有保留键的对中的值具有指定的含义。

另一种类型的对包括那些创建Java语言绑定的对,这些值通常由脚本中的相应键或它们的装饰形式表示。

Eval(String script)

eval方法有多个重载,本文只介绍最常用的Eval(String script)

描述

执行指定的脚本。

实例代码

    /**
     * ScriptEngine.eval()
     */
    public void jsEngineEvalTest() {
        ScriptEngineManager sem = new ScriptEngineManager();
        //查找并为给定的扩展创建ScriptEngine。也可用getEngineByName,查找并为给定名称创建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();
        }
    }

执行的脚本很简单,遍历输出了一个数组

结果如下所示:

index:0,value:1
index:1,value:2
index:2,value:3
index:3,value:4
index:4,value:5

Put() and Get()

描述

void put​(String key, Object value) : 设置ScriptEngine状态中的键/值对,可以创建用于执行脚本的Java语言绑定,也可以以其他方式使用,具体取决于是否保留键。

Object get​(String key) : 检索在此引擎状态下设置的值。 该值可能是其中之一是使用设置setValue或状态的其他值ScriptEngine ,取决于实施。

实例代码

    /**
     * ScriptEngine.put() and ScriptEngine.get()
     */
    public void jsEnginePutTest(){
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("javascript");
        //向engine中存值
        engine.put("str", "jsEnginePutTest");
        try {
            engine.eval("var output ='' ;for (i = 0; i <= str.length; i++) {  output = str.charAt(i) + output }");
        } catch (ScriptException e) {
            e.printStackTrace();
        }
        //从engine中取值
        String name = (String) engine.get("output");
        System.out.println("被翻转后的字符串:"+name);
    }

此处的js脚本是将str字符串进行翻转操作,结果如下

被翻转后的字符串:tseTtuPenignEsj

CompiledScript

描述

通过存储编译结果的类进行扩展。 状态可以以Java类,Java类文件或脚本语言操作码的形式存储。 脚本可以重复执行而无需重新分析。

我的理解:将ScriptEngine解析一段脚本的结果存起来,方便多次调用。但是使用时要先将ScriptEngine用Compilable接口强制转换,然后调用compile(String script)方法就能返回一个CompiledScript对象,下次使用的时候调用一下CompiledScript.eval()即可,以此可以省略每次使用脚本都要重新解析一遍的过程。

实例代码

    /**
     * CompiledScript
     */
    public void compiledScriptTest(){
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("javascript");
        //进行强制转换
        Compilable compilable = (Compilable) engine;
        String script = "print('CompiledScriptTest')";
        try {
        	//脚本解析结果存到JSFunction中,下次使用时用jsFunction.eval()即可
            CompiledScript jsFunction = compilable.compile(script);
            jsFunction.eval();
        } catch (ScriptException e) {
            e.printStackTrace();
        }
    }

此处js脚本只是进行一个简单的输出,结果如下:

CompiledScriptTest

Bindings

描述

没有找到对Bindings很准确的解释,这里写下查阅了很多码友的笔记后我的得出的结论,Bindings是一个用来存放数据的容器,它有3个层级,为Global级、Engine级和Local级,前2者通过ScriptEngine.getBindings()获得,是唯一的对象,而Local Binding由ScriptEngine.createBindings()获得,很好理解,每次都产生一个新的。Global对应到工厂,Engine对应到ScriptEngine,向这2者里面加入任何数据或者编译后的脚本执行对象,在每一份新生成的Local Binding里面都会存在。

实例代码

    /**
     * Bindings
     */
    public void jsEngineBindingsTest(){
        ScriptEngine engine = new ScriptEngineManager().getEngineByName("javascript");
        Compilable compilable = (Compilable) engine;
        Bindings bindings = engine.createBindings();
        String script = "function add(num1,num2){return num1+num2} add(a, b)";
        CompiledScript JSFunction = null;
        try {
            JSFunction = compilable.compile(script);
            //向bingdings中传入键值对
            bindings.put("a", 1);
            bindings.put("b", 2);
            //调用eval时将bindings也传入
            Object result = JSFunction.eval(bindings);
            System.out.println(result);
        } catch (ScriptException e) {
            e.printStackTrace();
        }
    }

此处脚本代码进行了一个简单的加法运算,结果如下:

3.0

到此这篇关于Java详解ScriptEngine接口动态执行JS脚本的文章就介绍到这了,更多相关Java ScriptEngine内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java全面分析面向对象之多态

    Java全面分析面向对象之多态

    多态就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量到底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定
    2022-04-04
  • 浅谈UUID生成的原理及优缺点

    浅谈UUID生成的原理及优缺点

    UUID是一套用于生成全局唯一标识符的标准,也被称为GUID (Globally Unique Identifier),通过使用UUID可以在分布式系统中生成唯一的 ID,UUID的生成方式有多种,本文将详细讲解 UUID 的生成原理、特性、实用场景以及优缺点
    2023-06-06
  • 详解Spring 拦截器流程及多个拦截器的执行顺序

    详解Spring 拦截器流程及多个拦截器的执行顺序

    这篇文章主要介绍了Spring 拦截器流程及多个拦截器的执行顺序的相关资料,帮助大家更好的理解和学习使用Spring框架,感兴趣的朋友可以了解下
    2021-05-05
  • linux用java -jar启动jar包缓慢的问题

    linux用java -jar启动jar包缓慢的问题

    这篇文章主要介绍了linux用java -jar启动jar包缓慢的问题,具有很好的参考价值,希望对大家有所帮助,
    2023-09-09
  • Java的Spring框架的三种连接池的基本用法示例

    Java的Spring框架的三种连接池的基本用法示例

    这篇文章主要介绍了Java的Spring框架的三种连接池的基本用法示例,Spring框架是Java下注明的SSH三大web开发框架之一,需要的朋友可以参考下
    2015-11-11
  • springboot整合SSE的项目实践

    springboot整合SSE的项目实践

    SSE是一种可以主动从服务端推送消息的技术,本文主要介绍了springboot整合SSE的项目实践,具有一定的参考价值,感兴趣的可以了解一下
    2023-09-09
  • 如何搭建一个完整的Java开发环境

    如何搭建一个完整的Java开发环境

    这篇文章主要教大家如何搭建一个完整的Java开发环境,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-11-11
  • Spring Boot使用过滤器Filter过程解析

    Spring Boot使用过滤器Filter过程解析

    这篇文章主要介绍了Spring Boot使用过滤器Filter过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-01-01
  • MyBatis批量更新(update foreach)报错问题

    MyBatis批量更新(update foreach)报错问题

    这篇文章主要介绍了MyBatis批量更新(update foreach)报错问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-08-08
  • 23种设计模式(3) java原型模式

    23种设计模式(3) java原型模式

    这篇文章主要为大家详细介绍了23种设计模式之java原型模式,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-11-11

最新评论