现在的位置: 首页 > 综合 > 正文

BeanShell

2013年09月04日 ⁄ 综合 ⁄ 共 17305字 ⁄ 字号 评论关闭

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

 

 

 

 

 

 

抱歉!评论已关闭.