BeanShell学习

Beanshell (bsh) 是用Java写成的,一个小型的、免费的、可以下载的、嵌入式的Java源代码解释器,具有对象脚本语言特性。BeanShell执行 标准Java语句和表达式,另外包括一些脚本命令和语法。它将脚本化对象看作简单闭包方法(simple method closure)来支持,就如同在Perl和JavaScript中的一样。 它具有以下的一些特点:使用Java反射API以提供Java语句和表达式 的实时解释执行;可以透明地访问任何Java对象和API;可以在命令行模式、控制台模式、小程序模式和远程线程服务器模式等四种模式下面运行;与在应用 程序中一样,可以在小程序中(Applet)正常运行(无需编译器或者类装载器);非常精简的解释器jar文件大小为175k。


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




BeanShell 将成为Java平台上的第三种编程语言
-------------------------------------------------------------------------------
JCP 接纳了一个新的技术规范进入标准化进程,
这个编号为JSR-274的技术规范将把 BeanShell 引入为Java平台上支持的又一种编程语言。
(JSR, Original Java Specification Request)


JSR-274(http://jcp.org/en/jsr/detail?id=274)是由 Patrick Niemeyer 提交的技术规范,
其目标是将 BeanShell 脚本语言(http://www.beanshell.org/)
规范化为Java虚拟机平台上支持的第三种编程语言。


除了Java之外,Java虚拟机还支持Groovy脚本语言。
Doug Lea、Apache 和 Google 三个JCP执委会成员对此规范表示了支持。


按照Java最初的设计思路,有很多语言都可以在JVM上运行,详细列表参见:
http://en.wikipedia.org/wiki/List_of_Java_scripting_languages
但这些语言大多没有流行起来。直到2004年为止,Java平台事实上只有一种编程语言,也就是Java。
2004年3月, Groovy(JSR-241)成为了Java平台上的第二种编程语言。






下载与安装
---------------------------------------
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类的两种方式
-------------------------------------------------------------------------------
在Beanshell中可以调用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();
h{"foo"} = "bar"; // Equivalent to: h.put("foo", "bar");




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

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值