BeanShell是一個(gè)小型的,免費的,可嵌入式的,具有面向對象腳本語(yǔ)言特性的Java代碼解釋器。它是用Java語(yǔ)言寫(xiě)的。它能執行標準的Java語(yǔ)句和表達式,還自帶簡(jiǎn)單的腳本命令和語(yǔ)法。它把編程對象當成一個(gè)簡(jiǎn)單的方法,這很像Perl和JavaScript.
你可以在寫(xiě)Java測試或調試時(shí)使用BeanShell,也可以用它作為你的應用程序的腳本引摯。簡(jiǎn)而言之,BeanShell可以動(dòng)態(tài)的解釋JAVA語(yǔ)言。也就是說(shuō)BeanShell在許多方面對于Java的用處就像Tcl/Tk對于C的用處一樣:BeanShell是可嵌入式的---你可以在運行時(shí)從你的應用程序調用BeanShell去動(dòng)態(tài)的執行Java代碼或是為你的應用程序提供腳本擴展。相反,你也可以從BeanShell調用你的應用程序及其對象,它可以讓JAVA對象和API動(dòng)態(tài)運行。正因為BeanShell是用JAVA寫(xiě)的,所以它可以和你的應用程序運行在同一個(gè)JVM空間內,你也可以自由的傳遞實(shí)時(shí)對象的引用(References)到腳本代碼中并且作為結果返回。
![]() ![]() |
![]()
|
BeanShell能理解標準的JAVA語(yǔ)句,表達式,和方法宣告。語(yǔ)句和表達式的內容可以是:變量,宣告,賦值,方法調用,循環(huán),條件等。
在Java程序中你必須嚴格的使用它們,但在BeanShell中,你可以用"寬松類(lèi)型"(loosely typed)的方式來(lái)使用它們。也就是說(shuō),你可以在寫(xiě)腳本時(shí)偷懶,不進(jìn)行變量類(lèi)型的宣告(在原始數據類(lèi)型和對象都可以)。如果你試著(zhù)用錯變量類(lèi)型,BeanShell將會(huì )給出一個(gè)錯誤??傊瓸eanShell的腳本是很容易上手的。
這里有一個(gè)簡(jiǎn)單的例子:
foo = "Foo"; four = (2 + 2)*2/2; print( foo + " = " + four ); // print() 是BeanShell的一個(gè)腳本命令。 // 循環(huán) for (i=0; i<5; i++) print(i); //顯示一個(gè)有包含一個(gè)按鈕的窗口 button = new JButton( "My Button" ); frame = new JFrame( "My Frame" ); frame.getContentPane().add( button, "Center" ); frame.pack(); frame.setVisible(true); |
你也可以在Beanshell腳本中宣告和定義自己的方法:
int multiply(int a, int b) { return a*b; } print(multiply(12,14));//打印出168 |
BeanShell的變量或參數的類(lèi)型可以不用顯示的指定,如下:
int multiply(a, b) { return a*b; } result = multiply(12,14); print(result);//打印出168 |
在BeanShell中也可以寫(xiě)對象。它與JavaScript很相似,它用一個(gè)方法,再內嵌一些內部方法,并且在未尾返回一個(gè)this來(lái)實(shí)現對象的編程:
Employee() { age = 26; sex = "M"; name = "Turbo"; int getAge() { return age; } String getSex() { return sex; } String getName() { return name; } return this; } turbo = Employee(); // 構造一個(gè)Employee對象。 print("Name:"+turbo.getName); //打印出employee的名字。 |
上面的程序片斷,相信大家已經(jīng)對BeanShell的語(yǔ)法有了一個(gè)印象,你可以通過(guò)參考資料中的鏈接,找到更詳細的BeanShell的腳本語(yǔ)法教程。
![]() ![]() |
![]()
|
其實(shí)在Java中調用bsh的腳本非常簡(jiǎn)單,你需要先創(chuàng )建一個(gè)Interpreter類(lèi)的實(shí)例.然后就可以用它運行你的腳本代碼或者腳本文件。請看下面的一個(gè)例子,這個(gè)例子來(lái)自于BeanShell的文檔:
Import bsh.*; //創(chuàng )建一個(gè)bsh解釋器實(shí)例 Interpeter bsh = new Interpreter(); // 表達式求值 bsh.eval("foo=Math.sin(0.5)"); bsh.eval("bar=foo*5; bar=Math.cos(bar);"); bsh.eval("for(i=0; i<10; i) { print(\"hello\"); }"); // 運行語(yǔ)句。 bsh.eval("for(int i=0; i<10; i) { System.out.println(\"hello\"); }"); // 載入腳本文件 bsh.source("myscript.bsh"); // or bsh.eval("source(\"myscript.bsh\")"); // 使用set()和get()方法存取變量值。 bsh.set( "date", new Date() ); Date date = (Date)bsh.get( "date" ); // This would also work: Date date = (Date)bsh.eval( "date" ); bsh.eval("year = date.getYear()"); Integer year = (Integer)bsh.get("year"); // primitives use wrappers // 也可以實(shí)現任意的Java Interface.. // 或處理AWT事件。 bsh.eval( "actionPerformed( e ) { print( e ); }"); ActionListener scriptedHandler = (ActionListener)bsh.eval("return (ActionListener)this"); Use the scripted event handler normally... new JButton.addActionListener( script ); |
![]() ![]() |
![]()
|
為了讓讀者更好的理解,我們在這里以jdk1.4中的一個(gè)演示程序,Notepad程序作為基礎,向讀者講解BeanShell是如何嵌入到Notepad程序中的。如果你安裝了JDK1.4的話(huà),Notepad源程序可以在<JAVA_HOME>\demo\jfc\Notepad目錄中找到.
筆者寫(xiě)的一個(gè)BeanShell類(lèi),用來(lái)運行用戶(hù)的腳本,下面的該程序的完整清單:
import javax.swing.text.*; import javax.swing.*; import java.io.*; import bsh.*; public class BeanShell { private static NameSpace namespace; private static boolean running; private static Notepad notepad; //初始化引擎 public static void initBeanShell(Notepad pad) { notepad = pad; namespace = new NameSpace("Notepad embedded scripting engine."); } //運行一段腳本代碼 public static void runScript(String script) { try { StringReader reader = new StringReader(script); runScript( "New script", reader); } catch(Exception ex) { ex.printStackTrace(); System.out.println(ex); return; } } public static void runScript(String scriptInfo, Reader reader) { Interpreter interpreter = new Interpreter(reader,System.out,System.out,true,namespace); try { if(notepad != null) { JTextComponent editor = notepad.getEditor(); interpreter.set("application",notepad); //將應用程序的變量傳入解釋器, interpreter.set("editor", editor); //這樣就可在腳本中使用這個(gè)變量參照 running = true; interpreter.eval(reader, namespace, scriptInfo); } } catch(Throwable throwable) { throwable.printStackTrace(); JOptionPane.showMessageDialog(notepad, new Object[] {"Script 錯誤!", throwable.getMessage()}, "錯誤",JOptionPane.ERROR_MESSAGE); } finally { running = false; } } public static boolean isMacroRunning() { return running; } } |
這個(gè)BeanShell提供了三個(gè)方法,
void initBeanShell(Notepad),這個(gè)方法進(jìn)行初始化。
void runScript(String script),這個(gè)方法可直接運行腳本代碼。
void runScript(String scriptInfo, Reader reader),這個(gè)方法可從一個(gè)Reader流中運行腳本。
而真正核心的執行腳本的代碼在void runScript(String scriptInfo, Reader reader)方法中,大家注意,代碼中先創(chuàng )建了一個(gè)BeanShell的解釋器實(shí)例,
Interpreter interpreter = new Interpreter(reader,System.out,System.out,true,namespace); |
然后將Notepad程序的實(shí)例變量傳入解釋器,這樣就可直接在腳本中引用Notedpad的實(shí)例了,
JTextComponent editor = notepad.getEditor(); interpreter.set("application",notepad); //將應用程序的變量傳入解釋器, interpreter.set("editor", editor); //這樣就可在腳本中使用這個(gè)變量參照 |
接下來(lái)看看如何把BeanShell嵌入到Notepad程序中,筆者寫(xiě)了幾個(gè)類(lèi), Main,用來(lái)初始化,并在Notepad程序中加入一個(gè)"Script Editor"的菜單 ScriptEditor,簡(jiǎn)單的腳本編輯器,用來(lái)編輯或載入腳本,運行腳本程序。 ScriptEditorAction,啟動(dòng)Script Editor的Action.
下面是Main.class的主要代碼,
Notepad notepad = new Notepad(); JMenu editMenu = new JMenu("Script Editor"); JMenuItem editItem = new JMenuItem(); editMenu.add(editItem); editItem.setAction(new ScriptEditorAction(notepad)); notepad.getMenubar().add(editMenu); |
以上程序取得Notepad程序的Menu Bar,并添加一個(gè)Script Editor菜單到其中,這樣,就可不用修改Notepad程序,并在其中加入啟動(dòng)Script Editor的菜單。
下圖是程序運行中的畫(huà)面:

這個(gè)程序的完整代碼,請在文章未尾的參考資料中去下載。
![]() ![]() |
![]()
|
現在我們寫(xiě)一個(gè)簡(jiǎn)單的腳本代碼,用來(lái)統計某個(gè)單詞在Notepad文章中的出現次數,下面列出這個(gè)腳本的代碼:
/** * 字串統計程序。 * @author: turbo chen */ //字串統計函數 counter(s) { str = editor.getText(); str = str.toLowerCase(); slen = s.length(); s = s.toLowerCase(); count = 0; from = 0; while ( (from=str.indexOf(s,from))>-1 ) { count = count + 1; from = from + slen; } return count; } // application 是經(jīng)由BeanShell傳入的應用程序對象。 target = JOptionPane.showInputDialog(application,"Please input the count target:"); if ( target != null ) { count = counter(target); JOptionPane.showMessageDialog(application,"Found "+count+" targets."); } |
將上面的腳本輸入到"Script Editor"視窗中,運行它??纯闯绦蜻\行的畫(huà)面:

(查找"of"這個(gè)單詞在文章中出現的次數,)

(找到13個(gè)目標。)
![]() ![]() |
![]()
|
本文講解了BeanShell腳本引擎如何在現有的應用程序中應用,也讓讀者了解到BeanShell腳本的基本特性與腳本語(yǔ)法,讓大家看到嵌入腳本引擎到Java應用程序中是多么的容易。
聯(lián)系客服