1. 程式人生 > >java6內建JS引擎初接觸

java6內建JS引擎初接觸

由於要用到該技術,所以寫了幾個測試,直接上程式碼。

定義外部資源E:/ScriptEngine/test01.js
if(age>=18){
	print('Old enough to vote!');
}else{
	print('Back to school!');
}

定義外部資源E:/ScriptEngine/test02.js

if(age<25){
	riskFactor = 1.5;
}else if(noClaims){
	ristFactor = 0.75;
}else{
	ristFactor = 1.0;
}

定義外部資源E:/ScriptEngine/test03.js


function Hello(){} 
Hello.prototype.sayHello = function(value){
	println('hello!'+value);
} 
var hello = new Hello();
hello.sayHello('World1');
	//使用指令碼引擎執行指令碼程式
	public static void test01() throws ScriptException{
		// 如果呼叫者可訪問執行緒上下文 ClassLoader,則呼叫此構造方法的效果與呼叫 ScriptEngineManager(Thread.currentThread().getContextClassLoader()) 相同
		//ScriptEngineManager檢索感興趣的指令碼編寫的語言的ScriptEngine物件
		ScriptEngineManager manager = new ScriptEngineManager();
		ScriptEngine engine = manager.getEngineByName("js");//ScriptEngine用來處理指令碼解釋和求值
		engine.put("age", 26);//賦值指令碼環境中所使用的變數
		engine.eval("if(age>=18){println('Old enough to vote!');}else{println('Back to school!');}");//解析 JavaScript 指令碼,對指令碼表示式進行求值
	}
	//使用指令碼引擎執行外部資源中的指令碼
	public static void test02() throws FileNotFoundException, ScriptException{
		ScriptEngineManager manager = new ScriptEngineManager();
		ScriptEngine engine = manager.getEngineByName("js");
		engine.put("age", 26);
		engine.eval(new FileReader("E:/ScriptEngine/test01.js"));//對檔案或其它外部資源中得指令碼表示式進行求值
	}
	//使用指令碼引擎檢索結果
	public static void test03() throws FileNotFoundException, ScriptException{
		ScriptEngineManager manager = new ScriptEngineManager();
		ScriptEngine engine = manager.getEngineByName("js");
		engine.put("age", 26);
		engine.put("noClaims", Boolean.TRUE);
		Object result = engine.eval(new FileReader("E:/ScriptEngine/test02.js"));//eval()函式返回執行指令碼後所返回的值,預設情況下,將返回上次執行的表示式的值
		System.out.println(result.toString());
	}

	//上下文屬性的作用域
	public static void test04() throws ScriptException{
		ScriptEngineManager manager = new ScriptEngineManager();
		Bindings globalBindings = manager.getBindings();//屬於ScriptEngineManager的全域性上下文,每個ScriptEngineManager擁有一個Bindings
		globalBindings.put("name", "yangYong");
		ScriptEngine engine = manager.getEngineByName("js");
		Bindings globalBindings02 = engine.getBindings(ScriptContext.GLOBAL_SCOPE);//每個引擎都共有一個ScriptEngineManager的Bindings
		System.out.println("name="+globalBindings02.get("name"));
		System.out.println(globalBindings==globalBindings02);
		ScriptContext context = engine.getContext();//每個引擎都有自己獨立的scriptContext上下文
		
		Bindings engineDefaultBindings = engine.getBindings(ScriptContext.ENGINE_SCOPE);//每個引擎的scriptContext中都有個預設屬於自己的Bindings
		engineDefaultBindings.put("gender", "男");
		engine.eval("name2 = name;println(name2);",engineDefaultBindings);
		engineDefaultBindings.put("name", "zhangSan");
		engine.eval("name2 = name;println(name2);",engineDefaultBindings);
		Bindings engineCreatBindings = engine.createBindings();//每個引擎的scriptContext中也可以新建多個屬於自己的Bindings
		engineCreatBindings.put("gender", "女");
		System.out.println(engineDefaultBindings==engineCreatBindings);
		System.out.println(engine.getBindings(ScriptContext.ENGINE_SCOPE).get("gender"));
		System.out.println(engineCreatBindings.get("gender"));
		engine.eval("name2 = name;println(name2);",engineCreatBindings);
	}

	//java應用程式與指令碼互動
	public static void test05() throws FileNotFoundException, ScriptException{
		ScriptEngineManager manager = new ScriptEngineManager();
		ScriptEngine engine = manager.getEngineByName("js");
		Bindings bindings = engine.createBindings();//Bindings:KV對對映,用來在Java應用程式和javascript指令碼之間交換資訊,即上下文
		bindings.put("age", 26);
		bindings.put("noClaims", Boolean.TRUE);
		bindings.put("riskFactor", 1.0);
		engine.eval("if(age<25){riskFactor = 1.5;}else if(noClaims){ristFactor = 0.75;}else{ristFactor = 1.0;}",bindings);//必須繫結bindings執行指令碼,否則報變數未定義異常
		double risk = (Double) bindings.get("riskFactor");
		System.out.println(risk);
	}

	//使用指令碼引擎執行指令碼程式
	public static void test01() throws ScriptException{
		// 如果呼叫者可訪問執行緒上下文 ClassLoader,則呼叫此構造方法的效果與呼叫 ScriptEngineManager(Thread.currentThread().getContextClassLoader()) 相同
		//ScriptEngineManager檢索感興趣的指令碼編寫的語言的ScriptEngine物件
		ScriptEngineManager manager = new ScriptEngineManager();
		ScriptEngine engine = manager.getEngineByName("js");//ScriptEngine用來處理指令碼解釋和求值
		engine.put("age", 26);//賦值指令碼環境中所使用的變數
		engine.eval("if(age>=18){println('Old enough to vote!');}else{println('Back to school!');}");//解析 JavaScript 指令碼,對指令碼表示式進行求值
	}

	//指令碼內部訪問java資源
	public static void test06() throws ScriptException{
		ScriptEngineManager manager = new ScriptEngineManager();
		ScriptEngine engine = manager.getEngineByName("js");
		engine.eval("importPackage(java.util)");//importPackage()函式允許在指令碼內部匯入java包,即可在指令碼中例項化java物件
		engine.eval("today = new Date();println(today);");
		engine.put("name", "ZhangSan");
		engine.eval("name2 = name.toUpperCase();println(name2);");
	}

	//重定向指令碼輸出
	public static void test07() throws IOException, ScriptException{
		ScriptEngineManager manager = new ScriptEngineManager();
		ScriptEngine engine = manager.getEngineByName("js");
		
		PipedReader pr = new PipedReader();
		PipedWriter pw = new PipedWriter(pr);
		//使用者可以通過與這個 PrintWriter 連通的 PrintReader 讀取實際的輸出,使 Java 應用程式能獲取指令碼執行輸出
		PrintWriter out = new PrintWriter(pw);
		engine.getContext().setWriter(out);
		
		engine.eval("println('hello from javascript!');");
		
		BufferedReader br = new BufferedReader(pr);
		System.out.println(br.readLine());
	}

//可編譯且可呼叫的引擎
	public static void test08() throws ScriptException{
		ScriptEngineManager manager = new ScriptEngineManager();
		ScriptEngine engine = manager.getEngineByName("js");
		if(engine instanceof Compilable){//判斷指令碼引擎是否支援編譯操作
			Compilable compilable = (Compilable)engine;//用來儲存編譯的結果,從而能重複呼叫指令碼而沒有重複解釋的開銷
			//compile()方法將指令碼編譯成無需重新編譯就能反覆執行的CompiledScript容器
			CompiledScript script = compilable.compile("if(age<25){riskFactor = 1.5;}else if(noClaims){ristFactor = 0.75;}else{ristFactor = 1.0;}");
			
			Bindings bindings = engine.createBindings();
			bindings.put("age", 26);
			bindings.put("noClaims", Boolean.TRUE);
			bindings.put("riskFactor", 1.0);
			
			Object result = script.eval(bindings);//使用CompiledScript的eval()方法計算編譯後的表示式
			System.out.println(result.toString());
		}
	}

	//呼叫指令碼中的函式和方法
	public static void test09() throws ScriptException, NoSuchMethodException, FileNotFoundException{
		ScriptEngineManager manager = new ScriptEngineManager();
		ScriptEngine engine = manager.getEngineByName("js");
		engine.eval("function increment(i){return i+1;}");
		if (engine instanceof Invocable) {//判斷指令碼引擎是否支援編譯操作
			Invocable invocable = (Invocable)engine;//Invocable允許從java程式碼呼叫定義在指令碼中的單個函式
			Object result = invocable.invokeFunction("increment", new Object[]{10});// 呼叫指令碼中定義的頂層程式和函式
			System.out.println("result = "+result);
		}
		
		ScriptEngine engine2 = manager.getEngineByName("js");
		engine2.eval(new FileReader("E:/ScriptEngine/test03.js"));
		if(engine2 instanceof Invocable){
			Invocable invocable = (Invocable)engine2;
			invocable.invokeMethod(engine2.get("hello"), "sayHello", "yangYong");//對以前的指令碼執行中已經編譯的指令碼物件(以 ScriptEngine 的狀態保持)呼叫某一方法
		}
	}

定義java檔案Hello.java

public interface Hello {
	public int increment(int value);
	public void sayHello(String name);
}

	//呼叫指令碼中的函式和方法並將他們作為java程式中的介面實現
	public static void test10() throws FileNotFoundException, ScriptException{
		ScriptEngineManager manager = new ScriptEngineManager();
		ScriptEngine engine = manager.getEngineByName("js");
		engine.eval("function increment(i){return i+1;}");
		if (engine instanceof Invocable) {
			Invocable invocable = (Invocable)engine;
			Hello hello = invocable.getInterface(Hello.class);//返回一個介面的實現,該介面使用直譯器中編譯的函式
			Object result = hello.increment(2);
			System.out.println("result = "+result);
		}
		engine.eval(new FileReader("E:/ScriptEngine/test03.js"));
		if(engine instanceof Invocable){
			Invocable invocable2 = (Invocable)engine;
			Hello hello = invocable2.getInterface(engine.get("hello"), Hello.class);// 返回一個介面的實現,該介面使用直譯器中已編譯指令碼物件的成員函式
			hello.sayHello("zhangSan");
		}
	}