分享
 
 
 

为Java应用程序加入脚本引擎

王朝java/jsp·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

为Java应用程序加入脚本引擎

内容:

前言

常见的脚本引擎

什么是BeanShell?

BeanShell脚本语言简介

在应用程序中嵌入脚本引擎

示例程序

写一个简单的脚本

总结

例程下载

参考资料

关于作者

相关内容:

TCP/IP 介绍

TCP/IP 介绍

--

Java 专区中还有:

教学

工具与产品

代码与组件

所有文章

实用技巧

陈先波 (turbochen@163.com)

Author name (email address)

--赛微科技

2002 年 11 月

前言

现代许多流行的应用程序,越来越多的使用了脚本引擎,最典型的有Microsoft Office中的VBA等。脚本引擎能提供应用程序极大的可扩展性,也是被许多热忠于二次开发的使用者所乐意看到的。本文主要讲解BeanShell----这样一个Java应用程序脚本引擎,你会了解它的基本特性,及如何将它嵌入到你的应用程序中。你将看到,为自己的应用程序加上脚本引擎是多么容易的一件事情。

常见的脚本引擎

现在网络上流行着许多种脚本语言,如TCL,Perl, JavaScript,Python等,并且有许多脚本语言都有基于Java的解释器,就笔者所知道的有如下几种:

Language

Java Implementation

JavaScript

Rhino

Python

Jython (formerly JPython)

Tcl/Tk

Jacl

Perl

None

Java itself

BeanShell

以上几种脚本都有各自的语法,而其中JavaScript和BeanShell的语法,对于使用者来说更具有亲切感。本文主要讲解BeanShell的的特性及其如何集成到Java应用程序中。

什么是BeanShell?

BeanShell是一个小型的,免费的,可嵌入式的,具有面向对象脚本语言特性的Java代码解释器。它是用Java语言写的。它能执行标准的Java语句和表达式,还自带简单的脚本命令和语法。它把编程对象当成一个简单的方法,这很像Perl和JavaScript.

你可以在写Java测试或调试时使用BeanShell,也可以用它作为你的应用程序的脚本引挚。简而言之,BeanShell可以动态的解释JAVA语言。也就是说BeanShell在许多方面对于Java的用处就像Tcl/Tk对于C的用处一样:BeanShell是可嵌入式的---你可以在运行时从你的应用程序调用BeanShell去动态的执行Java代码或是为你的应用程序提供脚本扩展。相反,你也可以从BeanShell调用你的应用程序及其对象,它可以让JAVA对象和API动态运行。正因为BeanShell是用JAVA写的,所以它可以和你的应用程序运行在同一个JVM空间内,你也可以自由的传递实时对象的引用(References)到脚本代码中并且作为结果返回。

BeanShell脚本语言简介

BeanShell能理解标准的JAVA语句,表达式,和方法宣告。语句和表达式的内容可以是:变量,宣告,赋值,方法调用,循环,条件等。

在Java程序中你必须严格的使用它们,但在BeanShell中,你可以用"宽松类型"(loosely typed)的方式来使用它们。也就是说,你可以在写脚本时偷懒,不进行变量类型的宣告(在原始数据类型和对象都可以)。如果你试着用错变量类型,BeanShell将会给出一个错误。总之BeanShell的脚本是很容易上手的。

这里有一个简单的例子:

foo = "Foo";

four = (2 + 2)*2/2;

print( foo + " = " + four ); // print() 是BeanShell的一个脚本命令。

// 循环

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

你也可以在Beanshell脚本中宣告和定义自己的方法:

int multiply(int a, int b)

{

return a*b;

}

print(multiply(12,14));//打印出168

BeanShell的变量或参数的类型可以不用显示的指定,如下:

int multiply(a, b)

{

return a*b;

}

result = multiply(12,14);

print(result);//打印出168

在BeanShell中也可以写对象。它与JavaScript很相似,它用一个方法,再内嵌一些内部方法,并且在未尾返回一个this来实现对象的编程:

Employee()

{

age = 26;

sex = "M";

name = "Turbo";

int getAge()

{

return age;

}

String getSex()

{

return sex;

}

String getName()

{

return name;

}

return this;

}

turbo = Employee(); // 构造一个Employee对象。

print("Name:"+turbo.getName); //打印出employee的名字。

上面的程序片断,相信大家已经对BeanShell的语法有了一个印象,你可以通过参考资料中的链接,找到更详细的BeanShell的脚本语法教程。

在应用程序中嵌入脚本引擎

其实在Java中调用bsh的脚本非常简单,你需要先创建一个Interpreter类的实例.然后就可以用它运行你的脚本代码或者脚本文件。请看下面的一个例子,这个例子来自于BeanShell的文档:

Import bsh.*;

//创建一个bsh解释器实例

Interpeter bsh = new Interpreter();

// 表达式求值

bsh.eval("foo=Math.sin(0.5)");

bsh.eval("bar=foo*5; bar=Math.cos(bar);");

bsh.eval("for(i=0; i<10; i) { print(\"hello\"); }");

// 运行语句。

bsh.eval("for(int i=0; i<10; i) { System.out.println(\"hello\"); }");

// 载入脚本文件

bsh.source("myscript.bsh"); // or bsh.eval("source(\"myscript.bsh\")");

// 使用set()和get()方法存取变量值。

bsh.set( "date", new Date() );

Date date = (Date)bsh.get( "date" );

// This would also work:

Date date = (Date)bsh.eval( "date" );

bsh.eval("year = date.getYear()");

Integer year = (Integer)bsh.get("year"); // primitives use wrappers

// 也可以实现任意的Java Interface..

// 或处理AWT事件。

bsh.eval( "actionPerformed( e ) { print( e ); }");

ActionListener scriptedHandler =

(ActionListener)bsh.eval("return (ActionListener)this");

Use the scripted event handler normally...

new JButton.addActionListener( script );

示例程序

为了让读者更好的理解,我们在这里以jdk1.4中的一个演示程序,Notepad程序作为基础,向读者讲解BeanShell是如何嵌入到Notepad程序中的。如果你安装了JDK1.4的话,Notepad源程序可以在<JAVA_HOME>\demo\jfc\Notepad目录中找到.

笔者写的一个BeanShell类,用来运行用户的脚本,下面的该程序的完整清单:

import javax.swing.text.*;

import javax.swing.*;

import java.io.*;

import bsh.*;

public class BeanShell

{

private static NameSpace namespace;

private static boolean running;

private static Notepad notepad;

//初始化引擎

public static void initBeanShell(Notepad pad)

{

notepad = pad;

namespace = new NameSpace("Notepad embedded scripting engine.");

}

//运行一段脚本代码

public static void runScript(String script)

{

try

{

StringReader reader = new StringReader(script);

runScript( "New script", reader);

}

catch(Exception ex)

{

ex.printStackTrace();

System.out.println(ex);

return;

}

}

public static void runScript(String scriptInfo, Reader reader)

{

Interpreter interpreter = new Interpreter(reader,System.out,System.out,true,namespace);

try

{

if(notepad != null)

{

JTextComponent editor = notepad.getEditor();

interpreter.set("application",notepad); //将应用程序的变量传入解释器,

interpreter.set("editor", editor); //这样就可在脚本中使用这个变量参照

running = true;

interpreter.eval(reader, namespace, scriptInfo);

}

}

catch(Throwable throwable)

{

throwable.printStackTrace();

JOptionPane.showMessageDialog(notepad,

new Object[]

{"Script 错误!",

throwable.getMessage()},

"错误",JOptionPane.ERROR_MESSAGE);

}

finally

{

running = false;

}

}

public static boolean isMacroRunning()

{

return running;

}

}

这个BeanShell提供了三个方法,

void initBeanShell(Notepad),这个方法进行初始化。

void runScript(String script),这个方法可直接运行脚本代码。

void runScript(String scriptInfo, Reader reader),这个方法可从一个Reader流中运行脚本。

而真正核心的执行脚本的代码在void runScript(String scriptInfo, Reader reader)方法中,大家注意,代码中先创建了一个BeanShell的解释器实例,

Interpreter interpreter = new Interpreter(reader,System.out,System.out,true,namespace);

然后将Notepad程序的实例变量传入解释器,这样就可直接在脚本中引用Notedpad的实例了,

JTextComponent editor = notepad.getEditor();

interpreter.set("application",notepad); //将应用程序的变量传入解释器,

interpreter.set("editor", editor); //这样就可在脚本中使用这个变量参照

接下来看看如何把BeanShell嵌入到Notepad程序中,笔者写了几个类, Main,用来初始化,并在Notepad程序中加入一个"Script Editor"的菜单 ScriptEditor,简单的脚本编辑器,用来编辑或载入脚本,运行脚本程序。 ScriptEditorAction,启动Script Editor的Action.

下面是Main.class的主要代码,

Notepad notepad = new Notepad();

JMenu editMenu = new JMenu("Script Editor");

JMenuItem editItem = new JMenuItem();

editMenu.add(editItem);

editItem.setAction(new ScriptEditorAction(notepad));

notepad.getMenubar().add(editMenu);

以上程序取得Notepad程序的Menu Bar,并添加一个Script Editor菜单到其中,这样,就可不用修改Notepad程序,并在其中加入启动Script Editor的菜单。

下图是程序运行中的画面:

这个程序的完整代码,请在文章未尾的参考资料中去下载。

写一个简单的脚本

现在我们写一个简单的脚本代码,用来统计某个单词在Notepad文章中的出现次数,下面列出这个脚本的代码:

/**

* 字串统计程序。

* @author: turbo chen

*/

//字串统计函数

counter(s)

{

str = editor.getText();

str = str.toLowerCase();

slen = s.length();

s = s.toLowerCase();

count = 0;

from = 0;

while ( (from=str.indexOf(s,from))>-1 )

{

count = count + 1;

from = from + slen;

}

return count;

}

// application 是经由BeanShell传入的应用程序对象。

target = JOptionPane.showInputDialog(application,"Please input the count target:");

if ( target != null )

{

count = counter(target);

JOptionPane.showMessageDialog(application,"Found "+count+" targets.");

}

将上面的脚本输入到"Script Editor"视窗中,运行它。看看程序运行的画面:

(查找"of"这个单词在文章中出现的次数,)

(找到13个目标。)

总结

本文讲解了BeanShell脚本引擎如何在现有的应用程序中应用,也让读者了解到BeanShell脚本的基本特性与脚本语法,让大家看到嵌入脚本引擎到Java应用程序中是多么的容易。

例程下载

notepad.rar包括了本文示例中的所有源码。

参考资料

这儿有一个作者翻译的BeanShell的中文简介: http://www.csdn.net/develop/read_article.asp?id=15090

BeanShell的完整在线教程: http://www.beanshell.org/manual/contents.html

你也可以直接到BeanShell的首页下载最新的BeanShell引擎: http://www.beanshell.org/

如果想了解BeanShell与其它几种脚本语言之间的评测文章,可以点击下面的链接: http://tech.enet.com.cn/document/20020521/20020521154519011.shtml

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有