java 1.8 脚本引擎执行javascript脚本

您所在的位置:网站首页 java调用脚本 java 1.8 脚本引擎执行javascript脚本

java 1.8 脚本引擎执行javascript脚本

2024-06-26 07:07:14| 来源: 网络整理| 查看: 265

目录 一、什么是脚本引擎1. Java ScriptEngine优缺点 二、Nashorn JavaScript 引擎三、如何使用Nashorn1. java代码中使用 nashorn2. 向Java传递数据或者从Java传出数据2.1 在 JavaScript 端调用 Java 方法 四、常用类总结1. ScriptEngine、ScriptEngineManager2. CompiledScript3. Bindings4. ScriptContext 五、参考

一、什么是脚本引擎

使得Java应用程序可以通过一套固定的接口与各种脚本引擎交互,从而达到在Java平台上调用各种脚本语言的目的。

Java脚本API是连通Java平台和脚本语言的桥梁。

可以把一些复杂易变的业务逻辑交给脚本语言处理,这又大大提高了开发效率。

1. Java ScriptEngine优缺点

优点:可以执行完整的JS方法,并且获取返回值;在虚拟的Context中执行,无法调用系统操作和IO操作,非常安全;可以有多种优化方式,可以预编译,编译后可以复用,效率接近原生Java;所有实现ScriptEngine接口的语言都可以使用,并不仅限于JS,如Groovy,Ruby等语言都可以动态执行。

缺点:无法调用系统和IO操作 ,也不能使用相关js库,只能使用js的标准语法。更新:可以使用scriptengine.put()将Java原生Object传入Context,从而拓展实现调用系统和IO等操作。

二、Nashorn JavaScript 引擎

Nashorn,发音“nass-horn”,是德国二战时一个坦克的命名,同时也是java8新一代的javascript引擎–替代老旧,缓慢的Rhino,符合 ECMAScript-262 5.1 版语言规范。

javascript运行在jvm已经不是新鲜事了,Rhino早在jdk6的时候已经存在,但现在为何要替代Rhino,官方的解释是Rhino相比其他javascript引擎(比如google的V8)实在太慢了,要改造Rhino还不如重写。因此有了Nashorn。

nashorn首先编译javascript代码为java字节码,然后运行在jvm上,底层也是使用invokedynamic命令来执行,所以运行速度很给力。

从JDK 8开始,Nashorn取代Rhino成为Java的嵌入式JavaScript引擎。Nashorn完全支持ECMAScript 5.1规范以及一些扩展。它使用基于JSR 292的新语言特性,其中包含在JDK 7中引入的invokedynamic,将JavaScript编译成Java字节码。

官方参考URL: https://docs.oracle.com/javase/8/docs/technotes/guides/scripting/nashorn/

三、如何使用Nashorn

Nashorn javascript 引擎要么在java程序中以编程的方式使用要么在命令行工具jjs使用,jjs在目录$JAVA_HOME/bin中。如果你准备建立一个jjs的符号链接,如下:

$ cd /usr/bin $ ln -s $JAVA_HOME/bin/jjs jjs $ jjs jjs> print('Hello World'); 1. java代码中使用 nashorn

为了在java中执行JavaScript代码,首先使用原先Rhino (旧版Java1.6中来自Mozilla的引擎)中的包javax.script来创建一个nashorn脚本引擎。.

把JavaScript代码作为一个字符串来直接执行,也可放入一个js脚本文件中 如: ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn"); engine.eval("print('Hello World!');"); ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn"); engine.eval(new FileReader("script.js")); 2. 向Java传递数据或者从Java传出数据 可以将数据作为字符串显式传递 如下的 name变量 ScriptEngineManager scriptEngineManager = new ScriptEngineManager(); ScriptEngine nashorn = scriptEngineManager.getEngineByName("nashorn"); String name = "Olli"; nashorn.eval("print('" + name + "')"); 可以在Java中传递绑定,它们是可以从JavaScript引擎内部访问的全局变量 int valueIn = 10; SimpleBindings simpleBindings = new SimpleBindings(); simpleBindings.put("globalValue", valueIn); nashorn.eval("print (globalValue)", simpleBindings); JavaScript eval的求值结果将会从引擎的“eval”方法返回 Integer result = (Integer) nashorn.eval("1 + 2"); assert(result == 3); 2.1 在 JavaScript 端调用 Java 方法

在 JavaScript 中调用 Java 方法很简单。首先我们定义一个静态的 Java 方法:

static String fun1(String name) { System.out.format("Hi there from Java, %s", name); return "greetings from java"; }

JavaScript 可通过 Java.type API 来引用 Java 类。这跟在 Java 类中引入其他类是类似的。当定义了 Java 类型后我们可直接调用其静态方法 fun1() 并打印结果到 sout。因为方法是静态的,所以我们无需创建类实例。

var MyJavaClass = Java.type('my.package.MyJavaClass'); var result = MyJavaClass.fun1('John Doe'); print(result); 四、常用类总结 1. ScriptEngine、ScriptEngineManager

代码注释如下:

/** * ScriptEngine is the fundamental interface whose methods must be * fully functional in every implementation of this specification. * * These methods provide basic scripting functionality. Applications written to this * simple interface are expected to work with minimal modifications in every implementation. * It includes methods that execute scripts, and ones that set and get values. * * The values are key/value pairs of two types. The first type of pairs consists of * those whose keys are reserved and defined in this specification or by individual * implementations. The values in the pairs with reserved keys have specified meanings. * * The other type of pairs consists of those that create Java language Bindings, the values are * usually represented in scripts by the corresponding keys or by decorated forms of them. * * @author Mike Grogan * @since 1.6 */ public interface ScriptEngine {

ScriptEngine 是个接口类,它规范了包括执行脚本的方法,以及set和get值的方法。

demo:

import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; import javax.script.ScriptException; import javax.script.SimpleBindings; public class JSTesterCallFunctions { public static void main(String[] args){ ScriptEngineManager scriptEngineManager = new ScriptEngineManager(); ScriptEngine nashorn = scriptEngineManager.getEngineByName("nashorn"); try{ for(int i = 0; i < args.length; i++){ File file = new File(args[i]).getAbsoluteFile(); System.out.println("args[" +i+ "] is" + file); if(file.isFile()){ String strJSName = args[i];// For Jar nashorn.eval(new FileReader(strJSName )); Object eval = nashorn.eval("make('" + strJSName + "')");// 传递参数strJSName到JS脚本 else{ System.out.println("Java运行命令参数非法,请检查!"); } } } catch (ScriptException | FileNotFoundException e) { System.out.println("Error executing script: " + e.getMessage()); } } }

ScriptEngineManager是ScriptEngine的工厂,实例化该工厂的时候会加载可用的所有脚本引擎。从工厂中创建ScriptEngine可以使用getEngineByName、getEngineByExtension或 getEngineByMimeType来得到,只要参数名字能对上。执行脚本调用eval方法即可(效果等同于javascript中的eval)。

2. CompiledScript

把脚本编译成java字节码。可以让脚本重复执行,无需重新解析脚本。每个compiledScript都与一个scripteEngine——一个对一个eval的调用相关联。

/** * Extended by classes that store results of compilations. State * might be stored in the form of Java classes, Java class files or scripting * language opcodes. The script may be executed repeatedly * without reparsing. * * Each CompiledScript is associated with a ScriptEngine -- A call to an eval * method of the CompiledScript causes the execution of the script by the * ScriptEngine. Changes in the state of the ScriptEngine caused by execution * of the CompiledScript may visible during subsequent executions of scripts by the engine. * * @author Mike Grogan * @since 1.6 */ public abstract class CompiledScript {

使用如下:

ScriptEngineManager manager = new ScriptEngineManager(); ScriptEngine scriptEngine = manager.getEngineByName( "javascript" ); Bindings scope = scriptEngine.getBindings( ScriptContext.ENGINE_SCOPE ); scope.put( "TransformationName", "xxx" ); CompiledScript startScript = ( (Compilable) scriptEngine ).compile( strStartScript ); startScript.eval( scope ); 3. Bindings

如下源码,Bindings就是一个继承Map接口的接口,所有key都是字符串。

/** * A mapping of key/value pairs, all of whose keys are * Strings. * * @author Mike Grogan * @since 1.6 */ public interface Bindings extends Map { ScriptEngine 有一个getBindings方法,返回Bindings 类型。该方法:

返回命名值的作用域。 可能的范围是:

scriptcontext.global_scope:表示全局的命名值集范围scriptcontext.engine_scope: 表示状态的命名值集是scripteEngine /** * Returns a scope of named values. The possible scopes are: * * * ScriptContext.GLOBAL_SCOPE - The set of named values representing global * scope. If this ScriptEngine is created by a ScriptEngineManager, * then the manager sets global scope bindings. This may be null if no global * scope is associated with this ScriptEngine * ScriptContext.ENGINE_SCOPE - The set of named values representing the state of * this ScriptEngine. The values are generally visible in scripts using * the associated keys as variable names. * Any other value of scope defined in the default ScriptContext of the ScriptEngine. * * * * The Bindings instances that are returned must be identical to those returned by the * getBindings method of ScriptContext called with corresponding arguments on * the default ScriptContext of the ScriptEngine. * * @param scope Either ScriptContext.ENGINE_SCOPE or ScriptContext.GLOBAL_SCOPE * which specifies the Bindings to return. Implementations of ScriptContext * may define additional scopes. If the default ScriptContext of the ScriptEngine * defines additional scopes, any of them can be passed to get the corresponding Bindings. * * @return The Bindings with the specified scope. * * @throws IllegalArgumentException if specified scope is invalid * */ public Bindings getBindings(int scope);

语言绑定对象实际上就是一个简单的哈希表,用来存放和获取需要共享的数据,其定义的接口为javax.script.Bindings,继承自java.util.Map接口。一个脚本引擎在执行过程中可能会使用多个语言绑定对象,不同语言绑定对象的作用域不同。ScriptEngine类提供out和get方法对脚本引擎中特定作用域的默认语言绑定对象进行操作。

使用默认的语言绑定对象:

public void useDefaultBinding() throws ScriptException { ScriptEngine engine = getJavaScriptEngine(); engine.put("name", "Alex"); engine.eval("var message = 'Hello, ' + name;"); engine.eval("println(message);"); Object obj = engine.get("message"); System.out.println(obj); }

可以自定义语言绑定对象(如语言绑定对象中包含程序自己独有的数据等情形……):

public void useCustomBinding() throws ScriptException { ScriptEngine engine = getJavaScriptEngine(); Bindings bindings = new SimpleBindings(); bindings.put("hobby", "playing games"); engine.eval("println('I like ' + hobby);", bindings); } 4. ScriptContext

使用如下:

ScriptEngineManager manager = new ScriptEngineManager(); ScriptEngine scriptEngine = manager.getEngineByName( "javascript" ); Bindings scope = scriptEngine.getBindings( ScriptContext.ENGINE_SCOPE ); scope.put( "TransformationName", "xxx" );

ScriptContext源码注释如下: 该接口的实现类用于连接脚本引擎 在宿主应用程序中使用对象(如作用域绑定)。每个作用域都是一组 其值可以使用。scriptcontex.脚本上下文暴露读和写,即用于脚本引擎的输入和输出。

/** * The interface whose implementing classes are used to connect Script Engines * with objects, such as scoped Bindings, in hosting applications. Each scope is a set * of named attributes whose values can be set and retrieved using the * ScriptContext methods. ScriptContexts also expose Readers and Writers * that can be used by the ScriptEngines for input and output. * * @author Mike Grogan * @since 1.6 */ public interface ScriptContext { 五、参考

Java 8 的 Nashorn 脚本引擎教程 参考URL: https://www.cnblogs.com/top8/p/6207945.html Java新特性之Nashorn的实例详解 参考URL: https://www.cnblogs.com/qiumingcheng/p/7355456.html Java 8 Nashorn 教程 参考URL: https://segmentfault.com/a/1190000006041626 [推荐]Nashorn——在JDK 8中融合Java与JavaScript之力 参考URL: https://www.cnblogs.com/bodhitree/p/8005283.html 官方参考URL: https://docs.oracle.com/javase/8/docs/technotes/guides/scripting/nashorn/ java – 每个线程应该使用单独的ScriptEngine和CompiledScript实例吗? 参考URL: http://www.voidcn.com/article/p-czfxznxr-bsx.html



【本文地址】

公司简介

联系我们

今日新闻


点击排行

实验室常用的仪器、试剂和
说到实验室常用到的东西,主要就分为仪器、试剂和耗
不用再找了,全球10大实验
01、赛默飞世尔科技(热电)Thermo Fisher Scientif
三代水柜的量产巅峰T-72坦
作者:寞寒最近,西边闹腾挺大,本来小寞以为忙完这
通风柜跟实验室通风系统有
说到通风柜跟实验室通风,不少人都纠结二者到底是不
集消毒杀菌、烘干收纳为一
厨房是家里细菌较多的地方,潮湿的环境、没有完全密
实验室设备之全钢实验台如
全钢实验台是实验室家具中较为重要的家具之一,很多

推荐新闻


图片新闻

实验室药品柜的特性有哪些
实验室药品柜是实验室家具的重要组成部分之一,主要
小学科学实验中有哪些教学
计算机 计算器 一般 打孔器 打气筒 仪器车 显微镜
实验室各种仪器原理动图讲
1.紫外分光光谱UV分析原理:吸收紫外光能量,引起分
高中化学常见仪器及实验装
1、可加热仪器:2、计量仪器:(1)仪器A的名称:量
微生物操作主要设备和器具
今天盘点一下微生物操作主要设备和器具,别嫌我啰嗦
浅谈通风柜使用基本常识
 众所周知,通风柜功能中最主要的就是排气功能。在

专题文章

    CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭