1、下载Rhino安装包,下载地址:官网http://www.mozilla.org/rhino。

2、rhino环境配置,把解压出来的js.jar文件加入到系统的环境变量classpath

3、在命令提示符窗口下,调用javascript引擎,如:java org.mozilla.javascript.tools.shell.Main,即可进入js shell.

4、将javascript代码文件加载到引擎的内存缓冲区中,如:

load("C:/ws/job/vqq1.0/WebRoot/js/mergeJsFile.js");

5、执行合并操作,会一些相关js文件合并到一个js文件中,以减少浏览器对服务器端发出的http请求,提高性能问题。

如:runMerge(parameter1,parameter2, .., ...)

6、为了加快js文件运行的速度,可以把它编译为class文件,

compile:

java org.mozilla.javascript.tools.jsc.Main C:/ws/job/vqq1.0/WebRoot/js/mergeJsFile.js

编译产生mergeJsFile.class文件,然后直接执行class文件,java mergeJsFile.

Rhino的特点如下:

JavaScript 1.5的全部特性

◆ 允许使用脚本直接操作Java

◆ 提供JavaScript Shell执行其它JavaScript脚本

◆ 提供JavaScript编译器将JavaScript源程序转换成Java类文件

Rhino语言特点

Java是一种面对对象的编译型语言。它首先将源代码编译成二进制字节码(bytecode),然后依赖各种不同平台上的虚拟机来解释执行字节码,从而实现了“一次编译、到处执行”的跨平台特性。

JavaScript是一种动态、弱类型、基于原型的客户端脚本语言。JavaScript 包括一个基于对象的 API,称为文档对象模型(Document Object Model)或 DOM,用以访问和操作 Web 页面的内容,给HTML网页添加动态功能。

Rhino是一个介于Java与JavaScript之间的语言。它的基础是 Java 语言,这使得它简单易学,但相比于JavaScript脚本语言来说,它又太过复杂。不过,Rhino 的主要缺点也正是它的强大之处,Rhino 是一种轻量级的、功能强大的脚本语言。Rhino 使用原型而不是类,这使它比很多脚本语言更适合开发 GUI 应用程序,在考虑性能和风格等因素时更是如此。

Rhino语言特点的优缺点

一方面,作为一种动态类型的、基于原型的脚本语言,Rhino借用了很多JavaScript语法。比如,Rhino不再使用语句结束符( ; ),放宽了变量声明规则,并且极大地简化了修改和检索对象属性的语法。另一方面,作为JavaScript 的Java实现,Rhino语法非常类似于Java编程语言。比如,Rhino采用了与 Java 编程语言相似的循环和条件结构,并且遵循类似的语法模式来表示这些结构。

Rhino 和 Java 语言之间有一些显著的区别。Rhino 是一种基于原型的(prototype-based)语言,而不是一种基于类的(class-based)语言。Rhino中,函数和变量的声明中看不到 类型,取而代之的是,使用 function关键字声明函数,使用 var关键字声明局部变量。

Rhino的原始想法是将JavaScript 编译成Java字节码执行,即采用编译执行的方式。由于JVM存在垃圾收集、编译和装载过程的开销过大等限制,Rhino采用了解释执行的方式。

Rhino支持的脚本语言

在可以找到官方的脚本引擎的实现项目。这一项目基于BSD License ,表示这些脚本引擎的使用将十分自由。目前该项目已对包括 Groovy, JavaScript, Python, Ruby, PHP 在内的二十多种脚本语言提供了支持。这一支持列表还将不断扩大。

在 Mustang 中对脚本引擎的检索使用了工厂模式。首先需要实例化一个工厂 —— ScriptEngineManager。

// create a script engine manager

ScriptEngineManager factory = new ScriptEngineManager();

ScriptEngineManager 将在 Thread Context ClassLoader 的 Classpath 中根据 jar 文件的 META-INF 来查找可用的脚本引擎。它提供了 3 种方法来检索脚本引擎:

// create engine by name

ScriptEngine engine = factory.getEngineByName ("JavaScript");

// create engine by name

ScriptEngine engine = factory.getEngineByExtension ("js");

// create engine by name

ScriptEngine engine = factory.getEngineByMimeType ("application/javascript");

下面的代码将会打印出当前的 JDK 所支持的所有脚本引擎

ScriptEngineManager factory = new ScriptEngineManager();

for (ScriptEngineFactory available : factory.getEngineFactories()) {

System.out.println(available.getEngineName());

}

JavaScript操纵Java对象

1. Rhino如何访问Java包与类文件

Java语法规定,任何代码都必须以class文件的形式存在,而每个class文件必须属于一个package,默认为default。而JavaScript并没有类似package的层级结构概念,那么如何使用Rhino访问Java包呢?

Rhino定义了一个top-level变量Packages。变量Packages对应的所有属性均对应Java包名。比如,我们需要访问某一个Java的Package com.example,输入如下:

js> Packages.com.example

刚才演示了如何通过js shell访问Java包,访问Java类的方式类似。假如我们需要访问标准的Java 文件类java.io.File,如下。

js> java.io.File

或者,为避免输入全名,我们先导入包,然后输入Class类名,如下:

js> importPackage(java.io)

js>File

这里的importPackage(java.io),在效果上等价于Java声明import java.io.*; 不同的是,Java会隐式import java.lang.*,而Rhino不会。因为Rhino定义的对象Boolean, Math, Number, Object, String等与Java语法完全不同,两者无法等价。

2. Rhino如何与Java对象交互

与Java类似,Rhino使用new操作符创建对象。

js> new java.util.Date()

Thu May 06 16:19:04 CST 2011

可以使用JavaScript变量存储Java对象,并调用其方法,如下:

js> f = new java.io.File("sample.txt")

sample.txt

js> f.isDirectory()

false

对于static方法与变量,调用如下:

js> java.lang.Math.PI

3.141592653589793

js> java.lang.Math.cos(0)

1

在JavaScript中,方法本身就是对象,这一点与Java不同。我们可以通过下列方式查看方法的重载:

js> f.listFiles

function listFiles() {/*

java.io.File[] listFiles()

java.io.File[] listFiles(java.io.FilenameFilter)

java.io.File[] listFiles(java.io.FileFilter)

*/}

输出中列出三个重载方法。第一个为无参函数,第二与第三个对应的参数分别为FilenameFilter与FileFilter。

另一个比较有意思的特点是通过构造for..in,查看对象对应的所有方法与变量。如下:

js> for (i in f) { print(i) }

屏幕输出为:

exists

parentFile

mkdir

toString

wait

[44 others]

这里列出的方法一部分来自于父类,比如wait来自父类java.lang.Object。

对于JavaBean,Rhino也提供按名字访问的简单方式。比如,通过下面这种方式,我们就可以调用File对象的getName与isDirectory方法:

js> f.name

test.txt

js> f.directory

false

3. Rhino如何实现Java接口

JavaScript当中,方法本身就是对象。下面我们通过JavaScript语法{propertyName: value}声明一个JavaScript方法,并调用该方法如下:

js> obj = { run: function () { print("\nrunning"); } }

[object Object]

js> obj.run()

running

现在我们构造一个JavaScript对象,实现Runnable接口。并将该对象作为参数,构造一个新的线程,并启动该线程。

js> r = new java.lang.Runnable(obj);

adapter1@291aff

js> t = new java.lang.Thread(r)

Thread[Thread-0,5,main]

js> t.start()

js>

running

最后的js>提示符与新线程的打印输出running的先后顺序是随机的,取决于线程的调度策略。

从后端的处理流程来讲,Rhino首先为Runnable接口的实现类生成Java字节码文件。然后调用JavaScript对象定义的Run方法。

4. Rhino如何创建Java 数组

Rhino使用Java的发射机制生成数组。下面是生成2个String对象的代码:

js> array = java.lang.reflect.Array.newInstance(java.lang.String, 2);

[Ljava.lang.String;@a20892

js> array[0] = "Double"

Double

js> array[1] = "Life"

Life

js> array[0] + array[1]

DoubleLife

js>

5. Rhino如何捕获与处理异常

与Java类似,Rhino使用try...catch关键字处理异常。

js> function classForName(name) {

try {

return java.lang.Class.forName(name);

} catch (e if e.javaException instanceof java.lang.ClassNotFoundException) {

print("Class " + name + " not found");

} catch (e if e.javaException instanceof java.lang.NullPointerException) {

print("Class name is null");

}

}

js> classForName("NonExistingClass");

Class NonExistingClass not found

js> classForName(null);

Class name is null

6. Rhino如何调用js文件

当然,除了在命令行的方式,我们还可以使用操纵JavaScript文件。下面是一段JavaScript代码,主要目的是判断该数是否为质数。代码如下:

function isPrime (num)

{

if (num <= 1) {

print("Enter an integer no less than 2.")

return false

}

var prime = true

var sqrRoot = Math.round(Math.sqrt(num))

for (var n = 2; prime & n <= sqrRoot; ++n) {

prime = (num % n != 0)

}

return prime

}

我们保存文件为C:\isPrime.js。然后我们需要调用load方法加载该脚本。最后,我们可以调用isPrime方法来判断是否为质数。

js> load("C:/isPrime.js")

js> isPrime(33);

false

js> isPrime(31)

true

需要注意的是,注意:文件分隔符需要调整,是“/”而不是“\”。

刚才使用JavaScript操纵Java对象。接下来我们看看如何使用Java程序访问JavaScript

Java对象操纵JavaScript

下面是一段Java代码,用来运行数学表达式。代码如下:

package com.example;

import sun.org.mozilla.javascript.internal.Context;

import sun.org.mozilla.javascript.internal.Scriptable;

publicclass Test {

publicstaticvoid main(String[] args) {

Context cx = Context.enter();

try {

Scriptable scope = cx.initStandardObjects();

String str = "3/(1+2)";

Object result = cx.evaluateString(scope, str, null, 1, null);

System.out.println(str + "=" + Context.toNumber(result));

} finally {

Context.exit();

}

}

}

运行Java com.example.Test,输出结果如下:

3/(1+2)=1.0

之所以是1.0而不是1,是因为Context.toNumber(result)返回的类型为double。

另一个值得注意的是,这里import的package属于JDK 6.0。

因此,在不需要Rhino提供的js.jar,该程序仍能独立运行。因为rhino已经是jdk 6.0 的正规军了,即是它的一部分。

A Java program for running JavaScript scripts

import javax.script.*; import java.io.*; // Evaluate a file of JavaScript and print its result public class RunScript { public static void main(String[] args) throws IOException { // Obtain an interpreter or "ScriptEngine" to run the script. ScriptEngineManager scriptManager = new ScriptEngineManager( ); ScriptEngine js = scriptManager.getEngineByExtension("js"); // The script file we are going to run String filename = null; // A Bindings object is a symbol table for or namespace for the // script engine. It associates names and values and makes // them available to the script. Bindings bindings = js.createBindings( ); // Process the arguments. They may include any number of // -Dname=value arguments, which define variables for the script. // Any argument that does not begin with -D is taken as a filename for(int i = 0; i < args.length; i++) { String arg = args[i]; if (arg.startsWith("-D")) { int pos = arg.indexOf('='); if (pos == -1) usage( ); String name = arg.substring(2, pos); String value = arg.substring(pos+1); // Note that all the variables we define are strings. // Scripts can convert them to other types if necessary. // We could also pass a java.lang.Number, a java.lang.Boolean // or any Java object or null. bindings.put(name, value); } else { if (filename != null) usage( ); // only one file please filename = arg; } } // Make sure we got a file out of the arguments. if (filename == null) usage( ); // Add one more binding using a special reserved variable name // to tell the script engine the name of the file it will be executing. // This allows it to provide better error messages. bindings.put(ScriptEngine.FILENAME, filename); // Get a stream to read the script. Reader in = new FileReader(filename); try { // Evaluate the script using the bindings and get its result. Object result = js.eval(in, bindings); // Display the result. System.out.println(result); } catch(ScriptException ex) { // Or display an error message. System.out.println(ex); } } static void usage( ) { System.err.println( "Usage: java RunScript [-Dname=value...] script.js"); System.exit(1); } }

A Java configuration file utility that interprets JavaScript expressions

import javax.script.*; import java.util.*; import java.io.*; /** * This class is like java.util.Properties but allows property values to * be determined by evaluating JavaScript expressions. */ public class Configuration { // Here is where we store name/value pairs of defaults. Map defaults = new HashMap( ); // Accessors for getting and setting values in the map public Object get(String key) { return defaults.get(key); } public void put(String key, Object value) { defaults.put(key, value); } // Initialize the contents of the Map from a file of name/value pairs. // If a value is enclosed in curly braces, evaluate it as JavaScript. public void load(String filename) throws IOException, ScriptException { // Get a JavaScript interpreter. ScriptEngineManager manager = new ScriptEngineManager( ); ScriptEngine engine = manager.getEngineByExtension("js"); // Use our own name/value pairs as JavaScript variables. Bindings bindings = new SimpleBindings(defaults); // Create a context for evaluating scripts. ScriptContext context = new SimpleScriptContext( ); // Set those Bindings in the Context so that they are readable // by the scripts but so that variables defined by the scripts do // not get placed into our Map object. context.setBindings(bindings, ScriptContext.GLOBAL_SCOPE); BufferedReader in = new BufferedReader(new FileReader(filename)); String line; while((line = in.readLine( )) != null) { line = line.trim( ); // strip leading and trailing space if (line.length( ) == 0) continue; // skip blank lines if (line.charAt(0) == '#') continue; // skip comments int pos = line.indexOf(":"); if (pos == -1) throw new IllegalArgumentException("syntax: " + line); String name = line.substring(0, pos).trim( ); String value = line.substring(pos+1).trim( ); char firstchar = value.charAt(0); int len = value.length( ); char lastchar = value.charAt(len-1); if (firstchar == '"' && lastchar == '"') { // Double-quoted quoted values are strings defaults.put(name, value.substring(1, len-1)); } else if (Character.isDigit(firstchar)) { // If it begins with a number, try to parse a number try { double d = Double.parseDouble(value); defaults.put(name, d); } catch(NumberFormatException e) { // Oops. Not a number. Store as a string defaults.put(name, value); } } else if (value.equals("true")) // handle boolean values defaults.put(name, Boolean.TRUE); else if (value.equals("false")) defaults.put(name, Boolean.FALSE); else if (value.equals("null")) defaults.put(name, null); else if (firstchar == '{' && lastchar == '}') { // If the value is in curly braces, evaluate as JavaScript code String script = value.substring(1, len-1); Object result = engine.eval(script, context); defaults.put(name, result); } else { // In the default case, just store the value as a string. defaults.put(name, value); } } } // A simple test program for the class public static void main(String[] args) throws IOException, ScriptException { Configuration defaults = new Configuration( ); defaults.load(args[0]); Set> entryset = defaults.defaults.entrySet( ); for(Map.Entry entry : entryset) { System.out.printf("%s: %s%n", entry.getKey( ), entry.getValue( )); } } }

Compiling Scripts

// This is the text of the script we want to compile. String scripttext = "x * x"; // Get the script engine. ScriptEngineManager scriptManager = new ScriptEngineManager( ); ScriptEngine js = scriptManager.getEngineByExtension("js"); // Cast it to the Compilable interface to get compilation functionality. Compilable compiler = (Compilable)js; // Compile the script to a form that we can execute repeatedly. CompiledScript script = compiler.compile(scripttext); // Now execute the script five times, using a different value for the // variable x each time. Bindings bindings = js.createBindings( ); for(int i = 0; i < 5; i++) { bindings.put("x", i); Object result = script.eval(bindings); System.out.printf("f(%d) = %s%n", i, result); }

Invoking JavaScript Functions

// Obtain an interpreter or "ScriptEngine" to run the script ScriptEngineManager scriptManager = new ScriptEngineManager( ); ScriptEngine js = scriptManager.getEngineByExtension("js"); // Evaluate the script. We discard the result since we only // care about the function definition. js.eval("function f(x) { return x*x; }"); // Now, invoke a function defined by the script. try { // Cast the ScriptEngine to the Invokable interface to // access its invocation functionality. Invocable invocable = (Invocable) js; for(int i = 0; i < 5; i++) { Object result = invocable.invoke("f", i); // Compute f(i) System.out.printf("f(%d) = %s%n", i, result); // Print result } } catch(NoSuchMethodException e) { // This happens if the script did not define a function named "f". System.out.println(e); }

Implementing a Java interface with JavaScript code

import javax.script.*; import java.io.*; import java.awt.event.*; import javax.swing.*; public class Keys { public static void main(String[] args) throws ScriptException, IOException { // Obtain an interpreter or "ScriptEngine" to run the script. ScriptEngineManager scriptManager = new ScriptEngineManager( ); ScriptEngine js = scriptManager.getEngineByExtension("js"); // Evaluate the script. We discard the result since we only // care about the function definitions in it. js.eval(new FileReader("listener.js")); // Cast to Invocable and get an object that implements KeyListener. Invocable invocable = (Invocable) js; KeyListener listener = invocable.getInterface(KeyListener.class); // Now use that KeyListener in a very simple GUI. JFrame frame = new JFrame("Keys Demo"); frame.addKeyListener(listener); frame.setSize(200, 200); frame.setVisible(true); } }

Implementing an interface in JavaScript simply means defining a function with the same name as each method defined by the interface. Here, for example, is a simple script that implements KeyListener:

function keyPressed(e) {

print("key pressed: " + String.fromCharCode(e.getKeyChar( )));

}

function keyReleased(e) {

/* do nothing */

}

function keyTyped(e) {

/* do nothing */

}

Note that the JavaScript keyPressed( ) method defined here accepts ajava.awt.event.KeyEvent object as its argument and actually invokes a method on that Java object. The next section explains how this is done.

rhino java api demo_javascript与java的相互调用,纯java的javascript引擎rhino(转载)相关推荐

  1. Android JNI学习(五)——Java与Native之间如何实现相互调用

    本章将讲述Java与Native之间如何实现相互调用.我将围绕围绕如下三点来讲解. #mermaid-svg-qeVnGlVrLWrB5ryX .label{font-family:'trebuche ...

  2. java api 获取jvm实例_JVMTI那些事——和Java相互调用

    前面几篇文章介绍了JVMTI接口的一些基本概念,以及如何编写一个基于JVMTI的agent. 那些简单的例子只是JVMTI agent自己实现一些简单的功能,如果能够将JVMTI提供的接口经过包装之后 ...

  3. Java与.NET 的Web Services相互调用

    一:简介 本文介绍了Java与.NET开发的Web Services相互调用的技术.本文包括两个部分,第一部分介绍了如何用.NET做客户端调用Java写的Web Services,第二部分介绍了如何用 ...

  4. redis 3.0 java 工具包_redis分布式锁工具包,提供纯Java方式调用

    redis-distributed-lock redis分布式锁工具包,提供纯Java方式调用,支持传统Spring工程, 为spring boot应用提供了starter,更方便快捷的调用. 项目结 ...

  5. java jsch session 多久会断开_What?纯Java居然能实现Xshell!

    前言 最近由于项目需求,项目中需要实现一个WebSSH连接终端的功能,由于自己第一次做这类型功能,所以首先上了GitHub找了找有没有现成的轮子可以拿来直接用,当时看到了很多这方面的项目,例如:Gat ...

  6. java pdf 转txt文件怎么打开_纯Java实现PDF转txt文件

    展示这个Demo的原因是一哥们需要我帮他把一些PDF格式的资料转为txt,我在网上找了下在线的工具,都不好用,网上大多数的在线pdf转txt文件都需要付费,而免费的一次转换文件大小不能超过2M,比较痛 ...

  7. java与js交互,相互调用传参

    随着前端技术的发展与H5的广泛使用,移动端采用native+h5的方式越来越多了,对于Android来说就涉及到java与js的交互,相互调用传参等.下面就来看一下java与js交互的简单demo. ...

  8. JAVA与.NET的相互调用——通过Web服务实现相互调用

    JAVA与.NET是现今世界竞争激烈的两大开发媒体,两者语言有很多相似的地方.而在很多大型的开发项目里面,往往需要使用两种语言进行集成开发.而很多的开发人员都会偏向于其中一种语言,在使用集成开发的时候 ...

  9. java开发checklist,Java API设计CheckList

    API设计原则:正确.好名.易用.易学.够快.够小.但我们从来不缺原则,〜〜〜 Interface 1.The Importance of Being Use Case Oriented,一个接口应当 ...

最新文章

  1. 软件测试之功能测试详细过程
  2. (四)maven之查找jar包坐标,选择jar包版本
  3. Extension project - Component.js of standard application could not be loaded
  4. 运营体系_用户运营系统论:解构复杂产品的大规模用户运营体系
  5. 远程办公(2)-重新定义“雇佣关系”:交易成果,而不是时间
  6. UWA周年庆,福利分发,免费赠送专业版性能报告!
  7. jquery 自定义插件!
  8. 论文word引用参考文献
  9. linux识别riser卡,一种应用在GPU服务器中可灵活配置的Riser卡的制作方法
  10. vue、vant上传附件功能实现
  11. sis最新地址获取方法_拳头最新FPS游戏VALORANT资格免费获取方法
  12. led灯光衰怎么解决_LED灯具怎么解决光衰问题?
  13. 【虫师--系列15】性能测试知多少---系统架构分析
  14. HiC-Pro | HiC数据处理工具
  15. pdf编辑器工具哪个好?好用的pdf编辑器一款就够!
  16. C++ 读取文件时报错“将一个无效参数传递给了将无效参数视为严重错误的函数”解决方法
  17. 计算机网络——HTTP
  18. 用户生命周期(User Lifetime)
  19. *2-2 OJ 1163 导弹拦截之测试版
  20. 重学Android基础系列篇(二):泛型

热门文章

  1. 200代码写一套属于自己的事件总线(EventBus)库
  2. 使用Anaconda Prompte安装pytorch,在pycharm使用torch遇到的问题
  3. 代理记账的整套流程和费用
  4. 微信测试走步的软件是什么,微信运动步数是怎样计算的?终于有人研究出来了......
  5. Linux如何手动编译fcitx文件,linux下安装和配置fcitx中文输入法
  6. 智能家居主战场:小米生态链VS华为联盟
  7. HDU No Brainer
  8. 基于Open3D的点云处理6-点云去噪
  9. Windos 内网渗透之Token的使用
  10. 3836mysql数据库应用基础教程答案_mysql数据库面试题大全