余晖落尽暮晚霞,黄昏迟暮远山寻
本站
当前位置:网站首页 > 编程知识 > 正文

详解如何在 Java 中执行 JavaScript 脚本(jsp的java代码如何执行)

xiyangw 2022-11-25 11:39 64 浏览 0 评论

1 概述

本文介绍在 Java 环境中执行 JavaScript 脚本的简单使用,具体包含以下内容

  1. Java 8 中的内置 Nashorn Javascript 引擎介绍
  2. Rhino JavaScript 引擎介绍以及对 XML 的处理介绍

2 Java 8 中的内置 Nashorn Javascript 引擎介绍

Nashorn 是 Java 8 中内置的 JavaScript 引擎,无需加入任何依赖。

Nashorn 基本使用步骤如下

  1. new 出 ScriptEngineManager 对象
  2. 通过 ScriptEngineManager 对象中的 getEngineByName 方法获取指定的 JavaScript 引擎,返回 ScriptEngine 对象
  3. Java 8 中的默认的 Javascript 引擎包括:[nashorn, Nashorn, js, JS, JavaScript, javascript, ECMAScript, ecmascript]
  4. 通过 ScriptEngine 对象的 eval 方法来执行 JavaScript 脚本。

2.1 通过 PrintWriter 对象获取脚本中的 print 输出

Javascript 脚本中没有函数,没有返回值,通过 print 输出内容,这时需要通过 PrintWriter 获取读取脚本中的 print 输出,具体如下

@Test
    public void test_nashorn() {
        try {
            ScriptEngine engine = new ScriptEngineManager().getEngineByName("Nashorn");
            ScriptContext scriptContext = engine.getContext();
            StringWriter stringWriter = new StringWriter();
            PrintWriter printWriter = new PrintWriter(stringWriter);
            scriptContext.setWriter(printWriter);

            String jsString = "var obj=JSON.parse('{\\\"data\\\":\\\"7155\\\",\\\"sign\\\":\\\"success\\\",\\\"message\\\":null}');print(obj.sign==\"success\");";

            stringWriter = new StringWriter();
            printWriter = new PrintWriter(stringWriter);
            scriptContext.setWriter(printWriter);
            engine.eval(jsString);
            System.out.println(String.format("1 result = %s",stringWriter.toString()));

            jsString = "var obj=JSON.parse('{\\\"data\\\":\\\"7157\\\",\\\"sign\\\":\\\"success\\\",\\\"message\\\":null}');print((function getData() {  return obj.data;})())";
            stringWriter = new StringWriter();
            printWriter = new PrintWriter(stringWriter);
            scriptContext.setWriter(printWriter);
            engine.eval(jsString);
            System.out.println(String.format("2 result = %s",stringWriter.toString()));

            jsString = "var obj=JSON.parse('{\\\"data\\\":\\\"7157\\\",\\\"sign\\\":\\\"success\\\",\\\"message\\\":null}');print((function getData() {  return obj.data;})())";
            stringWriter = new StringWriter();
            printWriter = new PrintWriter(stringWriter);
            scriptContext.setWriter(printWriter);
            engine.eval(jsString);
            System.out.println(String.format("3 result = %s",stringWriter.toString()));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

2.2 获取匿名函数的返回值

Javascript 脚本是一个匿名函数并且有返回值,通过 eval 函数可以直接

@Test
public void test_js_function_return() {
    try {
        ScriptEngine engine = new ScriptEngineManager().getEngineByName("Nashorn");
        String jsFunction = "(function(){var obj=JSON.parse('{\\\"data\\\":\\\"7155\\\",\\\"sign\\\":\\\"success\\\",\\\"message\\\":null}');return obj.sign==\"success\"})();";
        Boolean result = (Boolean) engine.eval(jsFunction);
        System.out.println(result);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

2.3 调用 Javascript 脚本中指定的函数

Javascript 脚本中有变量,有多个函数,具体如下

@Test
public void test_invoke_js_function() {
    try {
        ScriptEngine engine = new ScriptEngineManager().getEngineByName("Nashorn");
        /*
        var obj = JSON.parse('{\"data\":\"7155\",\"sign\":\"success\",\"message\":null}');
        function checkSign() {
            return obj.sign == 'success'
        }
        function getData() {
            return obj.data
        }
        function calculate(a, b) {
            return a + b
        }
         */
        String jsFunction = "var obj=JSON.parse('{\\\"data\\\":\\\"7155\\\",\\\"sign\\\":\\\"success\\\",\\\"message\\\":null}');function checkSign(){return obj.sign=='success'}function getData(){return obj.data}function calculate(a,b){return a+b}";

        engine.eval(jsFunction);
        Invocable invocable = (Invocable) engine;

        Object result = invocable.invokeFunction("checkSign", null);
        System.out.println(result);

        result = invocable.invokeFunction("getData", null);
        System.out.println(result);

        result = invocable.invokeFunction("calculate", 2, 5);
        System.out.println(result);
    } catch (Exception e) {
        e.printStackTrace();
    }
}
  • 输出如下
true
7155
7.0

2.4 读取 Javascript 文件并执行

这种情况是读取 Javascript 文件,并执行,具体如下

  • src/test/resources/test.js
@Test
public void test_invoke_js_file() {
    try {
        ScriptEngine engine = new ScriptEngineManager().getEngineByName("Nashorn");
        engine.eval(new FileReader(TestJSEngine.class.getResource("/test.js").getPath()));
        Invocable invocable = (Invocable) engine;

        Object result = invocable.invokeFunction("checkSign", null);
        System.out.println(result);

        result = invocable.invokeFunction("getData", null);
        System.out.println(result);

        result = invocable.invokeFunction("calculate", 2, 5);
        System.out.println(result);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

文件内容和上面一样。

3 Rhino JavaScript 引擎介绍

默认的 Nashorn 引擎是无法解析 xml 的,像 DOMParser 这样的对象是浏览器内置的组件。

这里可以通过 Maven 依赖 Rhino 引擎来处理 xml。

  • Rhino Maven 依赖如下
<dependency>
  <groupId>cat.inspiracio</groupId>
  <artifactId>rhino-js-engine</artifactId>
  <version>1.7.10</version>
</dependency>

使用的步骤和其他 JavaScript 引擎一样,引擎的名称为 Rhino.

3.1 Rhino 对 xml 的解析

这里通过读取文件的方式来加载和解析 JavaScript 脚本,脚本中是对一段 xml 的解析的过程。

  • src/test/resources/xml.js 文件内容如下
print("----------------------------------------");
var e = new XML('<employees> <employee id="1"><name>Joe</name><age>20</age></employee> <employee id="2"><name>Sue</name><age>30</age></employee>  </employees>');
// 获取所有的员工
print("获取所有的员工:\n" + e..name);
// 名字叫 Joe 的员工
print("名字叫 Joe 的员工:\n" + e.employee.(name == "Joe"));
// 员工的id 为 1 和 2
print("员工的id 为 1 和 2:\n" + e.employee.(@id == 1 || @id == 2));
// 员工的id 为 1
print("员工的id 为 1: " + e.employee.(@id == 1).name);
print("----------------------------------------");
  • 执行如下
@Test
public void test_rhino_file_js() {
    try {
        ScriptEngine engine = new ScriptEngineManager().getEngineByName("rhino");

        ScriptContext scriptContext = engine.getContext();

        StringWriter stringWriter = new StringWriter();
        PrintWriter printWriter = new PrintWriter(stringWriter);
        scriptContext.setWriter(printWriter);
        engine.eval(new FileReader(TestJSEngine.class.getResource("/xml.js").getPath()));

        System.out.println(String.format("xml result = %s",stringWriter.toString() ));

    } catch (Exception e) {
        e.printStackTrace();
    }
}
  • 输出如下
xml result = ----------------------------------------
All the employee names are:
<name>Joe</name>
<name>Sue</name>
The employee named Joe is:
<employee id="1">
  <name>Joe</name>
  <age>20</age>
</employee>
Employees with ids 1 & 2:
<employee id="1">
  <name>Joe</name>
  <age>20</age>
</employee>
<employee id="2">
  <name>Sue</name>
  <age>30</age>
</employee>
Name of the the employee with ID=1: Joe
----------------------------------------

3.2 测试

  • xml 内容如下
<CCardProcessSyncResponse>
    <RetCode>0</RetCode>
    <Message>操作成功!</Message>
    <RefundCycle />
    <EpayRefundCycleMin>1</EpayRefundCycleMin>
    <EpayRefundCycleMax>7</EpayRefundCycleMax>
    <EpayRefundCycleUnitF />
</CCardProcessSyncResponse>
  • 具体测试如下
@Test
public void test_rhino() {
    try {
        ScriptEngine engine = new ScriptEngineManager().getEngineByName("rhino");

        String jsString = jsString = "var obj=new XML('<CCardProcessSyncResponse>    <RetCode>0</RetCode>    <Message>操作成功!</Message>    <RefundCycle />    <EpayRefundCycleMin>1</EpayRefundCycleMin>    <EpayRefundCycleMax>7</EpayRefundCycleMax>    <EpayRefundCycleUnitF />  </CCardProcessSyncResponse>');print(obj.Message == '操作成功!');";
        ScriptContext scriptContext = engine.getContext();

        StringWriter stringWriter = new StringWriter();
        PrintWriter printWriter = new PrintWriter(stringWriter);
        scriptContext.setWriter(printWriter);
        engine.eval(jsString);

        System.out.println(String.format("xml result = %s",stringWriter.toString() ));

    } catch (Exception e) {
        e.printStackTrace();
    }
}

上面的输出结果如下

xml result = true

相关推荐

Mac软件删除方法,这样删除不会有残留
Mac软件删除方法,这样删除不会有残留

Mac电脑如果有太多无用的应用程序,很有可能会拖垮Mac系统的运行速度。因此,卸载电脑中无用的软件是优化Mac系统运行速度的最佳方式之一。Mac卸载应用程序的方...

2023-09-23 17:34 xiyangw

安利一款 Mac 的清理工具 Cleaner One
安利一款 Mac 的清理工具 Cleaner One

自从入手mac以后,一直在找款mac的清理工具之前也尝试过CleanMyMac和柠檬清理柠檬清理是腾讯旗下的,虽然免费,但更新不频繁,最近一次更新还...

2023-09-23 17:33 xiyangw

苹果电脑需要安装杀毒软件吗?一文告诉你
苹果电脑需要安装杀毒软件吗?一文告诉你

随着数字时代的发展,计算机安全问题变得越来越重要。而在计算机安全领域中,杀毒软件是一个被广泛讨论的话题。苹果电脑需要安装杀毒软件吗?对于苹果电脑用户来说,他们常...

2023-09-23 17:30 xiyangw

mac上实用的工具

mac系统上有很多好用的工作,本期给大家带来一些本人长期使用的软件,特别是刚从windows系统的pc转移到macbook上的小伙伴,可能有一定的帮助。1.Alfred可以完全取代苹果自带Spotl...

Mac专用免费清理软件CleanMyMac
Mac专用免费清理软件CleanMyMac

在Mac中,越来越多的垃圾占用了磁盘空间怎么办?直接拖拽到废纸篓很多软件不能完全卸载干净怎么办……伴随着这些问题,如果有一款多功能的软件能够解决以上的全部难题就...

2023-09-23 17:29 xiyangw

MAC软件分享CleanMyMac中文版 支持最新版系统
MAC软件分享CleanMyMac中文版 支持最新版系统

CleanMyMac的强大不需要过多的去介绍,软件支持最新版Macos10.15.6系统。CleanMyMac具有非常强大的功能,可让您安全,智能地扫描和清理...

2023-09-23 17:28 xiyangw

安装CleanMyMac 3提示软件已损坏
安装CleanMyMac 3提示软件已损坏

安装CleanMyMac3提示软件已损坏,出现这样的原因是往往是使用了CleanMyMac3破解版,主要是因为CleanMyMac3的来源问题,我们的正版软件(...

2023-09-23 17:27 xiyangw

苹果Mac中使用 CleanMyMac X 清理垃圾时频繁要求输入密码如何解决?
苹果Mac中使用 CleanMyMac X 清理垃圾时频繁要求输入密码如何解决?

有不少用户反映在使用CleanMyMac清理系统垃圾文件的时候会频繁要求输入开机密码,如何解决这个问题?来看看吧!解决方法:1.打开「终端」,并输入以下命令...

2023-09-23 17:27 xiyangw

MacBook清理垃圾软件哪个好
MacBook清理垃圾软件哪个好

很多时候手动清理mac效果并没有那么好,常常会有疏忽的地方,其实我们完全可以依赖一些mac清理垃圾软件。windows上我们会借助360安全卫士、腾讯安全管家等...

2023-09-23 17:26 xiyangw

全球真的只有13台DNS根域名服务器吗?
全球真的只有13台DNS根域名服务器吗?

DNS根域名服务器(DNSrootnameservers)是一组特殊的DNS服务器,它们存储有关Internet域名系统(DNS)中所有顶级域的信息。这些...

2023-09-23 17:25 xiyangw

网络管理员,网络工程师每日一练

在DNS服务器中的()资源记录定义了区域的邮件服务器及其优先级。A.SOAB.NSC.PTRD.MX试题答案:D...

Android性能优化之网络优化DNS和HttpDNS知识详解
Android性能优化之网络优化DNS和HttpDNS知识详解

前言小计在App访问网络的时候,DNS解析是网络请求的第一步,默认我们使用运营商的LocalDNS服务。有数据统计,在这一块3G网络下,耗时在2...

2023-09-23 17:25 xiyangw

如何修改域名DNS服务器?修改DNS服务器常见问题汇总
如何修改域名DNS服务器?修改DNS服务器常见问题汇总

在域名管理过程中,我们为了获得更专业安全的域名解析服务,就需要修改DNS服务器,下面中科三方针对修改DNS服务器常见问题做下简单回答。1.修改DNS服务器和修改...

2023-09-23 17:24 xiyangw

netty系列之:在netty中使用 tls 协议请求 DNS 服务器

简介在前面的文章中我们讲过了如何在netty中构造客户端分别使用tcp和udp协议向DNS服务器请求消息。在请求的过程中并没有进行消息的加密,所以这种请求是不安全的。那么有同学会问了,就是请求解析一个...

「GCTT 出品」使用 Golang 构建 DNS 服务器
「GCTT 出品」使用 Golang 构建 DNS 服务器

需求:对DNS查询进行转发和缓存的本地DNS服务器。补充1:提供一个记录管理的接口(HTTPhandler)。补充2:提供一个名字(name)。D...

2023-09-23 17:23 xiyangw

取消回复欢迎 发表评论: