新的工作中用到beanShell,轉載學習一下。
簡介:
BeanShell是一種完全符合Java語法規範的腳本語言,並且又擁有自己的一些語法和方法;
BeanShell是一種鬆散類型的腳本語言(這點和JS類似)
BeanShell是用Java寫成的,一個小型的、免費的、可以下載的、嵌入式的Java源代碼解釋器,
具有對象腳本語言特性,非常精簡的解釋器jar文件大小爲175k。
BeanShell執行標準Java語句和表達式,另外包括一些腳本命令和語法。
BeanShell 將成爲Java平臺上的第三種編程語言,前兩種分別爲java和Groovy(也是一種腳本語言)
下載與安裝:
jar: http://www.beanshell.org/download.html
src: http://www.beanshell.org/developer.html
或使用SVN:
svn co http://ikayzo.org/svn/beanshell
doc: http://www.beanshell.org/docs.html
設置環境:
(1) 把bsh-xx.jar放到$JAVA_HOME/jre/lib/ext文件夾下(不推薦);
(2) UNIX: export CLASSPATH=$CLASSPATH:bsh-xx.jar(推薦)
(3) WINDOWS: set classpath %classpath%;bsh-xx.jar(推薦)
運行方式:
(1) 界面UI方式 : java bsh.Console
(2) 命令行方式 : java bsh.Interpreter
(3) 運行腳本文件: java bsh.Interpreter filename [args]
簡單舉例(windows):
設置好環境變量classpath, 打開dos或CMD窗口, 鍵入命令:
java bsh.Console
出現BeanShell的"Bsh Workspace"界面,表示設置成功,BeanShell開始運行;
在使用上面命令出現的控制檯界面中進行下面的測試:
bsh % foo="Foo"; //定義變量foo
bsh % four=(2+2)*2/2; //定義變量four並初始化爲(2+2)*2/2
bsh % print(foo+"="+four); //輸出 Foo=4
Foo=4 //輸出結果
bsh % for(i=0;i<5;i++)print(i); //循環打印0~4
0
1
2
3
4
bsh % button = new JButton("MyButton"); //實例化一個Button對象
bsh % frame = new JFrame("MyFrame"); //實例化一個Frame對象
bsh % frame.getContentPane().add(button,"Center"); //將Button對象加入Frame對象的面板中;
bsh % frame.pack(); //打包
bsh % frame.setVisible(true); //設置Frame對象的可見性;回車後會彈出一個GUI界面;
bsh %
完整代碼:
foo = "Foo";
four = (2 + 2)*2/2;
print( foo + " = " + four );
for (i=0; i<5; i++)
print(i);
button = new JButton( "My Button" );
frame = new JFrame( "My Frame" );
frame.getContentPane().add( button, "Center" );
frame.pack();
frame.setVisible(true);
在窗口中輸入上面的代碼, 敲回車執行,彈出一個有Button的GUI界面.
說明:
因爲BeanShell是鬆散類型的腳本語言因此可以直接寫:
foo = "Foo";
four = (2 + 2)*2/2;
也就是foo與four均不需要變量類型的聲明,給賦什麼類型的值,就是什麼類型的變量;
print()是BeanShell提供一種簡單的打印命令,相當於java中的System.out.println();
腳本中所寫的方法範例:
int addTwoNumbers( int a, int b ) {
return a + b;
}
sum = addTwoNumbers( 5, 7 ); // 12
也可以使用動態的變量類型(無狀態)方法
add(a, b){
return a + b;
}
foo = add(1, 2); // 3
foo = add(1, "2"); //"12"
特別注意:
只要有一個爲字符串全部按照字符串處理,
系統不會根據1是數字在前把"2"轉換成數字處理;
foo = add("Oh", " baby"); // "Oh baby"
腳本中實現接口:
實現任何接口需要JDK1.3或者更高,可以使用缺省的java匿名類的語法實現一個接口類,例如:
ActionListener scriptedListener = new ActionListener() {
actionPerformed( event ) { ... }
}
不需要實現接口的所有的方法,只需要實現你使用的方法即可, 如果使用你沒有實現的方法,
BeanShell將拋出一個錯誤,如:
ml = new MouseListener() {
mousePressed( event ) { print("test"); }
// handle the rest
invoke( name, args ) {
print("Method: "+name+" invoked!");
}
}
腳本中定義對象:
例一:
使用特殊的關鍵字this可以創建一個對象(根JS類似)
foo() {
print("foo");
x=5;
bar() {
print("bar");
}
return this;
}
myfoo = foo(); // prints "foo"
print( myfoo.x ); // prints "5"
myfoo.bar(); // prints "bar"
例二:
在java標準語言中可以使用this返回一個類的一個實例
// MyClass.java
MyClass {
Object getObject() {
return this; // return a reference to our object
}
}
在這個例子中getObject() 方法是返回MyClass類的一個實例
在BeanShell中對象中的變量只是局部的變量在對象內可以使用,
在對象外是不可以使用的(不同於前面for-loop,if-else中的使用);
// Define the foo() method:
foo() {
bar = 42;
print( bar );
}
// Invoke the foo() method:
foo(); // prints 42
print(bar); // Error, bar is undefined here
這裏的print(bar);會拋出異常:
// Error: EvalError: Undefined argument: bar : at Line: 1 : in file: <unknown file> : ( bar )
但可以使用this返回對象,使用對象加上"."運算符引用屬性(類似JS)
foo() {
bar = 42;
return this;
}
fooObj = foo();
print( fooObj.bar ); // prints 42
同樣對象中也可以定義一些方法,例如:
foo() {
int a = 42;
bar() {
print("The bar is open!");
}
//bar();
return this;
}
// Construct the foo object
fooObj = foo(); // prints "the bar is open!"
// Print a variable of the foo object
print ( fooObj.a ) // 42
// Invoke a method on the foo object
fooObj.bar(); // prints "the bar is open!"
也可以定義bar()和foo()也帶參數:
foo() {
bar(int a) {
print("The bar is open!" + a);
}
return this;
}
foo().bar(1);
也可以把bar()方法定義到對象外面
foo() {
return this;
}
bar(int a) {
print("The bar is open!" + a);
}
foo().bar(1); //其實就是bar(1);
BeanShell一種鬆散的腳本語言, 有很多中聲明的方法可以使用:
This super global
This 是引用當前對象
Super 是引用父親對象
Global 是引用最上層對象
super.super.super...foo = 42; // Chain super. to reach the top
global.foo = 42;
BeanShell(Bsh)調用外部Java類的兩種方式:
(1) 方法一(直接調用.java源文件)
sourceRelative("xxx.java");
利用sourceRelative()方法把java的源代碼引入bsh環境中,然後進行調用。
這種方法不需要編譯引用的java源文件,缺點也很明顯"無法利用javac來檢查java代碼"。
(2) 方法二(通過引用.class二進制文件)
import xxx;
利用傳統的java import機制來獲取java類,然後在bsh環境中進行調用。
需要編譯.java文件;
方便調用第三方的Java API(因爲通常情況下無法得到API的源碼,即使得到了文件會遠大於jar包的大小)。
BeanShell介紹:
我們知道,現在有很多腳本語言,大家平時使用的比較多的包括Perl,Python,Ruby,Javascript,Groovy,
在這裏我要介紹的是另外一個對象腳本語言BeanShell(http://www.BeanShell.org)。
BeanShell的解釋器是用Java寫的,開源並且免費的,
引用open-open上面的話來說明它的運作方式:
它將腳本化對象看作簡單閉包方法(simple method closure)來支持,
就如同在Perl和JavaScript中的一樣。它具有以下的一些特點:
* 使用Java反射API以提供Java語句和表達式的實時解釋執行;
* 可以透明地訪問任何Java對象和API;
* 可以在命令行模式、控制檯模式、小程序模式和遠程線程服務器模式等四種模式下面運行;
* 與在應用程序中一樣,可以在小程序中(Applet)正常運行(無需編譯器或者類裝載器);
* 非常精簡的解釋器, jar文件中的Intepreter.class大小爲150+k"。
每一種腳本語言都有它的使用場景,而正是因爲其在某些場景的使用而使語言本身得到了發揚光大,
比如Ruby正是因爲Ruby On Rails這個Web框架的流行而得到開發者的關注,Groovy也一樣;
BeanShell可不能再有Web框架,Java世界的Web框架已經太多了,夠讓人頭痛的了;
BeanShell是Java語法,所以對Java開發者來說,很快就可以上手,
BeanShell不能像Ruby,Perl,Ruby一樣可以佔據一個系統的主體,
而只能在一些小的地方發揮"螺絲釘"的作用。
筆者與BeanShell結緣是通過一個開源工作流引擎-OBE(這個鳥東西現在好像沒什麼聲音了),
BeanShell被用作流程跳轉的Parser,舉個例子,比如一個流程A節點的下一個節點是B或者C,
如何決定A->B還是A->C呢,我們可以寫一段Java腳本放在流程定義裏面,
一旦A運行完畢,流程會使用BeanShell來Parse這段Java腳本,
根據腳本的返回值決定流程下一步的運行方向,
腳本在這裏雖然用得不多,但是卻是非常的重要,
我們知道,簡單的表達式是遠遠滿足不了流程跳轉的判斷的,
有了腳本就可以滿足任何不規則的業務邏輯。
繼以上說到的,使用BeanShell可以處理現實中不規則的業務,舉個很典型的例子,
我們知道,一個保險公司有很多險種,每個險種的投入和收益的算法是很複雜的,
無法用規則的關係數據庫模型來描述,所以很多保險系統在處理險種的算法都是硬編碼,
如果要在系統中新加一個險種,是非常麻煩的,重新修改代碼,重新發布,
這對開發\維護人員和客戶都是很痛苦的,有了BeanShell,我們可以從這種痛苦中解脫出來,
對每個險種使用不同的腳本,新加的險種我們新配一個腳本,這樣既可以滿足業務多變的要求,
又可以減少工作量,節約成本。
BeanShell的一個特點是動態執行Java代碼,腳本文件改變不會影響當前腳本的調用,
新腳本將在腳本的下一次調用生效,這不同於配置文件,配置文件改變一般都需要應用重啓。
下面舉個例子來說明BeanShell的使用(JDK1.5,BeanShell2.04),
主類:
package com.test.BeanShell;
import bsh.Interpreter;
public class TestShell {
public static void main(String[] args) throws Exception {
Interpreter interpreter = new Interpreter();
interpreter.set("inValue", new Integer(1));
interpreter.source("/D://BeanShell_test/test.bsh");
System.out.println(((Integer) interpreter.get("outValue")).intValue());
}
}
腳本文件(D:/BeanShell_test/test.bsh)中的內容爲::
System.out.println("hello,in value is "+inValue);
outValue = inValue+1;
結果:
hello,in value is 1
2
再來一個簡單例子:
(1) 下載BeanShell的jar,加到 classpath 裏
(2) 寫一個腳本文件 myscript.txt ,內容如下:
a = 2;
b = 3;
c = a + b;
print(c);
(3) 運行該腳本
d:\BeanShell>java bsh.Interpreter myscript.txt
如果沒有將BeanShell的JAR加到classpath路徑裏,運行下面的命令:
java -classpath %CLASSPATH%;bsh-2.0b4.jar bsh.Interpreter myscript.txt
OK,輸出結果5
寫一個bat文件 bsh.bat放到系統目錄下,如:winnt 文件內容如下:
java bsh.Interpreter %1
就可以使用如下方法運行腳本文件了
c:\BeanShell>bsh myscript.txt
osworkflow用的就是他了
和Eclipse的集成: http://eclipse-shell.sourceforge.net/index.html
eclipse update url: http://eclipse-shell.sourceforge.net/update/
有用的BeanShell命令:
在剛纔那個例子中我們用了一個內建在BeanShell中的一個方便的命令print(),來顯示變量的值。
print()跟Java的System.out.println()非常的相像,除非它能保證輸出總是命令行。
print()也可以顯示一些對象的類型(如數組),但比Java的更詳細。
另一個相關的命令是show(),用來開啓與關閉顯示你輸入的每一行的結果。
下面是一些其它的BeanShell的命令(BeanShell腳本命令):
source(), run() //將一個bsh腳本讀到解釋器或運行在另一個解釋器。
frame() //顯示一個Frame或JFrame的GUI組件。
load(), save() //載入和保存一個序列化的對象到一個文件。
cd(), cat(), dir(), pwd(), etc. //使用UNIX或WIDOWS下面的命令
exec() //運行一個本地的程序
javap() //打印一個對象的方法和字段,類似於Java的javap命令。
setAccessibility() //開啓無限制的存取 private 和 protected 的組件。
BeanShell命令並不是真的"內建"其中的,而是作爲腳本方法自動從classpath載入的.
你可以擴展基本命令集並加到classpath中作爲自訂義的腳本來使用。
要獲得更多的信息請查看BeanShell命令的詳細清單。
腳本方法:
你可以在bsh中聲明和使用方法,就像在java的類中一樣。
int addTwoNumbers( int a, int b ) {
return a + b;
}
sum = addTwoNumbers( 5, 7 ); // 12
bsh的方法可以有動態的(寬鬆的)參數和返回類型。
add(a, b) {
return a + b;
}
foo = add(1, 2); // 3
foo = add("Oh", " baby"); // "Oh baby"
實現Interface
注意:如果要BeanShell能實現任意的Interface,必須有jdk1.3及以上支持。
你可以在腳本中用標準的Java內部類的語法來實現Interface.例如:
ActionListener scriptedListener = new ActionListener() {
actionPerformed( event ) { ... }
}
你可以不用實現Interface的所有方法,而只用實現你需要的方法。
如果代碼中調用了未被實現的方法,將丟出異常。
如果你想重載大量的方法的行爲--例如爲日誌生成一個"啞"適配器--你可以在腳本對象中,
實現一個特殊的方法:invoke(name,args)。
invoke()方法用來處理任何未被定義的方法的調用:
ml = new MouseListener() {
mousePressed( event ) { ... }
// handle the rest
invoke( name, args ) {
print("Method: "+name+" invoked!");
}
}
腳本對象
在BeanShell中,和在JavaScript與Perl中一樣,腳本對象是用封閉的方法體一構成的。
通過在方法未尾返回一個特殊值"this",你就可以像使用方法一樣調用這個對象了。
在這個方法調用時,你可以給與它任何的值。通常對象內部需要包括方法,
所以BeanShell的腳本方法在一定程度上可再包含一些方法以構成腳本對象。例如:
foo() {
print("foo");
x=5;
bar() {
print("bar");
}
return this;
}
myfoo = foo(); // prints "foo"
print( myfoo.x ); // prints "5"
myfoo.bar(); // prints "bar"
如果這些代碼對你來說很陌生,別急,請用戶手冊可得到更透徹的解釋。
在你的腳本中,BeanShell腳本對象(也就是先前例子中的"this"參照)能自動實現任何JAVA介面類型。
當JAVA代碼調用相應與之通訊的腳本方法內的方法。
當你試着將腳本對象作爲參數傳給Java方法時,BeanShell會自動將它造型(cast)爲相應的類型。
如要傳遞BeanShell外部的對象時,你可以在需要時顯式的進行造型(cast).
BeanShell語法:
BeanShell本身就是一種最原始的java解釋器,可以在其bsh%提示符下輸入Java的語句,然後執行:
1. Standard Java syntax(支持標準Java語法)
(1) Use a hashtable
bsh % Hashtable hashtable = new Hashtable();
bsh % Date date = new Date();
bsh % hashtable.put("today",date);
bsh % print(hashtable);
{today=Sun Jul 03 18:33:03 CST 2011}
注意:
目前不支持Java中的泛型,如:
bsh % Hashtable<String,Date> hashtable = new Hashtable<String,Date>();
// Error: Parser Error: Parse error at line 1, column 8179. Encountered: ,
bsh % // Error: Parser Error: Parse error at line 1, column 5. Encountered: te
(2) Print the current clock value
bsh % print(System.currentTimeMillis());
1309689354531
(3) Loop
bsh % for(int i=0;i<5;i++){print(i);}
0
1
2
3
4
(4) Pop up a frame with a button in it
JButton button = new JButton( "My Button" );
JFrame frame = new JFrame( "My Frame" );
frame.getContentPane().add( button, "Center" );
frame.pack();
frame.setVisible(true);
(5) difine a button
java.awt.Button button = new java.awt.Button();
button.setLabel("javaButton");
2. Loosely Typed Java syntax(支持鬆散類型的java語法)
(1) Use a hashtable
hashtable = new Hashtable();
date = new Date();
hashtable.put("today", date);
print(hashtable);
{today=Sun Jul 03 18:41:44 CST 2011}
(2) Print the current clock value
print(System.currentTimeMillis());
1309689745765
(3) Loop
for (i=0; i<5; i++)
print(i);
(4) Pop up a frame with a button in it
button = new JButton( "My Button" );
frame = new JFrame( "My Frame" );
frame.getContentPane().add( button, "Center" );
frame.pack();
frame.setVisible(true);
(5) difine a button
button = new java.awt.Button();
button.label = "my button";
(5) useing {} set the properties for a object instance
b = new java.awt.Button();
b{"label"} = "my button"; // Equivalent to: b.setLabel("my button");
f = new JFrame("MyFrame");
f.getContentPane().add(b);
f.pack();
f{"visible"}=true;
h = new Hashtable();
3. Exception handling(異常處理)
(1) 標準的java異常
try {
int i = 1/0;
} catch ( ArithmeticException e ) {
print( e );
}; //回車,拋出下面的Exception
java.lang.ArithmeticException: / by zero
(2) 鬆散的異常處理(類似JS)
try {
int i = 1/0;
} catch (e) {
print( e ); //這裏沒有具體類型
}; //回車,拋出下面的Exception
java.lang.ArithmeticException: / by zero
4. 鬆散類型變量的作用範圍
標準的java程序的變量作用範圍是在一個模塊中(在模塊中聲明的變量),
而在鬆散類型的語言中如果在一個模塊中沒有指定一個變量的類型,
則認爲是一個全局變量, 只有它以後的代碼可以使用該變量,
系統在調用該變量的時候自動生成一個全局變量,
也就爲什麼在調用模塊之前不能使用該變量的原因。
// Arbitrary code block
{
y = 2; // Untyped variable assigned
int x = 1; // Typed variable assigned
}
print( y ); // 2
print( x ); // Error! x is undefined.
// Error: EvalError: Undefined argument: x
// Same with any block statement: if, while, try/catch, etc.
if ( true ) {
y = 2; // Untyped variable assigned
int x = 1; // Typed variable assigned
}
print( y ); // 2
print( x ); // Error! x is undefined.
同樣也適用於for-loop, if-else等循環語句
for( int m=0; m<10; m++ ) { // typed for-init variable
j=42;
}
print( m ); // Error! 'm' is undefined.
print( j ); // 42
注意:
上面的代碼中的m如果在之前有過定義, 則可正確得到執行,
比如先執行下面的代碼,再執行上面的代碼,打印的m值實際上是下面的m值:
for(m=0; m<10; m++ ) { // typed for-init variable
j=42;
}
print( m ); // Error! 'i' is undefined.
print( j ); // 42
又如:
for( z=0; z<10; z++ ) { } // untyped for-init variable
print( z ); // 10
5. boxing & unboxing(自動裝箱和自動拆箱)
BeanShell自動轉爲簡單類型
i=5;
iBox=new Integer(5);
print( i * iBox ); // 25
6. import classes and package(導入類和包)
(1) normal import
import javax.xml.parsers.*;
import mypackage.MyClass;
(2) super import(超級導入法)
import *;
BeanShell默認導入下面的包
* java.lang
* java.io
* java.util
* java.net
* java.awt
* java.awt.event
* javax.swing
* javax.swing.event
7. 友好文檔實體(BeanShell支持特殊的文檔操作類型內容)
@gt >
@lt <
@lteq <=
@gteq >=
@or ||
@and &&
@bitwise_and &
@bitwise_or |
@left_shift <<
@right_shift >>
@right_unsigned_shift >>>
@and_assign &=
@or_assign |=
@left_shift_assign <<=
@right_shift_assign >>=
@right_unsigned_shift_assign >>>=
8. 腳本方法
你可以定義方法象java中的定義方法一樣
int addTwoNumbers( int a, int b ) {
return a + b;
}
你可以使用內嵌的BeanShell方法使用他們
sum = addTwoNumbers( 5, 7 );
只有BeanShell變量可以被動態定義爲動態類型,方法可以有動態的參數以及返回類型
add( a, b ) {
return a + b;
}
在這個方法中,當這個方法被調用時,BeanShell將動態的決定類型,
並且能夠準確的計算出你想要的結果:
foo = add(1, 2);
print( foo ); // 3
foo = add("Oh", " baby");
print( foo ); // Oh baby
在第一個例子中BeanShell將把參數定義爲數字型,並返回數字型;
在第二個例子中BeanShell將把參數定義爲字符型,並返回字符對象;
9. 變量和方法的可見範圍
就像您所預期的那樣,在方法內您可以引用到處於上下文中之前所定義的變量和方法,
a = 42;
someMethod() { }
foo() {
print( a );
someMethod(); // invoke someMethod()
}
// invoke foo()
foo(); // prints 42
如果一個變量只有在方法內使用請定義成局部變量,即加上類型,
如果是全局變量請在方法外定義;
var = "global";
foo() {
print(var);
String var = "local";
print(var);
}
foo();
print(var);
將打印出:
global
local
global
方法內的var(Line 4)變量屬於局部變量,不會覆蓋全局變量var(Line 1)的,
因此改變var(Line 4)變量不會影響到全局變量var(Line 1)
10. 範圍引用: super
使用super關鍵字可以在局部引用全局變量
var = "global";
foo() {
String var = "local";
print(var);
print(super.var);
}
foo();
將輸出
local
global
11. 從你的應用程序調用BeanShell
通過建立一個 BeanShell 解釋器,使用eval()或source()命令,
你可以在你的應用程序中求文本表達式的值和運行腳本。
如果你希望在你的腳本內部使用一個對象,可以用set()方法傳遞對象的變量引用給BeanShell,
並通過get()方法取得結果。
import bsh.Interpreter;
Interpreter i = new Interpreter(); // Construct an interpreter
i.set("foo", 5); // Set variables
i.set("date", new Date() );
Date date = (Date)i.get("date"); // retrieve a variable
// Eval a statement and get the result
i.eval("bar = foo*10");
System.out.println( i.get("bar") );
// Source an external script file
i.source("somefile.bsh");
BeanShell實例一:文本拖動
dragText() {
f = new Frame("Drag in the box");
f.setFont( new Font("Serif", Font.BOLD, 24) );
f.setSize(300, 300);
f.addWindowListener(new WindowListener(){
public void windowClosing(WindowEvent e) { System.exit(0);}
public void windowOpened(WindowEvent e) {}
public void windowClosed(WindowEvent e) {}
public void windowIconified(WindowEvent e) {}
public void windowDeiconified(WindowEvent e) {}
public void windowActivated(WindowEvent e) {}
public void windowDeactivated(WindowEvent e) {}
});
f.show();
gc = f.getGraphics();
gc.setColor(Color.cyan);
mouseDragged( e ) {
gc.drawString("Drag Me!", e.getX(), e.getY());
}
mouseMoved( e ) { }
f.addMouseMotionListener( this );
}
dragText();
Beanshell實例二:畫圖
import bsh.util.BshCanvas;
//BshCanvas simply buffers graphics
//不知道是不是BUG, 上面的import語句需要獨立先執行;
graph(int width, int height) {
canvas=new BshCanvas();
canvas.setSize(width, height);
frame=frame(canvas);
graphics=canvas.getBufferedGraphics();
// draw axis
graphics.setColor(Color.red);
graphics.drawLine(0, height/2, width, height/2);
graphics.drawLine(width/2, 0, width/2, height);
graphics.setColor( Color.black );
plot(int x, int y){
graphics.fillOval((x+width/2-1), (y+height/2-1), 3, 3);
canvas.repaint();
}
return this;
}
drawSin(graph) {
for (int x=-100; x<100; x++ ) {
y=(int)(50*Math.sin( x/10.0 ));
graph.plot(x, y);
}
}
myGraph = graph(250,125);
drawSin(myGraph);
myGraph.frame.setTitle("Sin(x)");
BeanShell實例四: web瀏覽器
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;
import java.awt.event.*;
import java.awt.*;
//同上, 這裏的import語句需要單獨執行;
JFrame browser(startingUrl){
invoke(method, args) {}
windowClosing(WindowEvent we) {
we.getWindow().setVisible(false);
}
setPage( url ) {
try {
pane.setPage( url );
} catch (Exception e) {
statusBar.setText("Error opening page: "+url);
}
}
hyperlinkUpdate( HyperlinkEvent he ) {
type = he.getEventType();
if (type == HyperlinkEvent.EventType.ENTERED) {
pane.setCursor(Cursor.getPredefinedCursor( Cursor.HAND_CURSOR));
statusBar.setText(he.getURL().toString());
} else if (type == HyperlinkEvent.EventType.EXITED) {
pane.setCursor( Cursor.getDefaultCursor() );
statusBar.setText(" ");
} else {
setPage( he.getURL() );
if (urlField != null)
urlField.setText(he.getURL().toString());
}
}
frame = new JFrame("Browser");
frame.setSize(400,300);
frame.addWindowListener( this );
urlPanel = new JPanel();
urlPanel.setLayout(new BorderLayout());
urlField = new JTextField(startingUrl);
urlPanel.add(new JLabel("Site: "), BorderLayout.WEST);
urlPanel.add(urlField, BorderLayout.CENTER);
statusBar = new JLabel(" ");
pane = new JEditorPane();
pane.setEditable(false);
setPage( startingUrl );
jsp = new JScrollPane(pane);
frame.getContentPane().add(jsp, BorderLayout.CENTER);
frame.getContentPane().add(urlPanel, BorderLayout.SOUTH);
frame.getContentPane().add(statusBar, BorderLayout.NORTH);
// This is the equivalent of an inner class in bsh.
urlTextHandler() {
actionPerformed(ActionEvent ae) {
setPage( ae.getActionCommand() );
}
return this;
}
urlField.addActionListener( urlTextHandler() );
pane.addHyperlinkListener( (HyperlinkListener)this );
return frame;
}
browser = browser("http://java.sun.com/");
browser.show();
從應用程序中調用BeanShell:
創建一個BeanShell的解釋器(Interpreter),
用eval()和source()命令可以對一個字符串求值和運行一個腳本文件,
使用set()方法可以給一個對象傳入一個變量的引用;
使用get()方法可以重新得到一個變量的結果;
完整代碼:
---------------------------------------
import bsh.*;
import java.util.*;
public class BeanShell {
public static void main(String[] args) {
try {
Interpreter interpreter = new Interpreter(); // 構造一個解釋器
interpreter.set("foo", 5);// 設置變量
interpreter.set("date", new Date()); //設置一個時間對象
Date date = (Date) interpreter.get("date"); // 重新得到時間對象
interpreter.println(date.toString()); //打印時間
interpreter.eval("bar = foo*10"); // 對一段腳本求值,並得到結果
System.out.println(interpreter.get("bar")); //打印變量
interpreter.source("d:\\helloWorld.bsh"); // 導入並執行一個腳本文件
} catch (Exception e) {
//如果發生異常,寫入日誌文件
Log.error(new BeanShell(), "main", FormatDate.getCurrDate(), e.getMessage());
}
}
}