1

JDK中内嵌JS引擎介绍及使用 - Stars-one

 1 year ago
source link: https://www.cnblogs.com/stars-one/p/16950837.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

JDK中内嵌JS引擎介绍及使用

本文为作者原创,允许转载,不过请在文章开头明显处注明链接和出处!!! 谢谢配合~
作者:stars-one
链接:https://www.cnblogs.com/stars-one/p/16950837.html

本篇大约有3095个字,阅读预计需要3.87分钟


原文: JDK中内嵌JS引擎介绍及使用 - Stars-One的杂货小窝

最近研究阅读这个APP,其主要功能就是通过一个个书源,从而实现移动端阅读的体验

比如说某些在线小说阅读网站,会加上相应的广告,从而影响用户阅读体验,于是阅读这个APP就是做了类似净化阅读体验

但是小说阅读网站千千万万,如果去适配每个小说阅读网站,岂不是累死,且作者也会有被发律师函的危险,于是作者提供了对应的工具,允许各位用户可自定义书源,阅读APP则通过导入书源,即可实现对某个小说阅读网站的支持

这里说的书源,实际上就是JS脚本代码,作者本质上是使用了rhino这个Java的JS引擎技术来实现的

JDK1.6和JDK1.7采用Rhino。Nashorn 支持 ECMAScript 5.1 规范,使用基于 JSR 292 的新语言特性,其中包含在 JDK 7 中引入的 invokedynamic,将 JavaScript 编译成 Java 字节码。

从JDK1.8开始,Java采用Nashorn作为嵌入式 JavaScript 引擎。

本质上,都是通用标准ECMAScriptJS规范,没啥过多的区别

JDK内置的方式,其实也就是将对应JS引擎的jar包一起集成在Java环境里了,如果想使用新版本的JS引擎,可以去对应的JS引擎上找最新版本的jar包或通过maven来引用依赖即可

rhino目前是由火狐浏览器团队开发的,使用Java写的一个JS引擎,目前也是在更新,如果想要更新,而不想更新JDK的话,可以直接使用maven引入最新的jar包即可

Nashorn之前是oracle团队在开发,现在看github的话,是有openjdk团队在维护

而在Android平台方面,由于平台对JVM进行了调整,所以默认是不支持的,但是好消息的是,有大神将移植到了Android平台上,具体可以查看APISENSE/rhino-android,需要的话可以直接引入依赖即可

不过作者写的使用文档不太清晰,这里我比较推荐使用阅读APP开发者的gedoor/rhino-android,实际上也是基于APISENSE/rhino-android进行了一定的调整,使用起来和Java内置的步骤是一样的

可能有同学就有疑惑了,使用这个JS引擎能有什么作用呢?

这里就举个例子,有个加密方法,是通过js去实现的,但是现在如果让我们想要获取到加密的结果,得通过阅读JS源码,看懂加密思路后再使用Java代码重现实现,是不是十分的复杂?

但如果采用JS引擎,我们只需要将对应的JS方法代码拿到,之后我们只需要传参数,通过JS引擎执行加密过程,即可得到加密后的参数了

PS: 最后,注意一下,上述说到的两种JS引擎,只支持部分ES6特性,所有,如果你的JS代码有ES6特性的,可能执行的时候会报错!

下文以JDK8内置的JS引擎为例,讲解一下使用

1.基本使用

首先,我们需要通过ScriptEngineManager对象获取JS脚本引擎engine对象,之后通过engine.eval()方法来执行我们需要的js代码

// 1、获得脚本引擎对象,选择脚本语言
val manager = ScriptEngineManager()
// 亦可以是js缩写,代表JavaScript脚本语言
val engine = manager.getEngineByName("js")
val result = engine.eval("""
    var num  = 5+2;
    num
""".trimIndent())
println(result)

PS: 如果是gedoor/rhino-android,getEngineByName()方法里面传rhino这个字符串!

2.获取JS变量数值

比较多的情况就是,我们需要通过JS去执行逻辑,之后得到返回的结果,有以下2种方式获取数值

  1. 通过eval()方法的返回值(如上面基本使用的示例代码),可以理解为在浏览器的控制台执行js代码后的控制台会输出的数值
  2. 通过作用域变量

作用域变量的方式代码如下:

// 1、获得脚本引擎对象,选择脚本语言
val manager = ScriptEngineManager()
// 亦可以是js缩写,代表JavaScript脚本语言
val engine = manager.getEngineByName("js")
//声明一个变量
engine.put("finalResult","")

//注册一个js方法
engine.eval("""
    function add(a,b){
        return a + b 
    }
""".trimIndent())

//执行获取结果,赋予finalResult数据
engine.eval("finalResult = add(2,3)")
println(engine["finalResult"])

或者直接在js中声明变量finalResult,如下代码:

// 1、获得脚本引擎对象,选择脚本语言
val manager = ScriptEngineManager()
// 亦可以是js缩写,代表JavaScript脚本语言
val engine = manager.getEngineByName("js")

//注册一个js方法
engine.eval("""
    function add(a,b){
        return a + b 
    }
""".trimIndent())

//执行获取结果
engine.eval("var finalResult = add(2,3)")
println(engine["finalResult"])

3.JS使用Java类型数值

// 1、获得脚本引擎对象,选择脚本语言
val manager = ScriptEngineManager()
// 亦可以是js缩写,代表JavaScript脚本语言
val engine = manager.getEngineByName("js")
val file = File("D:\\temp\\qrcode.gif")
//将文件的对象设置为JS变量
engine.put("myFile",file)

//注册一个js方法
engine.eval("""
    print(myFile.getPath());
""".trimIndent())

上面js中的print实际上也是Java提供的方法,而myFile则是我们Java中的一个File对象,JS代码中可以使用这个对象及相应的Java方法

提问之前,请先看提问须知 点击右侧图标发起提问

或者加入QQ群一起学习

TornadoFx学习交流群:1071184701

1210268-20200316120825333-1551152974.png
1210268-20190508151523126-971809604.gif

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK