JDK1.6 Java Scripting Programmer's Guide 翻译

来源:互联网 发布:vb和java 编辑:程序博客网 时间:2024/05/16 14:12
 

Java Scripting Programmer's Guide


Who is the Java Scripting API For?

下面是一些有用的脚本语言特性:

  • 方便:大多数脚本语言是动态类型的,你通常可以不用声名变量类型而创建一个新的变量,同时还可以为变量重新赋予一个完全不同类型的值。脚本语言会自动执行类型转换,例如,他在必要的情况下,会在10和“10”之间自动完成转换。

  • 快速开发模型:你可以完全避免“编辑-编译-运行”的流程,而直接“编辑-运行”。

  • 应用扩展/定制:你可以“定制”程序的很多部分-比如财务应用的脚本配置、业务逻辑规则和数学公式。

  • 为了诸如进行调试、运行时和部署时配置,大多数应用都提供一个给予WebGUI配置工具。但系统管理员们或者是部署人员常常喜欢使用命令行工具。

JavaTM Scripting API是脚本语言无关的Java代码运行脚本引擎的框架。使用Java代码编写可定制扩展的应用并将脚本语言的定制留给终端用户,JavaTM Scripting API使之成为可能。Java应用开发者不需要在开发阶段选择将要扩展的语言。如果你的应用遵从JSR223 API,那么你的用户将可以使用任何遵从JSR223 API的脚本语言。


Scripting Package

Java Script 功能包含在javax.script包中,这是一个相对小而且简单的API。脚本API的入口点是ScriptEngineManager类。一个ScriptEngineManager对象能够通过Jar文件服务发现机制找到脚本引擎,并实例化一个ScriptEngine对象,该对象将解释用特定语言编写的脚本。使用脚本API最简单的方式如下:

  1. 创建一个ScriptEngineManager对象

  2. 从这个管理器对象得到一个ScriptEngine对象

  3. 利用ScriptEngineeval方法执行脚本

现在,我们来看一些示例代码。


Examples

"Hello, World"

    利用getEngineByName方法从我们的ScriptEngineManager实例中请求一个JavaScript引擎实例。在这个脚本引擎中,eval方法用来执行作为字符串传入的一段JavaScript代码!为了简短起见,我们在后面不展示异常处理部分,那些异常由javax.script API抛出。

                
    import javax.script.*;

    public class EvalScript {
           
    public static void main(String[] args) throws Exception {
                     
    //创建脚本引擎管理器
                    ScriptEngineManager factory = new ScriptEngineManager(); 
                    
    //得到一个JavaScript脚本引擎 
                    ScriptEngine engine = factory.getEngineByName("JavaScript");
                    
    //运行作为字符串传入的脚本代码
                    engine.eval("print('Hello, World')"); 
             }

     }

Evaluating a Script File

    在这个例子中,我们的eval方法接受一个java.io.Reader最为输入源。利用这种方式,
我们可以运行来自脚本文件、
URLs或者封装为输入对象的脚本资源。
 
import javax.script.*;


public class EvalFile ...
            
public static void main(String[] args) throws Exception ...
                      
//创建脚本引擎管理器 
                      ScriptEngineManager factory = new ScriptEngineManager(); 
                      
//得到一个JavaScript脚本引擎
                       ScriptEngine engine = factory.getEngineByName("JavaScript");
                       
//运行来自文件的脚本代码 
                      engine.eval(new java.io.FileReader(args[0])); 
            }

}

Script Variables

    当你在应用中嵌入脚本引擎和脚本时,可能想把程序中的对象作为全局变量暴露给脚本。这个例子
演示了如何将应用程序的对象最为全局变量暴露给脚本。我们在程序中创建一个
java.io.File对象,
并将它作为全局变量“
file”暴露给脚本。现在,脚本便可以对这个对象进行存取操作了--比如,
它可以调用这个对象的
public方法。
       
            public class ScriptVars 

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

                           File f 
    = new File("test.txt"); 
                           
    //将File对象作为脚本全局变量导出 
                        engine.put("file", f);  
                           engine.eval(
    "print(file.getAbsolutePath())");  
                   }
     
            }
     


Invoking Script Functions and Methods

    有时候,你希望反复调用一个特定脚本函数--例如,你的应用当中的菜单功能可能是利用脚本
实现的,菜单时间的处理中你可能希望调用一个特定的脚本函数。下面的例子演示了如何通过
Java
代码调用脚本函数:

 
import javax.script.*;

public
 class InvokeScriptFunction {
             
public static void main(String[] args) throws Exception 
                ScriptEngineManager manager 
= new ScriptEngineManager();  
                   ScriptEngine engine 
= manager.getEngineByName("JavaScript"); 
                 String script 
= "function hello(name) { print('Hello, ' + name); }";  
                       engine.eval(script);

                  
//javax.script.Invocable是一个可选接口 
                
//检查你的脚本引擎是否实现了该接口 
                
//JavaScript引擎实现了Invocable接口. 
                Invocable inv = (Invocable) engine; 

                 
//调用脚本的全局函数"hello"  
                  inv.invokeFunction("hello""Scripting!!" ); 
            }

}

如果你的脚本语言是基于对象或者面向对象的,那么你还可以调用脚本对象的方法:

 

    

import javax.script.*;

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

                     
// JavaScript 代码是一个字符串,定义了一个脚本对象'obj'
                     
//这个对象带有一个方法,名为'hello'.        
                     String script = "var obj = new Object(); obj.hello = function(name) { print('Hello, ' + name); }";

                     engine.eval(script);
                     Invocable inv 
= (Invocable) engine;

                     
//得到脚本对象引用
                     Object obj = engine.get("obj");

                     
//调用脚本对象的方法“hello”并传入参数字符串
                     inv.invokeMethod(obj, "hello""Script Method !!" );
         }

}

Implementing Java Interfaces by Scripts

    为了替代Java中的脚本函数调用,有时候可以利用脚本方法活函数来实现Java接口。同时,使用这种
方式我们就可以避免在很多地方使用
javax.script API,我们可以得到一个接口的实现对象,并把它传
给各种
Java API.下面的代码演示了如何利用脚本实现java.lang.Runnable接口:
 
    import javax.script.*; 
     
public class RunnableImpl {  
            
public static void main(String[] args) throws Exception 
                   ScriptEngineManager manager 
= new ScriptEngineManager();  
                          ScriptEngine engine 
= manager.getEngineByName("JavaScript"); 

                    String script 
= "function run() { println('run called'); }";   
                         engine.eval(script);  
                      Invocable inv 
= (Invocable) engine;   

                          
//从引擎得到Runnable 接口的实现对象. 接口方法利用脚本中同名的函数来实现
                           Runnable r = inv.getInterface(Runnable.class);                                                                  
                          Thread th 
= new Thread(r);         
                   th.start();                         
                }
     
        }
     
 


如果你的脚本语言是基于对象或面向对象的,你就可以利用脚本对象上的方法活函数来实现一个
Java接口,
这样就避免了为接口而调用脚本的全局函数。脚本对象可以存储与接口实现者相关的状态。

import javax.script.*
public class RunnableImplObject 
      
public static void main(String[] args) throws Exception 
               ScriptEngineManager manager 
= new ScriptEngineManager(); 
               ScriptEngine engine 
= manager.getEngineByName("JavaScript");
  
               String script 
= "var obj = new Object(); obj.run = function() { println('run method called'); }";
                engine.eval(script);
              
//得到脚本中的接口实现对象
               Object obj = engine.get("obj"); 
               Invocable inv 
= (Invocable) engine;  

              
//从引擎得到Runnable 接口的实现对象. 接口方法利用脚本对象中的方法来实现 
               Runnable r = inv.getInterface(obj, Runnable.class); 
               Thread th 
= new Thread(r);   
               th.start();    
       }
     
}


Multiple Scopes for Scripts

    Script Variables的例子中,我们看到如何将Java中的对象作为脚本的全局变量暴露出来。现在我们
将看到,将
Java对象暴露给脚本的多种作用于也是可能的。一个单一作用域是javax.script.Bindings
一个实例,这个实例源自
java.util.Map<String,Object>。多作用域有javax.script.ScriptContext接口
提供。一个脚本上下文通过互相关联的
Bindings提供了一个或多个作用域。在默认情况下,每一个脚本引擎
有一个默认的脚本上下文,这个默认上下文至少有一个名为“
ENGINE_SCOPE”的作用域。脚本提供的各种
作用域可以通过
getScopes方法得到。

 import javax.script.*;  
public class MultiScopes 
              
public static void main(String[] args) throws Exception 
                           ScriptEngineManager manager 
= new ScriptEngineManager();                                            
                      ScriptEngine engine 
= manager.getEngineByName("JavaScript"); 

                    engine.put(
"x""hello"); 
                   engine.eval(
"println(x);");  
                          
//上面一行打印 "hello"  

                      
//现在,传递一个不同的脚本上下文 
                   ScriptContext newContext = new SimpleScriptContext(); 
                     Bindings engineScope 
= newContext.getBindings(ScriptContext.ENGINE_SCOPE);   

                     
//添加一个新的变量 "x" 到新的engineScope  
                          engineScope.put("x""world");                                                     
                  engine.eval(
"println(x);", newContext); 
                  
//上面一行打印 "world"   
          }
     
}
  


JavaScript Script Engine

 
原创粉丝点击