1. 程式人生 > >BeanShell(物件指令碼語言)

BeanShell(物件指令碼語言)

BeanShell使用背景:公司的抓取管理平臺,公司的產品人員每天都需要對各個地方的運營商網站看一些違規,投訴,公告等資訊進行監控,為了保證產品人員不必要每天都上各個網站上看資訊,所以針對內部需求,我們採用抓取策略,用程式模擬登入每一個網站,然後對我們要的資訊,如公告資訊進行抓取,當然抓取到網頁之後還要配合HtmlParse技術進行處理,然後將我們提取出的資訊顯示到我們平臺上,這樣產品人員不需要登入每一個網站看資訊,只要登入我們的抓取平臺就可以看各個網站最新的公告等資訊。因為每一個運營商的各個地方的網站是不一樣的,也就是說抓取的各個業務是不一樣的,針對這種情況,我們採用BeanShell來處理各個不同的業務。對不同的網站採用不同的

BSH檔案來處理,這樣各個網站的抓取程式碼都放到不同的BSH檔案中,不用每多抓取一個網站重新修改程式碼,重新發布。這樣可以減少很多工作量。下面介紹一下BeanShell.

首先:BeanShell:是一種物件指令碼語言http://www.beanshell.org)。BeanShell的直譯器是用Java寫的,開源並且免費的,它的運作方式它將指令碼化物件看作簡單閉包方法simple method closure)來支援,就如同在 JavaScript中的一樣。 它具有以下的一些特點:使用Java反射API以提供Java語句和表示式的實時解釋執行;可以透明地訪問任何Java物件和API;可以在命令列模式、控制檯模式、小程式模式和遠端執行緒伺服器模式等四種模式下面執行;與在應用

程式中一樣,可以在小程式中(Applet)正常執行(無需編譯器或者類裝載器);非常精簡的直譯器jar檔案大小為175k ”

使用BeanShell可以處理現實中不規則的業務,舉個很典型的例子,我們知道,一個保險公司有很多險種,每個險種的投入和收益的演算法是很複雜的,無法用規則的關係資料庫模型來描述,所以很多保險系統在處理險種的演算法都是硬編碼,如果要在系統中新加一個險種,是非常麻煩的,重新修改程式碼,重新發布,這對開發/維護人員和客戶都是很痛苦的,有了BeanShell,我們可以從這種痛苦中解脫出來,對每個險種使用不同的指令碼,新加的險種我們新配一個指令碼,這樣既可以滿足業務多變的要求,又可以減少工作量,節約成本。

BeanShell的一個特點是動態執行Java程式碼,指令碼檔案改變不會影響當前指令碼的呼叫,新指令碼將在指令碼的下一次呼叫生效,這不同於配置檔案,配置檔案改變一般都需要應用重啟。

一個BeanShell的簡單例子:

通過建立一個BeanShell直譯器,使用eval()source()命令,你可以在你的應用程式中求文字表示式的值和執行指令碼。如果你希望在你的指令碼內部使用一個物件,可以用set()方法傳遞物件的變數參照給BeanShell,並通過get()方法取得結果。

Java檔案中

package com.an;

import java.io.FileNotFoundException;

import java.io.IOException;

import bsh.EvalError;

import bsh.Interpreter;

publicclass TestBeanShell {

/**

*一個簡單往BEANSHELL的檔案傳入引數,然後.java檔案接收引數進行處理,然後返回結果

*.java檔案中列印結果

*/

publicstaticvoid main(String[] args) {

Interpreterinter= new Interpreter();

try {

//bsh檔案中傳入引數(BeanShell檔案中可以直接用,不用再定義)

inter.set("inValue",new Integer(1));

//呼叫並執行BSH檔案

inter.source("src/com/an/testBeanShell.bsh");

//獲得bsh檔案中的結果

String resultValue = inter.get("outValue").toString();

System.out.println("=====輸出結果========="+resultValue);

} catch (EvalError e) {

e.printStackTrace();

} catch (FileNotFoundException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

}

}

Bsh檔案

//BeanShell中列印呼叫print()函式

print("=======傳入的引數======="+inValue);

outValue = inValue+1;

一些常用的命令 (綠色的是我在專案中用到的)

print()avaSystem.out.println()非常的相像,除非它能保證輸出總是命令列。print()也可以顯示一些物件的型別(如陣列),但比Java的更詳細。

source(), run() : 將一個bsh指令碼讀到直譯器或執行在另一個直譯器。

frame() - 顯示一個FrameJFrameGUI元件.
load(), save() -
載入和儲存一個序列化的物件到一個檔案
.
cd(), cat(), dir(), pwd(), etc. -
unixshell命令。

exec() -
執行一個本地的程式。

javap() - 列印一個物件的方法和欄位,類似於Javajavap命令。
setAccessibility() - 開啟無限制的存取private protected的元件。

指令碼方法

你可以在bsh中宣告和使用方法,就像在java的類中一樣。只是bsh的方法可以有動態的(寬鬆的)引數和返回型別。

//bsh檔案中的定義方法(兩個數相加)

public int add(int num1 , int num2 ){

return num1+num2;

}

int result = add(1,2);

print(result);

注意:bsh檔案的載入順序是從上到下載入,上面例子中如果

int result = add(1,2);

print(result);

public int add(int num1 , int num2 ){

return num1+num2;

}

則會報

ourced file: src/com/an/testBeanShell.bsh : Typed variable declaration : Command not found: add( int, int ) : at Line: 1 : in file: src/com/an/testBeanShell.bsh : add ( 1 , 2 )

at bsh.Name.invokeLocalMethod(Unknown Source)

這個是BSH檔案中常到的一個錯誤Unknown Source未知源物件)。