實習第一期的任務基本做完,從python和django的世界又回到了Java,當初來剛來百度的時候怎麼也沒想到居然還會用上Java。新的任務也很簡單,不過正好學習了Java一個新的script包,可以用來解析指令碼文法。
javax.script,始於JDK1.6,不過現在只有sun實現的javascript的解析器,難道是因為主要用來解析js文法所以歸類到JEE的範疇?不過基本足夠了,一般的用途主要是能解析通用的運算式就好,比如X >= 1(X作為參數傳入)這樣的運算式,也能利用js的函數文法,創造一個就像java的函數一樣存在於記憶體中隨時可以被調用的函數,更可以將js中的對象直接轉換成java對象。
script包下最主要的是ScriptEngineManager、ScriptEngine、CompiledScript和Bindings 4個類或介面。
ScriptEngineManager是一個工廠的集合,可以通過name或tag的方式擷取某個指令碼的工廠並產生一個此指令碼的ScriptEngine,目前只有javascript的工廠。通過工廠函數得到了ScriptEngine之後,就可以用這個對象來解析指令碼字串了,直接調用Object obj = ScriptEngine.eval(String script)即可,返回的obj為運算式的值,比如true、false或int值。
CompiledScript可以將ScriptEngine解析一段指令碼的結果存起來,方便多次調用。只要將ScriptEngine用Compilable介面強制轉換後,調用compile(String script)就返回了一個CompiledScript對象,要用的時候每次調用一下CompiledScript.eval()即可,一般適合用於js函數的使用。
Bindings的概念算稍微複雜點,我的理解Bindings是用來存放資料的容器。它有3個層級,為Global級、Engine級和Local級,前2者通過ScriptEngine.getBindings()獲得,是唯一的對象,而Local Binding由ScriptEngine.createBindings()獲得,很好理解,每次都產生一個新的。Global對應到工廠,Engine對應到ScriptEngine,向這2者裡面加入任何資料或者編譯後的指令碼執行對象,在每一份新產生的Local Binding裡面都會存在。
給個代碼的例子,其中的functionScript可以從標準輸入stdin或者設定檔等地方獲得,這樣就可以動態控制Java代碼的運行結果
try {ScriptEngine engine = new ScriptEngineManager().getEngineByName("javascript");Compilable compilable = (Compilable) engine;Bindings bindings = engine.createBindings(); //Local層級的BindingString script = "function add(op1,op2){return op1+op2} add(a, b)"; //定義函數並調用CompiledScript JSFunction = compilable.compile(script); //解析編譯指令碼函數bindings.put("a", 1);bindings.put("b", 2); //通過Bindings加入參數Object result = JSFunction.eval(bindings);System.out.println(result); //調用緩衝著的指令碼函數對象,Bindings作為參數容器傳入}catch (ScriptException e) {}
另外還有一個ScriptContext的概念,這個可能很少用到吧,它是用來串連ScriptEngine和Bindings的工具。按照JDK的解釋:該介面的實作類別被用來串連ScriptEngine和宿主應用程式中的對象(如有範圍的Bindings)。