您的位置:首页 > 运维架构 > Shell

BeanShell

2015-06-09 14:08 555 查看
新的工作中用到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());

   }

  }

 }
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  beanShell