Java 脚本引擎的使用

news2024/10/7 14:28:05

1. 前言

Java 6 版本就已经引入了 Rhino 引擎用以支持脚本代码运行,而从 Java 8 开始 Nashorn 取代 Rhino 成为 Java 内嵌的 JavaScript 引擎。Nashorn 引擎允许开发人员将 JavaScript 代码嵌入到 Java 中执行,这个特性在复杂的配置系统中有比较大的应用价值,可以满足特定场景下的灵活性要求

以下示例代码可以列出所有脚本引擎工厂的相关属性,可以看到其支持的脚本引擎包括了 JavaScript 等

    public static void main(String[] args) {
        ScriptEngineManager manager = new ScriptEngineManager();
        manager.getEngineFactories().forEach(factory -> System.out.printf("Name: %s%n" +
                        "Version: %s%n" +
                        "Language name: %s%n" +
                        "Language version: %s%n" +
                        "Extensions: %s%n" +
                        "Mime types: %s%n" +
                        "Names: %s%n",
                factory.getEngineName(),
                factory.getEngineVersion(),
                factory.getLanguageName(),
                factory.getLanguageVersion(),
                factory.getExtensions(),
                factory.getMimeTypes(),
                factory.getNames()));
    }

在这里插入图片描述

2. 脚本引擎的使用

Java 脚本引擎 API 中最主要的是 ScriptEngineManager,开发者可以通过这个类获取当前 Java 版本所支持的所有脚本引擎,具体获取脚本引擎的方法有以下3种:

  1. 根据扩展名得到脚本引擎
     ScriptEngineManager manager = new ScriptEngineManager();
     // getEngineByExtension 的参数就是 Extensions:[js]中任一个
     ScriptEngine engine = manager.getEngineByExtension("js");
    
  2. 根据Mime类型得到脚本引擎
    ScriptEngineManager manager = new ScriptEngineManager();
    // getEngineByMimeType 的参数可以是 Mime types: [application/javascript, application/ecmascript, text/javascript, text/ecmascript]中的任一个
    ScriptEngine engine = manager.getEngineByMimeType("text/javascript");
    
  3. 根据名称得到脚本引擎
    ScriptEngineManager manager = new ScriptEngineManager();
    // getEngineByName 的参数可以是 Names: [js, rhino, JavaScript, javascript, ECMAScript, ecmascript] 
    // 中的任一个
    ScriptEngine engine = manager.getEngineByName("javascript");
    

2.1 脚本参数传递

脚本引擎除了简单的执行功能,还可以通过它向脚本中传递参数,同时也可以将脚本中的变量值取出来。这些功能要依靠 ScriptEngine#put()ScriptEngine#get() 方法,以下为代码示例

    public static void main(String[] args) {
        ScriptEngineManager manager = new ScriptEngineManager();
        // 获取javascript脚本引擎
        ScriptEngine engine = manager.getEngineByName("js");
        try {
            // 参数出入
            engine.put("name", "lucky");
            // 开始执行脚本
            engine.eval("var output ='' ;" +
                    "for (i = 0; i <= name.length; i++) {" +
                    "    output = name.charAt(i) + output" +
                    "}");
            // 得到output变量的值
            String name = (String) engine.get("output");
            System.out.printf("被翻转后的字符串:%s", name);
        } catch (Exception e) {
            System.err.println(e);
        }
    }

2.2 脚本编译

如我们所知,脚本解释执行的运行方式性能很低,但是不少脚本语言都支持编译功能,因此 Java 的脚本引擎也对编译进行了支持。如果某段脚本要运行多次的话,可以使用编译的方式将其转化为执行效率更高的形式,从而提高性能

具体做法是调用 ScriptEngine#compile() 方法进行脚本编译,不过只有实现了Compilable 接口的脚本引擎才可以进行编译,可参考以下示例

    public static void main(String[] args) {
        ScriptEngineManager manager = new ScriptEngineManager();
        // 得到javascript脚本引擎
        ScriptEngine engine = manager.getEngineByName("js");
        try {
            // 可编译的脚本,提高执行速度
            engine.put("counter", 0);
            // 判断这个脚本引擎是否支持编译功能
            if (engine instanceof Compilable) {
                Compilable compEngine = (Compilable) engine;
                CompiledScript script = compEngine.compile("function count() { " +
                        "    counter = counter +1; " +
                        "    return counter; " +
                        "};" +
                        "count();");
                System.out.printf("Counter: %s%n", script.eval());
                System.out.printf("Counter: %s%n", script.eval());
                System.out.printf("Counter: %s%n", script.eval());
            }
        } catch (Exception e) {
            System.err.println(e);
        }
    }

在这里插入图片描述

2.3 脚本动态调用

业务系统运行时通常需要将用户的输入入参执行函数,这就产生了脚本方法动态调用的需求。和编译一样,脚本引擎必须实现 Invocable 接口才可以动态调用脚本中的方法,具体可参考以下示例

    public static void main(String[] args) {
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("js");
        try {
            // 动态决定脚本调用
            String name = "nathan";
            if (engine instanceof Invocable) {
                engine.eval("function reverse(name) {" +
                        " var output =' ';" +
                        " for (i = 0; i <= name.length; i++) {" +
                        "     output = name.charAt(i) + output" +
                        " }" +
                        " return output;" +
                        "}");
                Invocable invokeEngine = (Invocable) engine;
                Object o = invokeEngine.invokeFunction("reverse", name);
                System.out.printf("翻转后的字符串:%s", o);
            }
        } catch (Exception e) {
            System.err.println(e);
        }
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/154288.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

javascript reduce()方法

相信挺多人对这个方法还是那么的陌生&#xff0c;其实也能理解&#xff0c;毕竟它能做到的事情还有其他的方法能做到。下面就说一下我个人的理解吧&#xff01;&#xff01;&#xff01;reduce()方法&#xff1a;用法&#xff1a;array.reduce(function(total,currentData,curr…

管理bug的工具

一、国内的bug管理软件&#xff1a; 1、禅道 禅道是第一款国产开源项目管理软件。它的核心管理思想基于敏捷方法scrum&#xff0c;内置了产品管理和项目管理&#xff0c;同时又根据国内研发现状补充了测试管理、计划管理、发布管理、文档管理、事务管理等功能。在一个软件中就…

nodejs+vue+element+eachers构建开源项目大型连续剧(5)前端请求封装,完成用户注册。

在前端项目开发中&#xff0c;一个好的请求封装可以给我们带来诸多便利&#xff0c;减少了代码重复&#xff0c;优化了问题处理等。那接下来我们一起学习一下怎么做到对一个请求的简单封装吧。主要通过对axios请求的二次封装&#xff0c;实现页面的请求以及必要的优化。 一、引…

Word处理控件Aspose.Words功能演示:在 C# 中将 Word DOC DOCX 转换为 Markdown

Aspose.Words 是一种高级Word文档处理API&#xff0c;用于执行各种文档管理和操作任务。API支持生成&#xff0c;修改&#xff0c;转换&#xff0c;呈现和打印文档&#xff0c;而无需在跨平台应用程序中直接使用Microsoft Word。此外&#xff0c; Aspose API支持流行文件格式处…

每个Java程序员都必须知道的四种负载均衡算法

前言 一般来说&#xff0c;我们在设计系统的时候&#xff0c;为了系统的高扩展性&#xff0c;会尽可能的创建无状态的系统&#xff0c;这样我们就可以采用集群的方式部署&#xff0c;最终很方便的根据需要动态增减服务器数量。但是&#xff0c;要使系统具有更好的可扩展性&…

【UE4 第一人称射击游戏】32-添加击杀AI的提示功能(使用到控件蓝图的动画功能)

上一篇&#xff1a;【UE4 第一人称射击游戏】31-更好的UI界面本篇效果&#xff1a;可以看到在击杀AI后&#xff0c;右上角有击杀提示信息步骤&#xff1a;新建一个控件蓝图命名为“KillPopup”双击打开“KillPopup”&#xff0c;拖入一个图像控件&#xff0c;锚点设置为右上角&…

RobotFramework测试库

在RF 测试库里面&#xff0c;分为三种测试库标准测试库扩展测试库远程测试库标准测试库随 Robot Framework 版本一同发布的测试库&#xff0c; 不需要单独安装&#xff0c;但部分标准库仍然需要手动导入标准库有扩展测试库标准库以外的其他测试库都统称为扩展测试库&#xff0c…

OceanBase产品家族及基础概念

第二章&#xff1a;OceanBase产品家族及基础概念 1. OceanBase产品家族 1.1 OceanBase数据库产品家族 1.2 OceanBase数据库内核 1.2.1 高扩展 • 水平扩展 • 按需在线扩容、缩容、不停服务 • 单集群突破100台服务器 1.2.2 高性能 • 峰值6,100万次/秒&#xff08;真实业…

P12 PyTorch 常见函数梯度

目录&#xff1a;1&#xff1a; 常见函数的导数2: 梯度与微分的关系3: 常见函数的梯度4&#xff1a; 梯度更新常见问题一 常见函数的导数&#xff08;复合函数求导证明&#xff09;二 梯度与微分的关系2.1 微分&#xff1a; x 为一元变量时微分&#xff1a; x 为向量时微分矩阵…

学术加油站|机器学习应用在数据库调优领域的前沿工作解读

编者按 本文系北京理工大学科研助理牛颂登所著&#xff0c;本篇也是「 OceanBase 学术加油站」系列稿件第八篇。 「牛颂登&#xff1a;北京理工大学科研助理。 硕士期间在电子科技大学网络空间安全研究院从事聚类和强化学习相关算法研究&#xff0c;在应用聚类研究个性化在线学…

Python之Hermite多项式

文章目录Hermite多项式求导和积分求根和反演拟合其他Hermite多项式 Hermite多项式是一种非常重要的正交多项式&#xff0c;尤其在量子力学中&#xff0c;是谐振子的本征态&#xff0c;在物理学中&#xff0c;其定义为 Hn(x)(−1)nex2dndxne−x2H_n(x)(-1)^ne^{x^2}\frac{\text…

算法之动态规划实战

目录 前言&#xff1a; 如何量化两个字符串的相似度&#xff1f; 如何编程计算莱文斯坦距离&#xff1f; 如何编程计算最长公共子串长度&#xff1f; 参考资料 前言&#xff1a; 利用 Trie 树&#xff0c;可以实现搜索引擎的关键词提示功能&#xff0c;这样可以节省用户输…

【Python+pandas】学生测试成绩求和排序

✨博文作者 wangzirui32 &#x1f496; 喜欢的可以 点赞 收藏 关注哦~~ &#x1f449;本文首发于CSDN&#xff0c;未经许可禁止转载 &#x1f60e;Hello&#xff0c;大家好&#xff0c;我是wangzirui32&#xff0c;最近时间不够充足&#xff0c;鸽了几个月&#xff0c;这是2023…

【蓝桥杯第十三届C++B组】真题训练(5 / 8) - java写法

目录 4402.刷题统计 - 数学模拟 4403. 修剪灌木 - 思维 4404. X 进制减法 - 进制运算 贪心 4405. 统计子矩阵 - 前缀和 双指针​​​​​​​ 1、一维前缀和 2、二维前缀和 4406. 积木画 - dp 1、找规律dp 4402.刷题统计 - 数学模拟 4402. 刷题统计 - AcWing题库 思…

素数(prime)总结

素数的介绍 素数定义 质数(prime number)又称素数&#xff0c;有无限个。一个大于1的自然数&#xff0c;除了1和它本身外&#xff0c;不能被其他自然数整除&#xff0c;换句话说就是该数除了1和它本身以外不再有其他的因数;否则称为合数。 根据算术基本定理&#xff0c;每一个…

linux 文件夹多用户共享 解决文件删除的Permission denied

linux文件属性基础 Linux文件属主和属组 通过命令ls 可以查看文件属性&#xff1a; zcargo-MS-7D53:~/Desktop/parent_ceshi$ ll -lh total 16K drwxrwxr-x 2 zc zc 4.0K 1月 10 13:59 ceshi/ drwxrwxr-x 2 zc zc 4.0K 1月 10 13:59 ceshi02/以上展示命令的意思&#xff1…

大数据概念及Hadoop介绍

大数据概念及Hadoop介绍大数据概念数据存储单位大数据定义大数据的特点(5V特征)大数据部门组织架构分布式技术负载均衡故障转移伸缩性分布式技术总结分布式和集群的区别Hadoop介绍Hadoop核心组件Hadoop发展简史Hadoop特性优点与行业应用Hadoop特性优点行业应用Hadoop发行版本及…

14、Java网络编程

一、 网络编程概述Java是 Internet 上的语言&#xff0c;它从语言级上提供了对网络应用程序的支持&#xff0c;程序员能够很容易开发常见的网络应用程序。Java提供的网络类库&#xff0c;可以实现无痛的网络连接&#xff0c;联网的底层细节被隐藏在 Java 的本机安装系统里&…

【广度优先搜索遍历 + 染色法】判断二分图

还记得当时才大一&#xff0c;上离散数学课&#xff0c;当时觉得很不屑&#xff0c;就是觉得这学的什么玩弄啥用没有&#xff0c;但是其实很多的算法思想在解决题目时很有价值。 本文就将使用染色法解决判断二分图问题&#xff0c;使用广度优先搜索遍历和 Java 语言实现 一、题…

车辆逆行识别检测系统 opencv

车辆逆行识别检测系统通过opencvyolo网络深度学习技术&#xff0c;对现场画面中车辆逆向行驶行为进行检测抓拍预警。 OpenCV的全称是Open Source Computer Vision Library&#xff0c;是一个跨平台的计算机视觉处理开源软件库&#xff0c;支持与计算机视觉和机器学习相关的众多…