隨著java6.0的出現,向java嵌入javascript腳本變的特別容易。java6引入了一個新的javax.script包,為腳本化語言提供了一個通用接口。
案例:http://www.5a520.cn 小說520網
java中嵌入javascript腳本的思路:
1.取得腳本解釋器的管理器Manager
2.從管理器中取得js的解釋器實例ScriptEngine
3.取得存儲javascript變量的Bindings實例
4.把一個java.io.Reader流及Bindings傳遞給ScriptEngine的eval()方法,從而運行存儲在外部文件中的腳本。eval()方法返回腳本運行結果,如果執行中發生錯誤,會拋出ScriptException異常。
例:運行javascript腳本的一個java程序
import java.io.*;
import javax.script.Bindings;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

/** *//**
author by http://www.bt285.cn/content.php?id=1196863
*/

public class RunScript
{

public static void main(String[] args) throws IOException
{
ScriptEngineManager scriptManager = new ScriptEngineManager();//得到解釋器的管理器,里面有很多種腳本解釋器
ScriptEngine js = scriptManager.getEngineByExtension("http://www.bt285.cn/aidesefang/ js");//從管理器中獲取js的解釋器
//定義我們要運行的腳本文件
String filename = null;
//通過解釋器來獲得存儲javascript變量的Bindings的實例,使它們提供給腳本。
Bindings bindings = js.createBindings();
//處理參數,參數是定義的腳本的變量。參數可能包括-Dname/value對。我們要進行處理,任何參數不能以‘-D’為文件名開始

for(int i = 0;i<args.length;i++)
{
String arg = args[i];

if(arg.startsWith("-D"))
{//如果參數是以“-D”開頭,則進行處理
int pos = arg.indexOf('=');
if(pos == -1) usage();
String name=arg.substring(2,pos);
String value= arg.substring(pos+1);
//注意:我們定義的所有的變量是字符串,如果必要的話,我們可以通過java.lang.Number ,一個java.lang.Boolean,任何Java對象或NULL,將腳本轉換為其他類型。
bindings.put(name, value);//腳本中的變量存入bindings實例中

}else
{
if(filename!=null)usage();
filename=arg;
}
}
//這里是為了確保我們得到了一個文件的參數。

if(filename==null)
{
usage();
}
//增加一個具有約束力的使用特殊的保留變量名稱,告訴腳本引擎的文件的名稱將執行。這使它能夠提供更好的錯誤信息
bindings.put(ScriptEngine.FILENAME, filename);
//讀取文件的流
Reader in = new FileReader(filename);

try
{
//執行腳本并取得結果。注意in就相當于js中的腳本,而bindings是腳本執行所需要的變量
Object result = js.eval(in,bindings);
System.out.println(result);

}catch(ScriptException ex)
{
//執行過程中出異常則顯示一個錯誤信息
System.out.println(ex);
}
}

static void usage()
{
System.err.println("Usage: java RunScript[-Dname=value
] script.js");
System.exit(1);//異常退出程序。如果正常退出程序用System.exit(0);
}
}

這段代碼中所創建的Bindings對象不是靜態的,JavaScript腳本所創建的所有的變量都存儲在這里。下面是一個腳本化Java的更加實用的例子。它將它的Bindings對象存儲在一個具有較高的作用域的ScriptContext對象中,以便可以讀取其變量,但是新的變量就不存儲到Binhdings對象中。這個例子實現了一個簡單的配置文件工具,即一個文本文件,用來定義名字/值對,可以通過這里定義的Configuration類來查詢它們。值可能是字符串、數字或布爾值,并且,如果一個值包含在花括號中,那么它就會傳遞給一個JavaScript解釋器去計算。java.util.Map對象保存了這些包裝在一個SimpleBindings對象中的值,這樣一來,JavaScript解釋器也可以訪問同一個文件中定義的其他變量的值。
import javax.script.*;
import java.util.*;
import java.io.*;

/** *//**
author by http://www.bt285.cn/sejishikong/
*/
//這個類像java.util.Properties ,但是允許屬性值執行javascript表達式

public class Configuration
{
Map<String,Object> defaults = new HashMap<String,Object>();
//在map中獲取和設置值的方法

public Object get(String key)
{
return defaults.get(key);
}

public void put(String key,Object value)
{
defaults.put(key, value);
}
//從map的name/value對中獲取初始化內容。如果一個值在大括號內,表示是一個javascript腳本,計算它

public void load(String filename) throws IOException,ScriptException
{
//獲得javascript編譯器
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByExtension("http://www.bt285.cn/yazhou/ js");
//使用我們的name/value對(即javascript變量)
Bindings bindings = new SimpleBindings(defaults);
//創建一個變量,用于存放腳本執行的內容
ScriptContext context = new SimpleScriptContext();
//設置那些Bindings 在Context 中,使它們可讀。但這樣的變量定義的腳本不要放入我們的Map中
context.setBindings(bindings, ScriptContext.GLOBAL_SCOPE);
BufferedReader in = new BufferedReader(new FileReader(filename));
String line;

while((line=in.readLine())!=null)
{
line = line.trim();
if(line.length()==0) continue;//跳過空行
if(line.charAt(0)=='#')continue;//跳過命令
int pos = line.indexOf(":");

if(pos == -1)
{
throw new IllegalArgumentException("syntax:"+line);
}
String name = line.substring(0,pos).trim();
String value= line.substring(pos+1).trim();
char firstchar = value.charAt(0);
int len = value.length();
char lastchar = value.charAt(len-1);

if(firstchar=='"'&&lastchar=='"')
{
//雙引號引用的值為字符串
defaults.put(name, value.substring(1,len-1));

}else if(Character.isDigit(firstchar))
{
//如果開始是一個數字

try
{
double d = Double.parseDouble(value);
defaults.put(name, value);

}catch (NumberFormatException e)
{
//沒有數字,是一個string
defaults.put(name, value);
}

}else if("true".equals(value))
{//處理布爾值
defaults.put(name,Boolean.TRUE);

}else if("false".equals(value))
{
defaults.put(name, Boolean.FALSE);

}else if("null".equals(value))
{//處理null值
defaults.put(name, null);

}else if(firstchar=='{'&&lastchar=='}')
{
//如果值是在一對大括號之內,則執行javascript代碼
String script = value.substring(1,len-1);
Object result = engine.eval(script,context);
defaults.put(name, result);

}else
{
//其它情況,剛好是一個字符串
defaults.put(name, value);
}
}
}
//一個簡單的類的測試程序

public static void main(String[] args) throws IOException,ScriptException
{
Configuration defaults = new Configuration();
defaults.load(args[0]);
Set<Map.Entry<String, Object>> entryset = defaults.defaults.entrySet();

for(Map.Entry<String, Object> entry:entryset)
{
System.out.printf("%s:%s%n",entry.getKey(),entry.getValue());
}
}
}
