`

JavaSE6脚本引擎(java中javascript脚本)

    博客分类:
  • java
阅读更多

  在默认情况下,Java SE 6只支持JavaScript,但这并不以为着Java SE 6只能支持JavaScript。在Java SE 6中提供了一些接口来定义一个脚本规范,也就是JSR223。通过实现这些接口,Java SE 6可以支持任意的脚本语言(如PHP或Ruby)。

       在使用Java SE 6运行脚本之前,必须要知道你的Java SE 6支持什么脚本语言。在javax.script包中有很多的类,但这些类中最主要的是ScriptEngineManager。可以通过这个类得到当前Java SE 6所支持的所有脚本。如下面例子将列出所有可以使用的脚本引擎工厂。

import javax.script.*;
import java.io.*;
import java.util.*;
import static java.lang.System.*;
public class ListScriptEngines
{
 public static void main(String args[])
 {
  ScriptEngineManager manager = new ScriptEngineManager();
  // 得到所有的脚本引擎工厂
  List<ScriptEngineFactory> factories = manager.getEngineFactories();
  // 这是Java SE 5 和Java SE 6的新For语句语法
  for (ScriptEngineFactory factory: factories)
  {
   // 打印脚本信息
   out.printf("Name: %s%n" +
    "Version: %s%n" +
    "Language name: %s%n" +
    "Language version: %s%n" +
    "Extensions: %s%n" +
    "Mime types: %s%n" +
    "Names: %s%n",
    factory.getEngineName(),
    factory.getEngineVersion(),
    factory.getLanguageName(),
    factory.getLanguageVersion(),
    factory.getExtensions(),
    factory.getMimeTypes(),
    factory.getNames());
   // 得到当前的脚本引擎
   ScriptEngine engine = factory.getScriptEngine();
  }
 }
}


上面的例子必须要在Java SE 6中编译。其中import static java.lang.System.*是新的语法,将System中的所有静态成员进行引用,以后就可以直接使用out、in或err了。

  通过运行java ListScriptEngines,将显示如下信息

Name: Mozilla Rhino
Version: 1.6 release 2
Language name: ECMAScript
Language version: 1.6
Extensions: [js]
Mime types: [application/javascript, application/ecmascript, text/javascript, text/ecmascript]
Names: [js, rhino, JavaScript, javascript, ECMAScript, ecmascript]


  在最下面一行是脚本的别名,也就是使用它们中的任意一个都可以。得到一个具体的脚本引擎有3种方法。

  ·根据扩展名得到脚本引擎

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


  getEngineByExtension的参数就是Extensions:[js]中[…]里的部分。

  ·根据Mime类型得到脚本引擎

ScriptEngine engine = manager.getEngineByMimeType("text/javascript");


  getEngineByMimeType的参数可以是Mime types: [application/javascript, application/ecmascript, text/javascript, text/ecmascript]中的任何一个,可以将text/javascript改成text/ecmascript。

  ·根据名称得到脚本引擎

ScriptEngine engine = manager.getEngineByName("javascript");


  getEngineByName后的参数可以是Names: [js, rhino, JavaScript, javascript, ECMAScript, ecmascript]中的任何一个,如可以将javascript改成ecmascript。

上面已经讨论了执行脚本的第一步,就是得到一个可用的脚本引擎。在完成这项工作之 后就可以利用这个脚本引擎执行相应的脚本了。我们可以使用ScriptEngine的eval方法来执行脚本。eval方法被重载的多次,但最常用的是public Object eval(String script)。
下面的例子演示了如何使用eval方法来执行javascript脚本。

import javax.script.*;
import java.io.*;
import static java.lang.System.*;
public class FirstJavaScript
{
 public static void main(String args[])
 {
  ScriptEngineManager manager = new ScriptEngineManager();
  // 得到javascript脚本引擎
  ScriptEngine engine = manager.getEngineByName("javascript");
  try
  {
   // 开始运行脚本,并返回当前的小时
   Double hour = (Double)engine.eval("var date = new Date();" +"date.getHours();");
   String msg;
   // 将小时转换为问候信息
   if (hour < 10)
   {
    msg = "上午好";
   }
   else if (hour < 16)
   {
    msg = "下午好";
   }
   else if (hour < 20)
   {
    msg = "晚上好";
   }
   else
   {
    msg = "晚安";
   }
   out.printf("小时 %s: %s%n", hour, msg);
  }
  catch (ScriptException e)
  {
   err.println(e);
  }
 }
}

  上面的例子通过得到当前的小时,并将其转化为问候语。上面的程序的输出信息为:

  小时9.0:上午好

  这个例子最值得注意的是执行的2句脚本,最后一句是date.getHours()。并未将这个值赋给一个javascript变量。这时,eval方法就将这样的值返回。这有些类似C语言的(…)运算符。如(c=a+b, c + d),这个表达式的返回值是a+b+d。

和脚本语言进行交互

  上面例子只是运行了一个非常简单的脚本。这个脚本是孤立的,并未通过Java向这脚本传递任何的值。虽然从这个脚本返回了一个值,但这种返回方式是隐式的。

  脚本引擎除了这些简单的功能,还为我们提供了更强大的功能。甚至可以通过Java向脚本语言中传递参数,还可以将脚本语言中的变量的值取出来。这些功能要依靠ScriptEngine中的两个方法put和get。

  put 有两个参数,一个是脚本变量名,另一个是变量的值,这个值是Object类型,因此,可以传递任何值。
  get 有一个参数,就是脚本变量的名。

  下面的代码通过javascript脚本将一个字符串翻转(这个字符串是通过java传给javascript的),然后通过java得到这个被翻转后的字符后,然后输出。

import javax.script.*;
import java.io.*;
import static java.lang.System.*;
public class ReverseString
{
 public static void main(String args[])
 {
  ScriptEngineManager manager = new ScriptEngineManager();
  // 建立javascript脚本引擎
  ScriptEngine engine = manager.getEngineByName("javascript");
  try
  {
   // 将变量name和变量值abcdefg传给javascript脚本
   engine.put("name", "abcdefg");
   // 开始执行脚本
   engine.eval("var output = '';" +
    "for (i = 0; i <= name.length; i++) {" +
    " output = name.charAt(i) + output" +
    "}");
   // 得到output变量的值
   String name = (String)engine.get("output");
   out.printf("被翻转后的字符串:%s", name);
  }
  catch (ScriptException e)
  {
   err.println(e);
  }
 }
}

  以上代码的输出结果为:被翻转后的字符串:gfedcba
让脚本运行得更快

  众所周知,解释运行方式是最慢的运行方式。上述的几个例子无一例外地都是以解释方式运行的。由于Java EE 6的脚本引擎可以支持任何实现脚本引擎接口的语言。有很多这样的语言提供了编译功能,也就是说,在运行脚本之前要先将这些脚本进行编译(这里的编译一般将不是生成可执行文件,而只是在内存中编译成更容易运行的方式),然后再执行。如果某段脚本要运行之交多次的话,使用这种方式是非常快的。我们可以使用ScriptEngine的compile方法进行编译。并不是所有脚本引擎都支持编译,只有实现了Compilable接口的脚本引擎才可以使用compile进行编译,否则将抛出一个错误。下面的例子将演示如何使用compile方法编译并运行javascript脚本。

import javax.script.*;
import java.io.*;
import static java.lang.System.*;
public class CompileScript
{
 public static void main(String args[])
 {
  ScriptEngineManager manager = new ScriptEngineManager();
  ScriptEngine engine = manager.getEngineByName("javascript");
  engine.put("counter", 0); // 向javascript传递一个参数
  // 判断这个脚本引擎是否支持编译功能
  if (engine instanceof Compilable)
  {
   Compilable compEngine = (Compilable)engine;
   try
   {
    // 进行编译
    CompiledScript script = compEngine.compile("function count() { " +
     " counter = counter +1; " +
     " return counter; " +
    "}; count();");
    out.printf("Counter: %s%n", script.eval());
    out.printf("Counter: %s%n", script.eval());
    out.printf("Counter: %s%n", script.eval());
   }
   catch (ScriptException e)
   {
    err.println(e);
   }
  }
  else
  {
   err.println("这个脚本引擎不支持编译!");
  }
 }
}

  上面的代码运行后的显示信息如下:

  Counter: 1.0
  Counter: 2.0
  Counter: 3.0

  在这个例子中,先通过compile方法将脚本编译,然后通过eval方法多次进行调用。在这段代码中只有一个函数,因此,eval就返回了这个函数的值。

动态调用脚本语言的方法

  上面的例子只有一个函数,可以通过eval进行调用并将它的值返回。但如果脚本中有多个函数或想通过用户的输入来决定调用哪个函数,这就需要使用invoke方法进行动态调用。和编译一样,脚本引擎必须实现Invocable接口才可以动态调用脚本语言中的方法。下面的例子将演示如何通过动态调用的方式来运行上面的翻转字符串的javascript脚本。

import javax.script.*;
import java.io.*;
import static java.lang.System.*;
public class InvocableTest
{
 public static void main(String args[])
 {
  ScriptEngineManager manager = new ScriptEngineManager();
  ScriptEngine engine = manager.getEngineByName("javascript");
  if (engine instanceof Invocable)
  {
   try
   {
    engine.eval("function reverse(name) {" +
     " var output = '';" +
     " for (i = 0; i <= name.length; i++) {" +
      " output = name.charAt(i) + output" +
       " } return output;}");
    Invocable invokeEngine = (Invocable)engine;
    Object o = invokeEngine.invoke("reverse", name);
    out.printf("翻转后的字符串:%s", name);
   }
   catch (NoSuchMethodException e)
   {
    err.println(e);
   }
   catch (ScriptException e)
   {
    err.println(e);
   }
  }
  else
  {
   err.println("这个脚本引擎不支持动态调用");
  }
}

动态实现接口

  脚本引擎还有一个更吸引的功能,那就是动态实现接口。如我们要想让脚本异步地执行,即通过多线程来执行,那InvokeEngine类必须实现Runnable接口才可以通过Thread启动多线程。因此,可以通过getInterface方法来使InvokeEngine动态地实现Runnable接口。这样一般可分为3步进行。

  1. 使用javascript编写一个run函数

engine.eval("function run() {print('异步执行');}");


  2. 通过getInterface方法实现Runnable接口

Runnable runner = invokeEngine.getInterface(Runnable.class);


  3. 使用Thread类启动多线程

Thread t = new Thread(runner);
t.start();


  下面是实现这个功能的详细代码。

import javax.script.*;
import static java.lang.System.*;

public class InterfaceTest
{
 public static void main(String args[])
 {
  ScriptEngineManager manager = new ScriptEngineManager();
  ScriptEngine engine = manager.getEngineByName("javascript");
  try
  {
   engine.eval("function run() {print('异步调用');}");
   Invocable invokeEngine = (Invocable)engine;
   Runnable runner = invokeEngine.getInterface(Runnable.class);
   Thread t = new Thread(runner);
   t.start();
   t.join();
  }
  catch (InterruptedException e)
  {
   err.println(e);
  }
  catch (ScriptException e)
  {
   System.err.println(e);
  }
 }
}


  其实上面的代码是通过javascript实现了Runnable接口的run方法。

分享到:
评论

相关推荐

    JavaSE6入门之脚本引擎让程序如虎添翼.txt

    通过JavaSE6中的脚本引擎功能,开发人员可以在Java应用程序中集成多种脚本语言,如JavaScript、PHP、Ruby等,从而提高程序的灵活性和可扩展性。 #### 二、脚本引擎概述 在JavaSE6之前,虽然可以通过一些第三方库来...

    JavaSE6API中文帮助文档.rar

    5. **动态语言支持**:Java SE 6包含了一个Java平台的脚本引擎API(JSR 223),使得可以嵌入各种脚本语言,如JavaScript、Groovy等,增强应用程序的灵活性。 6. **改进的JDBC**:提升了JDBC API,支持自动关闭资源...

    JavaSE6_API

    13. **Scripting API**:`javax.script`包允许在Java应用中执行脚本语言,如JavaScript、Groovy等。 14. **JMX(Java Management Extensions)**:提供了管理和监控Java应用程序的工具和API。 以上只是JavaSE6_API...

    javase-6-doc-api-zh_CN

    开发者可以使用JavaScript、Ruby等脚本语言编写代码,并直接在Java环境中执行。 4. **NIO.2(New I/O 2)** Java 6引入了NIO的升级版NIO.2,增加了文件系统API,如Path类、Files类和FileChannel类的新方法,使文件...

    Java与脚本语言的整合与应用.pdf

    近几年来,搜索引擎的搜索趋势表明,单词“Java”的搜索量略有下降,而搜索脚本语言的名字像JavaScript、Ruby、Python以及Rails的搜索量正在不断增加。有些人认为Java语言将被这些脚本语言所代替。但我们有坚实的...

    JDK1.6(JavaSE1.6/JDK6)

    - **Scripting for the Java Platform**:允许在Java应用程序中嵌入脚本语言,如JavaScript。 JDK1.6之后的版本,如JDK7和JDK8,都引入了更多新特性和优化,但JDK1.6作为Java发展历程中的一环,它的特性和改进为...

    使用java+mysql实现的人员管理系统,附带数据库脚本,直接导入项目创建数据库即可运行

    JavaSE(Java Standard Edition)是Java的基础版本,提供了构建桌面应用所需的类库,适用于此类管理系统。 其次,MySQL是一个流行的开源关系型数据库管理系统,因其高性能、易用性和低成本而被广泛采用。在这个系统...

    Java SE 6 API 中文版 CHM格式

    3. **动态语言支持**:Java 6添加了JSR 223(Scripting for the Java Platform),使得在Java应用程序中嵌入和执行脚本语言成为可能,如JavaScript、Ruby等。 4. **改进的JDBC**:Java数据库连接(JDBC)API在Java ...

    Jdk8下载(附:官网下载地址)

    6. ** Nashorn JavaScript引擎**:Java 8引入了一个新的脚本引擎Nashorn,允许在Java应用中直接执行JavaScript代码,实现了Java与JavaScript之间的互操作性。 7. **Optional类**:为了解决null引用的问题,Java 8...

    Java SE Development Kit 8u181

    7. **新的 Nashorn JavaScript引擎**:JDK 8包含了一个内置的JavaScript引擎,允许Java程序直接执行JavaScript代码,促进了Java与其他脚本语言的交互。 8. **并发改进**:JDK 8对并发工具进行了优化,例如`ForkJoin...

    java 软件开发中文文档全收集打包

    Java软件开发领域涵盖广泛,包括基础的Java Standard Edition (JavaSE)、企业级应用的Java Enterprise Edition (JavaEE)以及前端交互的JavaScript。这个压缩包集合了这些关键领域的中文文档,为开发者提供全面的学习...

    java se6 全方位学习 ---源代码及附录

    4. **动态语言支持**:Java 6添加了Java Dynamic Language Toolkit(JDT),允许在Java平台上运行脚本语言,如JavaScript和Ruby。 5. **改进的内存管理**:包括更高效的垃圾回收机制,例如并行和并发GC策略,提升了...

    Java JavaWeb 数据库等开发参考手册四

    3. **JavaScript (JS)**: JavaScript是Web开发中的客户端脚本语言,主要用于网页交互和动态效果。它与Java虽然名字相似,但两者并无直接关联。JavaScript API通常指的是浏览器提供的DOM(Document Object Model)...

    制作鼠标悬浮变色java脚本.html

    用javascript 编译的制作鼠标悬浮变色java脚本.html

    Java8学习全套PPT

    7. ** Nashorn JavaScript引擎**:Java8引入了Nashorn JavaScript引擎,使得在Java应用中可以直接执行JavaScript代码,增强了Java与脚本语言的交互能力。 8. **并行和并发改进**:Java8对并行和并发进行了优化,...

    javase javaee linux 大数据教程

    - jQuery 等 JavaScript 库简化客户端脚本编写。 - **Linux系统管理**: - Linux 是服务器领域广泛使用的操作系统之一。 - 掌握基本的 Linux 命令行操作对部署和维护应用程序至关重要。 - **大数据技术**: - ...

    Java JavaWeb 数据库等开发参考手册二

    JavaScript,虽然名字中带有"Java",但实际上是一种完全不同的脚本语言,主要用于Web前端开发。它可以操纵DOM(Document Object Model),实现动态网页效果,处理用户输入,与服务器进行异步通信(AJAX),并通过库...

    Java JavaWeb 数据库等开发参考手册三

    《Java JavaWeb 数据库等开发参考手册三》是一份涵盖了JavaEE、JavaSE以及JavaScript API的综合开发资源,旨在为开发者提供便捷的函数查询和学习资料。这份文档以CHM(Compiled HTML Help)格式呈现,使得信息检索...

    张龙 java web 课堂ppt

    4. **Servlet**:Servlet是Java中的一个接口,用于扩展服务器的功能,特别是处理HTTP请求。它们通常用于接收来自客户端的请求,处理业务逻辑,并返回响应。Servlet生命周期包括加载、初始化、服务、销毁等阶段,是...

Global site tag (gtag.js) - Google Analytics