Java学习笔记–脚本语言帮衬API

Java语言的动态性之脚本语言辅助API

       随着Java平台的盛行,很多的脚本语言(scripting language)都可以运作在Java虚拟机啊上,其中比较流行的有JavaScript、JRuby、Jython和Groovy等。相对Java语言来说,脚本语言由于其灵活性极度强,极度适合在好几意况下行使,比如描述应用中复杂多变的事务逻辑,并在采纳运行进度中展开动态修改;为运用提供一种世界特定语言(Domainspecific Language,DSL),供没有技术背景的普通用户使用;作为利用中种种零部件之间的“胶水”,飞快展开零部件之间的三结合;急速支付出利用的原型系统,从而飞速取得用户举报,并开展改良;辅助开发人士快速编写测试用例等。等于这一个场景,要是利用java来开发则事倍功半。

       对于这几个运行在Java虚拟机平台上的脚本语言来说,并不必要为他们准备额外的运作环境,直接复用已部分Java虚拟机环境即可。那就节省了在运行环境上所需的资金投入。在应用开发中应用脚本语言,实际上是“多语言开发”的一种很好的实施,即基于使用的急需和言语本身的特征来挑选最合适的成为语言,以很快高效地解决选拔中的某一部分标题。各类差别语言完结的组件组合起来,用Java编写焦点业务逻辑,用Ruby来开展数量处理。分化语言编写的代码可以同时运行的同一个Java虚拟机之上。那么些脚本语言和Java语言之间的并行,是由脚本语言援助API来落成的。

1.脚本发动机

     
 一段脚本的施行要求由该脚本语言对应的本子引擎来落成。一个Java程序可以选拔同时富含各种脚本语言的实践引擎,那全然由程序的必要来支配。程序中所用到的脚本语言,都亟待有对应的剧本引擎。JSR
233中定义了本子引擎的注册和搜索体制。那对于脚本引擎的落成者来说,是亟需精晓的。而貌似的开发人士只需求通晓哪些通过脚本引擎管理器来获取相应语言的台本引擎,并不要求精晓脚本引擎的登记机制。Java
SE6中自带了JavaScript语言的本子引擎,是基于Mozilla的Rhino来落成的。对于别的的脚本语言,则需求下载对应的本子引擎的库并放在程序的类路径中。一般只要放在类路径中中,脚本引擎就可以被应用程序发现并选取。
       
首先介绍脚本引擎的形似用法。首先创立一个剧本引擎管理器javax.script.ScriptEngineManager对象,再经过管理器来查询所需的JavaScript脚本引擎,最终经过脚本引擎来执行JavaScript代码。

ScriptEngineManagerDemo

Java 1

实践结果

Java 2

     
 上边的代码中是通过脚本引擎的名字举行搜寻的。实际上,脚本引擎管理共扶助三种检索脚本引擎的法子,分别通过名称、文件扩大名和MIME类型来成功。

2.语言绑定

     
 脚本语言扶助API的一个很大优势在于它规范了Java语言与脚本语言之间的交互格局,使Java语言编写的顺序可以与剧本之间展开双向的法子调用和数量传递。方法调用的点子会在稍后介绍。数据传递是通过言语绑定对象来完毕的。所谓的绑定对象就是一个粗略的哈希表,用来存放和得到需求共享的数目。所有数据都对应以此哈希表中的一个条文,是概括的名值对。接口javax.script.Bindings定义了语言绑定对象的接口,继承自java.util.Map接口。一个本子引擎在举行进度中可能会动用三个语言绑定对象。分化语言绑定对象的作用域差别。在默认情状下,脚本引擎会提供七个语言绑定对象,用来存放在实施进程中发出全局对象等。ScriptEngine类提供了put和get方法对台本引擎中一定功效域的默许语言绑定对象进行操作。程序可以平昔利用这几个默许的语言绑定对象,也足以利用自己的言语绑定对象。在脚本语言的履行进度中,可以将语言绑定对象看成是一个附加的变量映射表。在分析变量值的时候,语言绑定对象中的名称也会被考虑在内。脚本执行进度中生出的全局变量等内容,会油但是生在言语绑定对象中。通过那种措施就完了了Java与脚本语言之间的双向数据传递。

剧本引擎默许的语言绑定对象的以身作则

    /**
    * 脚本引擎默认的语言绑定对象的示例
     */
    public static void useDefaultBinding(){
        try{
            ScriptEngine  engine = getJavaScriptEngine();
            engine.put("name","Arthur");
            engine.eval("var message = 'Hello,' + name;");
            engine.eval("print(message);");
            Object obj = engine.get("message");
            System.out.println(obj);
        }catch (Exception e){
            System.out.println("异常信息:"+e.getMessage());
        }
    }

剧本引擎默许的言语绑定对象的演示执行结果

Java 3

    在大多数气象下,使用ScriptEngine的put和get方法就足足了。假如仅使用put和get方法,语言绑定对象自我对于开发人员来说是晶莹的。在一些意况下,须要拔取程序自己的语言绑定对象,比如语言绑定对象中涵盖了先后自己独有的数目。若是希望利用自己的语言绑定对象,可以调用脚本引擎的createBindings方法或创设,并传递给脚本引擎的eval方法。

自定义语言绑定对象的言传身教

    /**
     * 自定义语言绑定对象的示例
     */
    public static void userCustomBinding(){
        try{
            ScriptEngine engine = getJavaScriptEngine();
            Bindings bindings = new SimpleBindings();
            bindings.put("hobby","playe games");
            engine.eval("print('I like ' + hobby);",bindings);
        }catch(Exception e){
            System.out.println("异常信息:"+e.getMessage());
        }
    }

自定义语言绑定对象的示范的执行结果

Java 4

    通过eval方法传递的语绑定对象,仅在当下eval调用中生效,并不会转移引擎默许的语言绑定对象。

3.脚本实施上下文

    与剧本引擎执行有关的此外一个关键的接口是javax.script.ScriptContext,其中带有脚本引擎执行进度的相干上下文音信,可以透过与Java
EE中servlet规范中的javax.servlet.ServletContext接口来开展类比。脚本引擎通过此上下文对象得到与剧本执行相关的音信,也同意开发人士通过此目的来布局脚本引擎的一言一动。该上下文对象首要含有以下3类音讯:

3.1输入与输出

    首先介绍与脚本输入和输出的陈设信息,其中囊括脚本在推行中用来读取数据输入的java.io.Reader对象以及出口正确内容和失误音信的java.io.Writer对象。在默许情形下,脚本的输入输出都在暴发在正儿八经控制塞内加尔达喀尔。

把脚本运行时的输出写入到文件中的示例

    /**
     * 把脚本运行时的输出写入到文件中。
     */
    public static void scriptToFile(){
        try {
            ScriptEngine engine = getJavaScriptEngine();
            ScriptContext context = engine.getContext();
            context.setWriter(new FileWriter("output.txt"));
            engine.eval("print('Hello World!');");
        } catch (ScriptException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

施行结果

Java 5

说明
    通过setWriter方法把剧本的出口重定向到一个文本中。通过ScriptContext的set里德r和setErrorWriter方法可以分级设置脚本执行时的数码输入来源和爆发错误时出错信息的输出目标。

3.2自定义属性

    ScriptContext中也有与ServletConext中近乎的获得和设置属性的办法,即setAttribute和getAttribute。所例外的是,ScriptContext中的属性是有作用域之分的。分歧功能域的分别在于寻找属性时的逐条差别。每个功效域都以一个相应的整数表示其搜索顺序。该整数值越小,表达查找时的顺序越优先。优先级高的成效域中的属性会暗藏优先级低的作用域中的同名属性。因此,设置属性时必要显式地指定所在地功能域。在收获属性地时候,既可以挑选在指定地成效域中寻找,也得以接纳依据功能域优先级活动举行搜索。
    不过脚本执行上下文落成中富含地效能域是定点的,开发人士不可能随随便便定义自己的功效域。通过ScriptContext的getScopes方法可以取得所有可用的成效域列表。ScriptContext中优先定义了三个成效域:

  • 常量ScriptContext.ENGINE_SCOPE表示的功用域对应的是眼下的台本引擎。
  • 常量ScriptContext.GLOBAL_Java,SCOPE表示的成效域对应的是从同一引擎工厂中创设出来的保有脚本引擎对象。

    说明: 前者的先行级较高

#### 作用域影响同名属性查找示例

       /**
     * 作用域影响同名属性查找的示例
     */
    public static void scriptContextAttribute(){
        try{
            ScriptEngine engine = getJavaScriptEngine();
            ScriptContext context = engine.getContext();
            context.setAttribute("name","Arthur Ming",ScriptContext.GLOBAL_SCOPE);
            context.setAttribute("name","明国宾",ScriptContext.ENGINE_SCOPE);
            System.out.println(context.getAttribute("name"));
            System.out.println(context.getAttribute("name",ScriptContext.GLOBAL_SCOPE));
        } catch(Exception e){
            System.out.println("异常信息:"+e.getMessage());
        }
    }

#### 执行结果

![](https://images2015.cnblogs.com/blog/1001991/201703/1001991-20170326223034830-213077996.png)

3.1言语绑定对象

    脚本实施上下文中的末梢一类信息是语言绑定对象。语言绑定对象也是与作用域相对应的,同样的效用域优先级依次对语言绑定对象也适用。那样的预先级依次会对台本执行时的变量解析暴发震慑。

语言绑定对象的预先级依次的以身作则

    /**
     * 语言绑定对象的优先级顺序的示例
     */
    public static void scriptContextBindings(){
        try {
            ScriptEngine engine = getJavaScriptEngine();
            ScriptContext context = engine.getContext();
            Bindings binding1 = engine.createBindings();
            binding1.put("name","Arthur Ming");
            context.setBindings(binding1,ScriptContext.GLOBAL_SCOPE);
            Bindings binding2 = engine.createBindings();
            binding2.put("name","明国宾");
            context.setBindings(binding2,ScriptContext.ENGINE_SCOPE);
            engine.eval("print(name)");
        } catch (Exception e){
            e.printStackTrace();
        }
    }

执行结果

Java 6

    通过ScriptContext的setBindings方法设置的语言绑定对象会影响到ScriptEngine在实践脚本时变量解析。ScriptEngine的put和get方法所操作的其实就是ScriptContext中的功用域为ENGINE_SCOPE的言语绑定对象。

通过脚本执行上下文获取语言绑定对象的以身作则

   /**
     * 通过脚本执行上下文获取语言绑定对象的示例
     */
    public static void useScriptContextValues(){
        try{
            ScriptEngine engine = getJavaScriptEngine();
            ScriptContext context = engine.getContext();
            Bindings bindings = context.getBindings(ScriptContext.ENGINE_SCOPE);
            bindings.put("name","Arthur Ming");
            engine.eval("print(name)");
        } catch (Exception e){
            e.printStackTrace();
        }
    }

履行结果

Java 7

    自定义属性实际上也保留在言语绑定对象中。

自定义属性保存在语言绑定对象中示范

    /**
     * 自定义属性保存在语言绑定对象中示例
     */
    public static void attributeInBindings(){
        try{
            ScriptEngine engine = getJavaScriptEngine();
            ScriptContext context = engine.getContext();
            context.setAttribute("name1","Arthur Ming",ScriptContext.GLOBAL_SCOPE);
            context.setAttribute("name2","明国宾",ScriptContext.ENGINE_SCOPE);
            engine.eval("print(name1);");
            engine.eval("print(name2);");
        }catch (Exception e){
            e.printStackTrace();
        }
    }

推行结果

Java 8

相关文章