BeanShell

新的工作中用到beanShell,轉載學習一下。

簡介:
 BeanShell是一種完全符合Java語法規範的腳本語言,並且又擁有自己的一些語法和方法;
 BeanShell是一種鬆散類型的腳本語言(這點和JS類似)
 BeanShell是用Java寫成的,一個小型的、免費的、可以下載的、嵌入式的Java源代碼解釋器,
 具有對象腳本語言特性,非常精簡的解釋器jar文件大小爲175k。
 BeanShell執行標準Java語句和表達式,另外包括一些腳本命令和語法。

官網:http://www.BeanShell.org/

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());
   }
  }
 }

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章