在默认情况下,Java SE6只支持javascript,但这也提供了一些接口,也就是脚本规范,JSR223。通过这些接口,Java SE6可以支持任意的脚本语言。
在javax.script包中有很多的类,但这些类中最主要的是ScripEngineManager。通过这个类得到当前Java SE6所支持的所有脚本。
import javax.script.*;
import java.io.*;
import java.util.*;
import static java.lang.System.*;
public class ListScriptEngines
{
public static void main(String args[]){
ScriptEngineManager manager = new ScriptEngineManager();
// 得到所有的脚本引擎工厂
List factories = manager.getEngineFactories();
// 这是Java SE 5 和Java SE 6的新For语句语法
for (ScriptEngineFactory factory: factories){
// 打印脚本信息
out.printf("Name: %s%n" +
"Version: %s%n" +
"Language name: %s%n" +
"Language version: %s%n" +
"Extensions: %s%n" +
"Mime types: %s%n" +
"Names: %s%n",
factory.getEngineName(),
factory.getEngineVersion(),
factory.getLanguageName(),
factory.getLanguageVersion(),
factory.getExtensions(),
factory.getMimeTypes(),
factory.getNames());
// 得到当前的脚本引擎
ScriptEngine engine = factory.getScriptEngine();
} } }
其中import static java.lang.System.*是将System中的所有静态成员进行引用。得到一个具体的脚本引擎有3种方法。
(1)根据扩展名得到脚本引擎
ScriptEngine engine = manager.getEngineByExtension("js");
(2)根据Mime类型得到脚本引擎
ScriptEngine engine = manager.getEngineByMimeType("text/javascript");
(3)根据名称得到脚本引擎
ScriptEngine engine = manager.getEngineByName("javascript");
可以使用ScriptEngine的eval方法来执行脚本,eval方法被重载的多次,但最常用的是public Object eval(String script)。
import javax.script.*;
import java.io.*;
import static java.lang.System.*;
public class FirstJavaScript
{
public static void main(String args[])
{
ScriptEngineManager manager = new ScriptEngineManager();
// 得到javascript脚本引擎
ScriptEngine engine = manager.getEngineByName("javascript");
try
{
// 开始运行脚本,并返回当前的小时
Double hour = (Double)engine.eval("var date = new Date();" +"date.getHours();");
String msg;
// 将小时转换为问候信息
if (hour < 10)
{
msg = "上午好";
}
else if (hour < 16)
{
msg = "下午好";
}
else if (hour < 20)
{
msg = "晚上好";
}
else
{
msg = "晚安";
}
out.printf("小时%s: %s%n", hour, msg);
}
catch (ScriptException e)
{
err.println(e);
}
}
}
和脚本语言进行交互
ScriptEngine有两个方法put和get:
(1)put有两个参数,一个是脚本变量名,另一个是变量的值,这个值是Object类型,因此,可以传递任何值。
(2)get有一个参数,就是脚本变量的名。
import javax.script.*;
import java.io.*;
import static java.lang.System.*;
public class ReverseString
{
public static void main(String args[])
{
ScriptEngineManager manager = new ScriptEngineManager();
// 建立javascript脚本引擎
ScriptEngine engine = manager.getEngineByName("javascript");
try
{
// 将变量name和变量值abcdefg传给javascript脚本
engine.put("name", "abcdefg");
// 开始执行脚本
engine.eval("var output ='' ;" +
"for (i = 0; i <= name.length; i++) {" +
" output = name.charAt(i) + output" +
"}");
// 得到output变量的值
String name = (String)engine.get("output");
out.printf("被翻转后的字符串:%s", name);
}
catch (ScriptException e)
{
err.println(e);
}
}
}
compilable接口
只有实现了Compilable接口的脚本引擎才可以使用compile进行编译(这里的编译一般将不是生成可执行文件,而只是在内存中编译成更容易运行的方式),可以使用ScriptEngine的compile方法进行编译。
import javax.script.*;
import java.io.*;
import static java.lang.System.*;
public class CompileScript
{
public static void main(String args[])
{
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("javascript");
engine.put("counter", 0); // 向javascript传递一个参数
// 判断这个脚本引擎是否支持编译功能
if (engine instanceof Compilable)
{
Compilable compEngine = (Compilable)engine;
try
{
// 进行编译
CompiledScript script = compEngine.compile("function count() { " +
" counter = counter +1; " +
" return counter; " +
"}; count();");
out.printf("Counter: %s%n", script.eval());
out.printf("Counter: %s%n", script.eval());
out.printf("Counter: %s%n", script.eval());
}
catch (ScriptException e)
{
err.println(e);
}
}
else
{
err.println("这个脚本引擎不支持编译!");
}
}
}
Invocable接口
实现Invocable接口可以动态调用脚本语言中的方法。
import javax.script.*;
import java.io.*;
import static java.lang.System.*;
public class InvocableTest
{
public static void main(String args[])
{
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("javascript");
String name="abcdefg";
if (engine instanceof Invocable)
{
try
{
engine.eval("function reverse(name) {" +
" var output =' ';" +
" for (i = 0; i <= name.length; i++) {" +
" output = name.charAt(i) + output" +
" } return output;}");
Invocable invokeEngine = (Invocable)engine;
Object o = invokeEngine.invokeFunction("reverse", name);
out.printf("翻转后的字符串:%s", o);
}
catch (NoSuchMethodException e)
{
err.println(e);
}
catch (ScriptException e)
{
err.println(e);
}
}
else
{
err.println("这个脚本引擎不支持动态调用");
}
}
动态实现接口
如果我们要想让脚本异步地执行,即通过多线程来执行,那InvokeEngine类必须实现Runnable接口才可以通过Thread启动多线程。
import javax.script.*;
import static java.lang.System.*;
public class InterfaceTest
{
public static void main(String args[])
{
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("javascript");
try
{
engine.eval("function run() {print(异步调用);}");
Invocable invokeEngine = (Invocable)engine;
Runnable runner = invokeEngine.getInterface(Runnable.class);
Thread t = new Thread(runner);
t.start();
t.join();
}
catch (InterruptedException e)
{
err.println(e);
}
catch (ScriptException e)
{
System.err.println(e);
}
}
}
最后欢迎大家访问我的个人网站:1024s