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

目录
  • 简介
  • Eval(String script)
    • 描述
    • 实例代码
  • Put() and Get()
    • 描述
    • 实例代码
  • CompiledScript
    • 描述
    • 实例代码
  • Bindings
    • 描述
    • 实例代码

大多的方法描述都来自于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内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Java动态脚本Groovy获取Bean技巧

    目录 一.使用BeanFactoryPostProcessor注入Bean: 第一步:创建实现SpringUtils 接口工具(组件)来获取spring bean 第二步:创建Groovy脚本装载类,动态解析脚本为Class 第三步:读取脚本内容,执行脚本 第四步:在resources目录下创建.groovy文件 第五步:实例化脚本,执行方法  二.使用ApplicationContext注入Bean 第一步:修改项目启动类,获得ApplicationContext 第二步:修改resource

  • Java使用ScriptEngine动态执行代码(附Java几种动态执行代码比较)

    引言 在Java项目中,或多或少我们有动态执行代码的需求,比如: 系统中有一个规则验证需求,但规则经常改变 代码热更新,热修复 笔者也在目前参与的一个项目中遇到了动态执行代码的需求:项目需要一个自动审核模块,但是审核规则根据相关书面文件制定,如果写死在.java文件里,那么当新的书面文件下发时,就要系统停机更新系统,然后才能继续使用,其中存在着很多不稳定因素,也很麻烦.因此在设计上就有动态执行代码的需求.好在这个需求只是审核一个表单,并没有对系统的操作和IO操作,输入参数也很固定. 笔者上网查阅

  • Java动态脚本Groovy

    目录 1.Groovy特性 2.核心涉及 3.Java与Groovy转换 第一步:引入Groovy依赖 第二步:创建interface接口声明方法 第三步:在resources目录下创建.groovy文件 第四步:创建Groovy脚本装载类,动态解析脚本为Class 第五步:读取脚本内容,执行脚本 4.Groovy特性验证 第一步:将之前Groovy脚本数据修改.存于数据库表中,动态加载脚本 第二步:数据库表中:添加.查询Groovy脚本,动态加载执行 第三步:多次修改表数据值,查看执行结果 5

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

    目录 简介 Eval(String script) 描述 实例代码 Put() and Get() 描述 实例代码 CompiledScript 描述 实例代码 Bindings 描述 实例代码 大多的方法描述都来自于jdk11API帮助文档,由于是机翻,可能有些难以理解,大家多多担待 简介 首先来看一下JDK11API文档中对ScriptEngine的描述 模块 java.scripting 软件包 javax.script Interface ScriptEngin public inter

  • Java 详解循环屏障CyclicBarrier如何实现多线程分段等待执行完成

    前言 工作中是否有这样的场景,多个线程任务,如果所有线程完成到某个阶段,你希望知道所有线程均完成该阶段.当然你使用线程计数可以实现,只是不够优雅. 所以我即:Java 多线程等待优雅的实现方式之Phaser同步屏障 之后再提供一个循环屏障,CyclicBarrier,更优雅的实现工具. Maven依赖 可以依赖,也可以不依赖,只是代码要稍微多一些,最好添加. <dependency> <groupId>org.projectlombok</groupId> <ar

  • Java执行JS脚本工具

    Java 执行 JS 脚本工具 用途:为了便于系统扩展,提供了 JS 脚本的功能,可以通过在系统中执行脚本来获得更复杂的功能. 例如:系统提供了一个接口,这个接口不必非的有实现类,而是可以通过JS来实现这个接口的方法,在运行时载入JS脚本去实现.只要能融会贯通,可用的地方还是很多的. 先看最基础的一个工具类 实际上有这么一个工具类就足够了,后面讲的例子也是基于这个工具类的. 这段代码的原理: 由于在 Java 的 javascript 引擎中,常用的List,Map等复杂对象的 属性值 不能在

  • Java详解线上内存暴涨问题定位和解决方案

    前因: 因为REST规范,定义资源获取接口使用GET请求,参数拼接在url上. 如果按上述定义,当参数过长,超过tomcat默认配置 max-http-header-size :8kb 会报一下错误信息: Request header is too large 可以修改springboot配置,调整请求头大小 server: max-http-header-size: xxx 后果: 如果max-http-header-size设置过大,会导致接口吞吐下降,jvm oom,内存泄漏. 因为tom

  • Java 详解如何获取网络接口信息

    前言 查看本机的网络接口信息,本文有详细的介绍哦. 代码 不废话,上代码. package com.hy.csdn.tools; import java.net.InetAddress; import java.net.NetworkInterface; import java.net.SocketException; import java.util.Enumeration; /** * @Program: hy-utils @ClassName: StuNetworkInterface @A

  • Java 详解Collection集合之ArrayList和HashSet

    目录 Collection List ArrayList Set HashSet ArrayList和HashSet的区别 泛型 Collection Collection接口被List接口和Set接口继承 本章只介绍常用的集合 List ArrayList是List接口的实现类 ArrayList ArrayList 类是一个可以动态修改的数组,与普通数组的区别就是它是没有固定大小的限制,我们可以添加或删除元素. ArrayList 继承了 AbstractList ,并实现了 List 接口

  • 详解PHP接口签名验证

    目录 概览 常用验证 单向散列加密 对称加密 非对称加密 密钥安全管理 接口调试工具 在线接口文档 扩展 小结 概览 在设计签名验证的时候,一定要满足以下几点: 可变性:每次的签名必须是不一样的. 时效性:每次请求的时效性,过期作废. 唯一性:每次的签名是唯一的. 完整性:能够对传入数据进行验证,防止篡改. 下面主要分享一些工作中常用的加解密的方法. 常用验证 举例:/api/login?username=xxx&password=xxx&sign=xxx 发送方和接收方约定一个加密的盐值

  • Java 详解Collection集合之ArrayList和HashSet

    目录 Collection List ArrayList Set HashSet ArrayList和HashSet的区别 泛型 Collection Collection接口被List接口和Set接口继承 本章只介绍常用的集合 List ArrayList是List接口的实现类 ArrayList ArrayList 类是一个可以动态修改的数组,与普通数组的区别就是它是没有固定大小的限制,我们可以添加或删除元素. ArrayList 继承了 AbstractList ,并实现了 List 接口

  • Java详解表格的创建与使用流程

    目录 Java 的表格 JTable的构造函数 表格的创建 小结 Java 的表格 表格是一个由多行,多列组成的二维显示区.Swing的JTable以及相关类提供了对这种表格的支持,程序既可以使用简单的代码创建出表格来显示二维数据,也可以开发出功能丰富的表格,还可以为表格制定各种显示外观,编辑特性. JTable的构造函数 方法描述 功能说明 JTable() 建立一个新的JTable,并使用系统默认的Model JTable(int numRows,int numColumns) 建立一个具有

  • Java详解多线程协作作业之信号同步

    目录 一.信号同步 二.基于时间维度 1.CountDownLatch 2.CyclicBarrier 三.基于信号维度 一.信号同步 多线程很多时候是协作作业.比如4个线程对电商数据分季度统计,统计完成之后,再汇总.如何知道4个线程都执行完成呢,我们可以使用JDK1.5给我们提供的辅助类CountDownLatch( 减少计数).CyclicBarrier(循环栅栏).Semaphore(信号灯). 二.基于时间维度 1.CountDownLatch 多少个协作线程就初始化CountDownL

随机推荐