zoukankan      html  css  js  c++  java
  • JDK1.7新特性(3):java语言动态性之脚本语言API

    简要描述:其实在jdk1.6中就引入了支持脚本语言的API。这使得java能够很轻松的调用其他脚本语言。具体API的使用参考下面的代码:

      1 package com.rampage.jdk7.chapter2;
      2 
      3 import java.io.FileWriter;
      4 import java.io.IOException;
      5 
      6 import javax.script.Bindings;
      7 import javax.script.Compilable;
      8 import javax.script.CompiledScript;
      9 import javax.script.Invocable;
     10 import javax.script.ScriptContext;
     11 import javax.script.ScriptEngine;
     12 import javax.script.ScriptEngineManager;
     13 import javax.script.ScriptException;
     14 import javax.script.SimpleBindings;
     15 
     16 /**
     17  * 简单的脚本引擎使用方法
     18  * 
     19  * @author zyq
     20  *
     21  */
     22 public class SimpleScriptAPI {
     23     public static void main(String[] args) throws ScriptException, IOException, NoSuchMethodException {
     24         SimpleScriptAPI simpleScriptEngine = new SimpleScriptAPI();
     25         
     26         // Part 1: 通用的脚本引擎用法
     27         ScriptEngine engine = simpleScriptEngine.getJavaScriptEngine();
     28         if (engine == null) {
     29             throw new RuntimeException("找不到JavaScript脚本执行引擎!");
     30         }
     31         engine.eval("var a = 12;");
     32         
     33         // Part 2: 不同脚本语言与java之间的对象绑定
     34         engine.put("name", "Alex");
     35         engine.eval("var message = 'hello ' + name");
     36         Object message = engine.get("message");
     37         System.out.println(message);         // hello Alex
     38         
     39         // 当然也可以通过SimpleBinds对象来进行变量绑定或者通过脚本引擎的createBindings方法
     40         Bindings bindings = new SimpleBindings();
     41         bindings = engine.createBindings();
     42         bindings.put("hobby1", "java");
     43         bindings.put("hobby2", "dota");
     44         engine.eval("var message2 = 'I like ' + hobby1 + ' and ' + hobby2", bindings);
     45         // 使用binding来绑定的变量只能在脚本语言内部是使用,java语言内获取不到对应的变量
     46         System.out.println(engine.get("message2"));        // null 
     47         System.out.println(engine.get("hobby1"));        // null
     48         System.out.println(engine.get("hobby2"));        // null
     49         engine.put("hobby1", "java");
     50         engine.put("hobby2", "dota");
     51         engine.eval("var message2 = 'I like ' + hobby1 + ' and ' + hobby2"); 
     52         System.out.println(engine.get("message2"));   // I like java and dota
     53         System.out.println(engine.get("hobby1"));      // java
     54         System.out.println(engine.get("hobby2"));      // dota
     55         
     56         // Part 3: 脚本执行上下文
     57         // ScriptContext的setReader/setWriter/setErrorWriter可以分别设置脚本执行时候的输入来源,输出目的地和错误输出目的地
     58         ScriptContext context = engine.getContext();
     59         context.setWriter(new FileWriter("output.txt"));
     60         engine.eval("var a = 13");
     61         // ScriptContext中也有setAttribute和getAttribute方法来自定义属性。属性有不同的作用域之分。
     62         // 每个作用域都以一个对应的整数表示其查找顺序,该整数越小,说明查找时的顺序更优先。
     63         // 因此在设置属性时需显示的指定所在的作用域,在获取属性的时候可以指定查找的作用域。也可以选择根据作用域优先级
     64         // 自动进行查找。
     65         // 但是脚本执行上下文所能包含的作用域可以通过 getScopes 方法得到而不能随意指定
     66         System.out.println(context.getScopes());        // [100, 200]
     67         // ScriptContext预先定义了两个作用域: ENGINE_SCOPE(当前脚本引擎) 和 GLOBAL_SCOPE(从同一引擎工厂创建出来的所有脚本引擎),前者的优先级更高
     68         context.setAttribute("name", "Alex", ScriptContext.GLOBAL_SCOPE);
     69         context.setAttribute("name", "Bob", ScriptContext.ENGINE_SCOPE);
     70         System.out.println(context.getAttribute("name"));        // Bob
     71         // ScriptContext的setbindings方法设置的语言绑定对象会影响到ScriptEngine在执行脚本时的变量解析。
     72         // ScriptEngine的put和get方法所操作的实际上就是ScriptContext中作用域为ENGINE_SCOPE的语言绑定对象。
     73         // 从ScriptContext中得到语言绑定对象之后,可以直接对这个对象进行操作。如果在ScriptEngine的eval中没有
     74         // 指明所使用的语言绑定对象,实际上起作用的是ScriptContext中作用域为ENGINE_SCOPE的语言绑定对象。
     75         Bindings binding1 = engine.createBindings();
     76         binding1.put("name", "Alex");
     77         context.setBindings(binding1, ScriptContext.GLOBAL_SCOPE);
     78         Bindings binding2 = engine.createBindings();
     79         binding2.put("name", "Bob2");
     80         context.setBindings(binding2, ScriptContext.ENGINE_SCOPE);
     81         System.out.println(engine.get("name"));        // Bob2
     82         Bindings binding3 = context.getBindings(ScriptContext.ENGINE_SCOPE);
     83         binding3.put("name", "Alex2");
     84         System.out.println(engine.get("name"));        // Alex2
     85         context.setAttribute("name", "Bob3", ScriptContext.ENGINE_SCOPE);
     86         System.out.println(engine.get("name"));        // Bob3
     87         
     88         // Part 4: 脚本的编译
     89         // 脚本语言一般是解释执行的,脚本引擎在运行时需要先解析脚本之后再执行。一般来说
     90         // 通过解释执行的方式运行脚本的速度比先编译再运行会慢一些。所以对于需要多次执行的脚本,我们
     91         // 可以选择先编译,以防止重复解析。不是所有的脚本语言都支持对脚本进行编译,如果脚本支持
     92         // 编译,他会实现 javax.script.Compilable接口。编译的结果用CompiledScript来表示。
     93         if (engine instanceof Compilable) {
     94             CompiledScript script  = ((Compilable) engine).compile("var a = 12; b = a * 3;");
     95             script.eval();
     96         }
     97         
     98         // Part 5: 方法调用
     99         // 有些脚本引擎允许使用者单独调用脚本中的某个方法。支持这种调用方法的脚本引擎可以实现
    100         // javax.script.Invocable 接口。通过Invocable接口既可以调用脚本中的顶层方法,也可一
    101         // 调用对象中的成员方法。如果脚本中的顶层方法或者对象中的成员方法实现了java中的接口,
    102         // 可以通过Invocable接口中的方法来获取及脚本中对应的java接口 的实现对象。这样就可以
    103         // 在java中定义借口,在脚本中实现接口。程序中使用该接口的其他部分代码并不知道接口是
    104         // 由脚本来实现的。
    105         String scriptText = "function greet(name) {return 'hello ' + name; }";
    106         engine.eval(scriptText);
    107         Invocable invocable = (Invocable) engine;
    108         System.out.println(invocable.invokeFunction("greet", "Alex"));  // hello Alex
    109         // 如果调用的是脚本中对象的成员方法,则需要用invokeMethod.
    110         scriptText = "var obj = {getGreeting: function(name) {return 'hello ' + name;}};";
    111         engine.eval(scriptText);
    112         Object scope = engine.get("obj");
    113         System.out.println(invocable.invokeMethod(scope, "getGreeting", "Bob"));  // hello Bob
    114         // 在脚本中实现接口
    115         scriptText = "function getGreeting(name) {return 'Hello ' + name;}";
    116         engine.eval(scriptText);
    117         Greet greet = invocable.getInterface(Greet.class);        // 接口必须是public类型的
    118         System.out.println(greet.getGreeting("KiDe"));
    119     }
    120 
    121     private ScriptEngine getJavaScriptEngine() {
    122         ScriptEngineManager manager = new ScriptEngineManager();
    123         // PS: 通过脚本引擎管理者来获取对应引擎,有三种方法:一是通过getEngineByName(这时只能是 javascript 或者
    124         // JavaScript)
    125         ScriptEngine engine = manager.getEngineByName("JavaScript");
    126         // 第二种方法是通过 getEngineByExtension (这时候只能是全小写的js)
    127         // engine = manager.getEngineByExtension("js");
    128         // 第三种方法是通过 getEngineByMimeType (这时候也必须是全小写的 text/javascript)
    129         // engine = manager.getEngineByMimeType("text/javascript");
    130         
    131         return engine;
    132     }
    133 }
    SimpleScriptAPI
    1 package com.rampage.jdk7.chapter2;
    2 
    3 public interface Greet {
    4     String getGreeting(String name);
    5 }
    Greet
  • 相关阅读:
    ruby 二进制转十进制 Integer("0b101") = 5
    开始菜单和我的文档的我的图片及我的音乐变成 my pictrues 正常图标了
    ruby watir 莫名其妙的错误
    Excel SaveAS是去掉提示框
    apache && jboss安装
    ruby require include的区别
    ruby控制鼠标
    This error is raised because the column 'type' is reserved for storing the class in case of inheritance
    用正则表达式限制文本框只能输入数字,小数点,英文字母,汉字等各类代码
    ASP.NET 如何动态修改 Header 属性如添加 Meta 标签 keywords description!
  • 原文地址:https://www.cnblogs.com/Kidezyq/p/5754646.html
Copyright © 2011-2022 走看看