BeanShell(物件指令碼語言)
BeanShell使用背景:公司的抓取管理平臺,公司的產品人員每天都需要對各個地方的運營商網站看一些違規,投訴,公告等資訊進行監控,為了保證產品人員不必要每天都上各個網站上看資訊,所以針對內部需求,我們採用抓取策略,用程式模擬登入每一個網站,然後對我們要的資訊,如公告資訊進行抓取,當然抓取到網頁之後還要配合HtmlParse技術進行處理,然後將我們提取出的資訊顯示到我們平臺上,這樣產品人員不需要登入每一個網站看資訊,只要登入我們的抓取平臺就可以看各個網站最新的公告等資訊。因為每一個運營商的各個地方的網站是不一樣的,也就是說抓取的各個業務是不一樣的,針對這種情況,我們採用BeanShell來處理各個不同的業務。對不同的網站採用不同的
首先:BeanShell:是一種物件指令碼語言(http://www.beanshell.org)。BeanShell的直譯器是用Java寫的,開源並且免費的,它的運作方式“它將指令碼化物件看作簡單閉包方法(simple method closure)來支援,就如同在 JavaScript中的一樣。 它具有以下的一些特點:使用Java反射API以提供Java語句和表示式的實時解釋執行;可以透明地訪問任何Java物件和API;可以在命令列模式、控制檯模式、小程式模式和遠端執行緒伺服器模式等四種模式下面執行;與在應用
使用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():跟ava的System.out.println()非常的相像,除非它能保證輸出總是命令列。print()也可以顯示一些物件的型別(如陣列),但比Java的更詳細。
source(), run() : 將一個bsh指令碼讀到直譯器或執行在另一個直譯器。
frame() - 顯示一個Frame或JFrame的GUI元件.
load(), save() - 載入和儲存一個序列化的物件到一個檔案.
cd(), cat(), dir(), pwd(), etc. - 類unix的shell命令。
exec() - 執行一個本地的程式。
javap() - 列印一個物件的方法和欄位,類似於Java的javap命令。
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(未知源物件)。