現在的位置: 首頁 > 編程語言 > 正文

哪些腳本語言支持API

2020年06月08日 編程語言 ⁄ 共 7224字 ⁄ 字型大小 評論關閉

  JAVA語言是一種靜態類型的編程語言。靜態類型的含義是指在編譯的時候進行類型檢查。JAVA源代碼中的每個每個變數的類型都需要顯式地進行聲明。所有的變數、方法的參數和返回值的類型在程序運行之前就必須是已知的。下面學步園小編來講解下哪些腳本語言支持API?

  哪些腳本語言支持API

  隨著JAVA平台的流行,很多的腳本語言(scriptinglanguage)都可以運行在JAVA虛擬機上,其中比較流行的有JavaScript、JRuby、Jython和Groovy等。對於這些運行在JAVA虛擬機平台上的腳本語言來說,並不需要為它們準備額外的運行環境,直接復用已有的JAVA虛擬機環境即可。在應用開發中使用腳本語言,實際上是"多語言開發"的一種很好的實踐,即根據應用的需求和語言本身的特性來選擇最合適的變成語言,以快速高效的解決應用中的問題,比如一個一用,可以用Groovy來編寫用戶界面,用Java編寫核心業務邏輯,用Ruby來進行數據處理,不同的語言編寫的代碼可以同時運行在同一個JAVA虛擬機上。這些腳本語言於Java語言之間的交互,是由腳本語言支持API來完成的。

  1、腳本引擎

  來一個簡單的例子(相當於java中System.out.println方法),了解一下腳本引擎的用法,代碼如下

  publicvoidgreet()throwsScriptException{

  ScriptEngineManagermanager=newScriptEngineManager();

  ScriptEngineengine=manager.getEngineByName("JavaScript");

  if(engine==null)

  thrownewRuntimeException("未找到JavaScript語言執行引擎");

  engine.eval("println('HelloWorld!');");

  }

  上面的代碼中我們是通過腳本引擎的名稱來查找的。實際上,腳本引擎管理器提供了三種查找腳本引擎的方式,分別是通過名稱、文件擴展名和MIME類型來完成,如:

  ScriptEngineengine=manager.getEngineByExtension("js");

  ScriptEngineengine=manager.getEngineByMimeType("text/javascript");

  ScriptEngineengine=manager.getEngineByName("JavaScript");

  2、語言綁定所謂的語言綁定對象就是一個簡單的哈希表,用來存放和獲取需要共享的數據。所有的數據都對應這個哈希表中的一個條目,是簡單的鍵值對。介面javax.script.Bindings定義了語言綁定對象的介面,它繼承自java.util.Map介面。一個腳本引擎在執行過程中可能會使用多個語言綁定對象,用來存放在執行過成功產生的全局對象等。ScriptEngine類提供了put和get方法對腳本引擎中特定作用域的默認語言綁定對象進行操作。程序可以直接使用這個默認的語言綁定對象,也可以使用自己的語言綁定對象。在腳本語言的執行過程中,可以將語言綁定對象看成是一個額外的變數映射表。

  腳本引擎默認的語言綁定對象示例:

  首先通過ScriptEngine的put方法向腳本引擎默認的語言綁定對象中添加一個名為name的字元串,接著在腳本中直接根據名稱來引用這個對象。同樣,在腳本中創建的全局變數message也可以通過ScriptEngine的get方法來獲取。這樣就實現了Java程序與腳本之間的雙向數據傳遞。數據傳遞過程中的類型轉換是有腳本引擎類完成的,轉換規則取決於具體的腳本語言的語法。

  publicvoiduseDefaultBinding()throwsScriptException{

  ScriptEngineengine=getScriptEngine();

  engine.put("name","andy");

  engine.eval("varmessage='Hello,'+name;");

  engine.eval("println(message);");

  Objectobj=engine.get("message");

  System.out.println(obj);

  }

  自定義語言綁定對象的示例:

  如果希望使用自己的語言綁定對象,可以調用腳本引擎的createBindings方法或者創建一個javax.script.SimpleBindings對象,並傳遞給腳本引擎的eval方法。通過eval方法傳遞的語言綁定對象,僅在當前eval調用中生效,並不會改變引擎默認的語言綁定對象

  publicvoiduseCustomBinding()throwsScriptException{

  ScriptEngineengine=getScriptEngine();

  Bindingsbindings=newSimpleBindings();

  bindings.put("hobby","playinggemes");

  engine.eval("println('Ilike'+hobby);",bindings);

  }

  3、腳本執行上下文

  與腳本引擎相關的另外一個重要的介面是javax.script.ScriptContext,其中包含腳本引擎執行過程中的相關上下文信息,可以與JavaEE中的servlet規範中的javax.servlet.ServletContext介面進行類型。腳本引擎通過此上下文對象來獲取與腳本執行相關的信息,也允許開發人員通過次對象類配置腳本引擎的行為。該上下文對象中主要包括3類信息。

  3.1、輸入輸出

  其中包括腳本在執行中用來讀取數據輸入的java.io.Reader對象以及輸出正確內容和錯誤信息的java.io.Writer對象。在默認情況下,腳本的輸入輸出都發生在標準控制台中,如果希望把腳本的輸出寫入到文件中,可以通過setWriter方法把腳本的輸出重定向到一個文件中。通過ScriptContext的setReader和setErrorWriter方法可以分別設置腳本執行時的數據出入來源和產生錯誤時的出錯信息的輸出目的。代碼如下:

  publicvoidscriptToFile()throwsIOException,ScriptException{

  ScriptEngineengine=getScriptEngine();

  ScriptContextcontext=engine.getContext();

  context.setWriter(newFileWriter("output.txt"));

  engine.eval("println('HelloWorld!');");

  }

  哪些腳本語言支持API

  3.2、自定義屬性

  ScriptContext中也有與ServletContext中類似的獲取和設置屬性的方法,即setAttribute和getAttribute.所不同的是ScriptContext中的屬性是有作用於之分的。設置屬性的時候需要顯式地指定所在的作用於。在獲取屬性的時候,即可以選擇指定的作用於中查找,也可以選擇根據作用於優先順序自動進行查找。腳本上下文實現中包含的作用域是固定的,開發人員不能隨意定義自己的作用於。通過ScriptContext的getScopes方法可以得到所有可用的作用於列表。ScriptContext中預先定義了兩個作用於:常量ScriptContext.GLOBAL_SCOPE表示的作用於對應的是從一個引擎工廠中創建出來的所有腳本引擎對象,而ScriptContext.ENGINE_SCOPE表示的作用域對應的是當前的腳本引擎。後者優先於前者。

  [nextpage[

  作用域影響同名屬性查找的示例:

  ENGINE_SCOPE中的屬性name隱藏了GLOBAL_SCOPE中的同名屬性

  publicvoidscriptContextAttribute()throwsScriptException{

  ScriptEngineengine=getScriptEngine();

  ScriptContextcontext=engine.getContext();

  context.setAttribute("name","shanshouchen",ScriptContext.ENGINE_SCOPE);

  context.setAttribute("name","andy",ScriptContext.GLOBAL_SCOPE);

  engine.eval("println(name);");//值為shanshouchen

  }

  3.3、語言綁定對象

  腳本執行上下文中的最後一類信息是語言綁定對象。語言綁定對象也是與作用於相對應的。同樣的作用域優先順序對語言綁定對象也適用。這樣的優先順序順序會對腳本執行時的變數解析產生影響。

  語言綁定對象的優先順序順序的示例:

  兩個不同的語言綁定對象中都有名稱為name的對象,而在腳本的執行過程中,作用域ENGINE_SCOPE的語言綁定對象的優先順序較高,因此變數name的值是"andy"

  publicvoidscriptContextBindings()throwsScriptException{

  ScriptEngineengine=getScriptEngine();

  ScriptContextcontext=engine.getContext();

  Bindingsb1=engine.createBindings();

  b1.put("name","shanshouchen");

  context.setBindings(b1,ScriptContext.GLOBAL_SCOPE);

  Bindingsb2=engine.createBindings();

  b2.put("name","andy");

  context.setBindings(b2,ScriptContext.ENGINE_SCOPE);

  engine.eval("println(name);");

  }

  通過ScriptContext的setBindings方法設置的語言綁定對象會影響到ScriptEngine在執行腳本時的變數解析。ScriptEngine的put和get方法所操作的實際上就是ScriptContext的作用域為ENGINE_SCOPE的語言綁定對象。如下代碼,從ScriptContext中得到語言綁定對象之後,可以直接對這個對象進行操作。如果在ScriptEngine中的eval方法中沒有指明的語言綁定對象,實際上起作用的是ScriptContext中作用域為ENGINE_SCOPE的語言綁定對象

  通過腳本執行上下文獲取語言綁定對象的示例:

  publicvoiduseScriptContextValues()throwsScriptException{

  ScriptEngineengine=getScriptEngine();

  engine.put("name","shanshouchen");

  ScriptContextcontext=engine.getContext();

  Bindingsbindings=context.getBindings(ScriptContext.GLOBAL_SCOPE);

  bindings.put("name","andy");

  engine.eval("println(name);");//輸出andy

  }

  不直接操作語言綁定對象本身,通過ScriptContext的setAttribute類像語言綁定對象中添加數據。所添加的數據在腳本執行時也同樣是可見的

  自定義屬性保存在語言綁定對象中的示例:

  publicvoidattributeInBindings()throwsScriptException{

  ScriptEngineengine=getScriptEngine();

  ScriptContextcontext=engine.getContext();

  context.setAttribute("name","Andy",ScriptContext.GLOBAL_SCOPE);

  engine.eval("println(name);");//輸出為Andy

  }

  4、方法調用

  在腳本中,最常見和最實用的就是方法。有些腳本引擎允許使用者單獨調用腳本中的某個方法。支持這種方法調用方式的腳本引擎可以實現javax.script.Invocable介面。通過Invocable介面可以調用腳本中的頂層方法,也可以調用對象中的成員方法。如果腳本中頂層方法或者對象中的成員方法實現了JAVA中的介面,可以通過Invocable介面中的方法來調用腳本中相應的JAVA介面的實現對象。這樣可以在JAVA語言中定義介面,在腳本中實現介面。程序中使用該介面的其他部分代碼並不知道介面是由腳本來實現的。與Compilable介面一樣,ScriptEngine對Invocable介面的實現也是可選的。

  在JAVA中調用腳本中頂層方法的示例:

  通過Invocable介面的invokeFunction來調用腳本中的頂層方法,調用時的參數會被傳遞給腳本中的方法。因為JAVASE自帶的JavaScript腳本引擎實現了Invocable介面,所以這裡省去了對引擎是否實現了Invocable介面的判斷

  publicvoidinvokeFunction()throwsScriptException,NoSuchMethodException{

  ScriptEngineengine=getScriptEngine();

  StringscriptText="functiongreet(name){println('Hello,'+name);}";

  engine.eval(scriptText);

  Invocableinvocable=(Invocable)engine;

  invocable.invokeFunction("greet","Alex");

  }

  在JAVA中調用腳本中對象的成員方法的示例:

  如果被調用的方法是腳本中對象成員方法,就需要使用invokeMethod方法,代碼中的getGreeting方法是屬性對象obj的,在調用的時候把這個對象作為參數傳遞進來。

  publicvoidinvokeMethod()throwsScriptException,NoSuchMethodException{

  ScriptEngineengine=getScriptEngine();

  StringscriptText="varobj={getGreeting:function(name){return'Hello,'+name;}};";

  engine.eval(scriptText);

  Invocableinvocable=(Invocable)engine;

  Objectscrpe=engine.get("obj");

  Objectresult=invocable.invokeMethod(scrpe,"getGreeting","Alex");

  System.out.println(result);

  }

  在腳本中實現JAVA介面的示例:

  在有些腳本引擎中,可以在JAVA語言中定i介面,並在腳本中編寫介面的實現。這樣程序中的其他部分可以只同JAVA介面交互,並不需要關心介面是由什麼方式來實現的。代碼清單中,Greet是用JAVA定義的介面,其中包含一個getGreeting方法。在腳本中實現這個介面。通過getInterface方法可以得到由腳本實現的這個介面的對象,並調用其中的方法。

  publicvoiduseInterface()throwsScriptException{

  ScriptEngineengine=getScriptEngine();

  StringscriptText="functiongetGreeting(name){return'Hello,'+name;}";

  engine.eval(scriptText);

  Invocableinvocable=(Invocable)engine;

  Greetgreet=invocable.getInterface(Greet.class);

  System.out.println(greet.getGreeting("Alex"));

  }

  Greet.java

  publicinterfaceGreet{

  StringgetGreeting(Stringname);

  }

  註:方法invokeMethod與方法invokeFunction的用法差不多,區別在於invokeMethod要指定包含帶調用方法的對象。

  以上就是關於「哪些腳本語言支持API」的內容,希望對大家有用。更多資訊請關注學步園。學步園,您學習IT技術的優質平台!

抱歉!評論已關閉.