大数据培训新三板挂牌机构 股票代码:837906 | EN CN
Java是什么?
Java历史
Java语言特点
C++ VS Java比较
Java工厂设计模式
Java抽象工厂模式
Java单例模式
Java建造者(Builder)模式
Java原型模式
Java适配器模式
Java桥接模式
Java获取网络文件大小
Java套接字到单一的客户端
Java连接套接字
Java URL部分
Java URL连接日期
Java下载网页
Java主机指定IP地址
Java确定本地IP地址
Java检查端口占用
Java查找代理服务器设置
Java创建Socket
Java线程实例
Java检查线程活着
Java如何检查一个线程停止或没有?
Java解决死锁实例
Java如何获取正在运行的线程的优先级?
Java如何监视线程的状态?
Java获取线程名称
Java线程生产者消费者问题
Java如何设置线程的优先级?
Java如何停止线程一会儿?
Java如何暂停线程?
Java获取线程ID
Java如何检查线程的优先级?
Java显示所有正在运行的线程?
Java显示线程状态
Java中断一个线程
Java Applet实例
Java创建Applet
Java使用Applet创建横幅
Java使用Applet显示时钟?
Java在一个Applet创建不同形状
Java如何使用Applet填充形状的颜色?
Java使用Applet跳转到一个链接
Java在Applet创建事件监听器
Java使用Applet显示图像
Java使用Applet在新窗口中打开链接
Java使用Applet播放声音?
Java使用Applet读取文件
Java使用Applet写入文件
Java中Swing应用程序applet
Java简单的图形用户界面-GUI
Java以不同的字体显示文本
Java使用GUI画一条线
Java创建框架-frame
Java使用GUI显示多边形
Java在矩形中显示文本
Java GUI显示不同形状
Java如何绘制GUI实心矩形?
Java创建GUI透明光标
Java检查GUI平滑处理状态
Java在框架中显示颜色
Java GUI显示饼图
Java使用图形用户界面绘制文本
Java编辑表-table
Java 使用prepared语句
Java使用保存点和回滚
Java同时执行数据库多个SQL命令
Java使用行方法
Java使用列方法
Java正则表达式实例
Java将字符串分割
Java搜索重复单词
Java查找出现的单词
Java最后一个词的索引
Java模式匹配
Java删除空格
Java匹配电话号码
Java计数组词
Java搜索词组
Java拆分正则表达式
Java替换第一个出现字符串
Java检查日期格式
Java验证电子邮件地址格式
Java替换所有匹配字符串
Java使每个单词的第一个字母大写
从XML创建SqlSessionFactory实例
不使用XML来创建SqlSessionFactory
从SqlSessionFactory获取SqlSession
映射SQL语句
作用域和生命周期
Mapper XML配置
properties元素
Settings元素
typeAliases 元素
typeHandlers元素
理解CacheLine与写出更好的JAVA
Java核心技术点之动态代理
更好的使用JAVA线程池
理解Java中字符流与字节流的区别
深入分析Java方法反射的实现原理
关于Java面试,你应该准备这些知识点
Java内存模型
2017年你不能错过的Java类库
Leakcanary Square的一款Android/Java内存泄漏检测工具
Java Synchronised机制
Java核心技术点之注解
JVM(8):JVM知识点总览-高级Java工程师面试必备
JVM(3):Java GC算法 垃圾收集器
JVM(1):Java 类的加载机制
解决ActiveMQ中,Java与C++交互中文乱码问题
关于Java Collections的几个常见问题
Java I/O 总结
JVM源码分析之Java对象的创建过程
JVM源码分析之Java类的加载过程
Java GC的那些事(下)
Java GC的那些事(上)
java对象头的HotSpot实现分析
面试的角度诠释Java工程师(一)
面试的角度诠释Java工程师(二)
框架开发之Java注解的妙用
谈谈Java反射机制
Java并发:volatile内存可见性和指令重排
死磕Java并发:Java内存模型之happens-before
死磕Java并发:深入分析volatile的实现原理
死磕Java并发:深入分析synchronized的实现原理
Java 10 可能对 Lambda 表达式进行升级
G1垃圾回收器中的字符串去重(Java 8 Update 20)
Java RESTful框架的性能比较
理解RxJava的线程模型
继续了解Java的纤程库 – Quasar
Java中的纤程库 – Quasar
Java豆瓣电影爬虫——抓取电影详情和电影短评数据
Java集合框架源码剖析:LinkedHashSet 和 LinkedHashMap
Java Lambda表达式初探
Java中的陷阱题
Java 9的这一基本功能,你可能从未听过
关于Java并发编程的总结和思考
几种简单的负载均衡算法及其Java代码实现
JAVA虚拟机关闭钩子(Shutdown Hook)
Java 脚本化编程指南
Java Scripting API 使用示例
Java 8 的 Nashorn 脚本引擎教程
如何开始使用 Java 机器学习
CognitiveJ —— Java 的图像分析库
Java 性能优化的五大技巧
Java 解惑:Comparable 和 Comparator 的区别
Google Java编程风格指南
java NIO详解
Java 异常处理的误区和经验总结
Java语法糖(4):内部类
Java语法糖(3):泛型
Java语法糖(2):自动装箱和自动拆箱
Java消息队列任务的平滑关闭
Java语法糖(1):可变长度参数以及foreach循环原理
2016最流行的Java EE服务器
自己写一个java.lang.reflect.Proxy代理的实现
java 如何在pdf中生成表格
如何防止单例模式被JAVA反射攻击
java虚拟机 jvm 局部变量表实战
聊聊并发-Java中的Copy-On-Write容器
java.lang.Instrument 代理Agent使用
Java开发者需要了解的移动开发编程语言
13个不容错过的Java项目
2016年7款最佳 Java 框架推荐
Java 开发者值得关注的 11 个技术博客
Redmonk发布Java框架流行度调研结果
Java 8开发的4大顶级技巧
GitHub漫游指南:10个值得你关注的Java项目
除了Guava,Java开发者还值得了解的5个谷歌类库
Java中创建对象的5种不同方法
Java性能优化全攻略
奇怪的Java题:为什么1000 == 1000返回为False,而100 == 100会返回为True?
11个最值得Java开发者收藏的网站
Java的常见误区与细节
对Java意义重大的7个性能指标
Java调优经验谈
关于Java并发编程的总结和思考
HDFS Federation设计动机与基本原理
《Effective STL》学习笔记(第三部分)
《Effective STL》学习笔记(第二部分)
《Effective STL》学习笔记(第一部分)
数据结构之位图
Thrift使用指南
Cassandra概要介绍
Cassandra部署与安装
Cassandra客户端
Cassandra数据模型
Cassandra中的各种策略
数据结构之树状数组
数据结构之伸展树
数据结构之后缀数组
数据结构之堆
浅析MRv1与MRv2的API兼容性
Apache Tez最新进展
运行在YARN上的计算框架
从传统操作系统角度理解Hadoop YARN

Java Scripting API 使用示例

于2017-05-10由小牛君创建

分享到:


Java Scripting API 包含一组类和接口,在 javax.script 包中定义。这是一个相对比较小的 Java 包,以 ScriptEngineManager 类作为起点。一个 ScriptEngineManager 对象可以通过 JAR 文件服务发现机制来查找脚本引擎,而实例化 ScriptEngine 对象的解析脚本使用专门的脚本语言编写。更多关于 javax.script 包的详细信息请看 Java SE 规范http://docs.oracle.com/javase/8/docs/api/javax/script/package-summary.html

Nashorn 引擎是 Java SE 开发工具包(JDK)自带的默认 ECMAScript (JavaScript)引擎。Nashorn 引擎是 Oracle 使用纯 Java 开发的,是 OpenJDK 项目的一部分。你可以在下面地址中找到关于 Nashorn 引擎更详细的信息:http://openjdk.java.net/projects/nashorn/

虽然 Nashorn 是 Java Scripting API 默认使用的 ECMAScript 引擎,但你也可以使用其他兼容 JSR 223 的脚本引擎,或者你可以实现自己的引擎。该文档不涉及脚本引擎的实现方法,但最最基础的级别,你必须实现 javax.script.ScriptEngine 和 javax.script.ScriptEngineFactory 接口。抽象类 javax.script.AbstractScriptEngine 提供了很多默认 ScriptEngine 接口的方法实现。

使用 Java Scripting API 的步骤:

  1. 创建一个 ScriptEngineManager 对象.
  2. 从管理器对象中获取 ScriptEngine 对象
  3. 使用脚本引擎的 eval() 方法来执行脚本

下面我们提供了几个例子来展示如何使用 Java Scripting API。为了让例子尽可能的简单,我们没有对执行过程中的异常进行处理。Java Scripting API 的异常有受检查异常和运行时异常两种,这些异常必须进行正确处理。在每个例子中,ScriptEngineManager 类的实例是通过 Nashorn 引擎的 getEngineByName() 方法来获取的。如果指定名称的引擎不存在,该方法会返回 null 。更多关于 Nashorn 引擎的信息请看 Nashorn User’s Guide.

注意:每个 ScriptEngine 对象都有它独有的变量作用域。要使用多个变量作用域请看  Example 8.

示例 1 —— 执行脚本语句

在这个例子中,调用脚本引擎实例的 eval() 方法来执行以字符串标识的 JavaScript 代码。

import javax.script.*;

public class EvalScript {
    public static void main(String[] args) throws Exception {
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("nashorn");

        // evaluate JavaScript code
        engine.eval("print('Hello, World')");
    }
}

示例 2 —— 执行脚本文件

在这个例子中, eval() 方法传递了一个 FileReader 对象作为参数,从 scripts.js 文件中读取 JavaScript 代码。通过封装不同的输入流对象作为 reader 来实现从文件、URL 或者其他资源中执行脚本。

import javax.script.*;

public class EvalFile {
    public static void main(String[] args) throws Exception {
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("nashorn");

        // evaluate JavaScript code
        engine.eval(new java.io.FileReader("script.js"));
    }
}

示例 3 —— 输出 Java 对象作为全局变量

在这个例子中,我们创建了一个 File 对象并通过 put() 方法暴露给引擎作为一个名为 file 的全局变量。然后在 JavaScript 代码中调用 eval() 方法就可以访问该变量并调用 getAbsolutePath() 方法

注意:

作为变量的 Java 对象的字段访问和方法调用语法取决于脚本语言。该例子使用 JavaScript 语法,和 Java 的类似。

import javax.script.*;
import java.io.*;

public class ScriptVars {
    public static void main(String[] args) throws Exception {
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("nashorn");

        // create File object
        File f = new File("test.txt");

        // expose File object as a global variable to the engine
        engine.put("file", f);

        // evaluate JavaScript code and access the variable
        engine.eval("print(file.getAbsolutePath())");
    }
}

示例 4 —— 调用脚本函数

本例中在 JavaScript 代码中调用 eval() 方法,定义了一个包含单个参数的函数。然后创建 Invocable 对象,并使用其方法 invokeFunction() 来调用这个函数。

注意:

并非所有的脚本引擎都实现了 Invocable 接口。本例中使用 Nashorn 引擎,可以在脚本中调用之前引擎已经定义的函数。

import javax.script.*;

public class InvokeScriptFunction {
    public static void main(String[] args) throws Exception {
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("nashorn");

        // evaluate JavaScript code that defines a function with one parameter
        engine.eval("function hello(name) { print('Hello, ' + name) }");

        // create an Invocable object by casting the script engine object
        Invocable inv = (Invocable) engine;

        // invoke the function named "hello" with "Scripting!" as the argument
        inv.invokeFunction("hello", "Scripting!");
    }
}

示例 5 —— 调用脚本对象的方法

本例中在 JavaScript 代码中调用 eval() 方法定义包含一个方法的对象。该对象在脚本中通过脚本引擎的 get() 方法暴露给 Java 应用,然后创建一个 Invocable 对象,并通过 invokeMethod() 方法调用对象的方法。

注意:

并非素有的脚本引擎都实现了 Invocable 接口。本例中使用 Nashorn 引擎,可以调用引擎之前已经定义的脚本方法。

import javax.script.*;

public class InvokeScriptMethod {
    public static void main(String[] args) throws Exception {
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("nashorn");

        // evaluate JavaScript code that defines an object with one method
        engine.eval("var obj = new Object()");
        engine.eval("obj.hello = function(name) { print('Hello, ' + name) }");

        // expose object defined in the script to the Java application
        Object obj = engine.get("obj");

        // create an Invocable object by casting the script engine object
        Invocable inv = (Invocable) engine;

        // invoke the method named "hello" on the object defined in the script
        // with "Script Method!" as the argument
        inv.invokeMethod(obj, "hello", "Script Method!");
    }
}

示例 6 —— 实现一个包含脚本函数的 Java 接口

本例中在 JavaScript 代码中调用 eval() 方法来定义一个函数。然后创建一个 Invocable 对象,并通过其getInterface() 方法来创建一个 Runnable 接口对象。接口的方法在脚本函数中实现,这是通过函数名称匹配的方式实现的(本例中 run() 函数用来实现接口对象的 run() 方法)。最后,启动一个新的线程来运行脚本函数。

import javax.script.*;

public class ImplementRunnable {
    public static void main(String[] args) throws Exception {
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("nashorn");

        // evaluate JavaScript code that defines a function with one parameter
        engine.eval("function run() { print('run() function called') }");

        // create an Invocable object by casting the script engine object
        Invocable inv = (Invocable) engine;

        // get Runnable interface object
        Runnable r = inv.getInterface(Runnable.class);

        // start a new thread that runs the script
        Thread th = new Thread(r);
        th.start();
        th.join();
    }
}

示例 7 —— 在脚本对象方法中实现 Java 接口

本例中在 JavaScript 代码中调用 eval() 方法来定义一个包含单个方法的对象。该对象在脚本中通过 get() 方法暴露给 Java 应用。然后创建一个 Invocable 对象并通过其 getInterface() 方法来创建一个 Runnable 接口对象。该接口的方法实现是在脚本对象中相同匹配名称的函数中(本例中对象的 run 方法对应接口的 run 方法的实现)。最后启动一个新线程来运行脚本对象的方法。

import javax.script.*;

public class ImplementRunnableObject {
    public static void main(String[] args) throws Exception {
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("nashorn");

        // evaluate JavaScript code that defines a function with one parameter
        engine.eval("var obj = new Object()")
        engine.eval("obj.run = function() { print('obj.run() method called') }");

        // expose object defined in the script to the Java application
        Object obj = engine.get("obj");

        // create an Invocable object by casting the script engine object
        Invocable inv = (Invocable) engine;

        // get Runnable interface object
        Runnable r = inv.getInterface(obj, Runnable.class);

        // start a new thread that runs the script
        Thread th = new Thread(r);
        th.start();
        th.join();
    }
}

示例 8 —— 使用多个变量作用域

本例中脚本引擎的 put() 方法用来设置 x 变量值为 “hello” 字符串对象。紧接着 eval() 方法用来打印默认作用域下的变量值。然后定义一个不同的脚本上下文,并在其作用域下设置相同变量为不同的值(“world” 字符串)。最后在新的脚本上下文中答应该变量,显示为不同的值。

单一的作用域是 javax.script.Bindings 接口的实例。这个接口继承自 java.util.Map<String,Object> 接口。一个作用域相当于是成对的名称和值的列表,其中名称不能为空。javax.script.ScriptContext 接口通过为每个作用域关联一个 Bindings 对象来实现对多个作用域的支持。默认情况下,每个脚本应用有自己独立的上下文。默认的脚本上下文至少有一个作用域,这是通过静态属性 ENGINE_SCOPE 来定义的。脚本上下文可以通过 getScopes() 方法来实现对不同作用域的支持。
import javax.script.*;

public class MultipleScopes {
    public static void main(String[] args) throws Exception {
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("nashorn");

        // set global variable
        engine.put("x","hello");

        // evaluate JavaScript code that prints the variable (x = "hello")
        engine.eval("print(x)");

        // define a different script context
        ScriptContext newContext = new SimpleScriptContext();
        newContext.setBindings(engine.createBindings(), ScriptContext.ENGINE_SCOPE);
        Bindings engineScope = newContext.getBindings(ScriptContext.ENGINE_SCOPE);

        // set the variable to a different value in another scope
        engineScope.put("x", "world");

        // evaluate the same code but in a different script context (x = "world")
        engine.eval("print(x)", newContext);