1、可用的脚本引擎9 q& V) @) [$ j1 e
Java 6提供对执行脚本语言的支持,这个支持来自于JSR223规范,对应的包是javax.script。默认情况下,Java 6只支持javascript脚本,它底层的实现是Mozilla Rhino,它是个纯Java的javascript实现。可以通过下面的代码列出当前环境中支持的脚本引擎:
* T' M* e- i, ]. P 1.ScriptEngineManager manager = new ScriptEngineManager();. L. D0 u% l3 g @! y- c# ~. L
2. ListScriptEngineFactory> factories = manager.getEngineFactories();
. r2 i. q w! q( s 3. for (ScriptEngineFactory f : factories) {
9 [) r& w& ]4 F" [, d 4. System.out.println(
/ | h& K( f- J5 ?) E. D+ d 5. "egine name:"+f.getEngineName()+0 u& ^9 J: U! t6 t, w# S
6. ",engine version:"+f.getEngineVersion()+% t8 @; g. Q' E# u% ]2 d
7. ",language name:"+f.getLanguageName()+5 f5 P8 |7 b: n1 k- }, R4 m. \
8. ",language version:"+f.getLanguageVersion()+( d k+ L9 ?& ?7 p) X6 R( L
9. ",names:"+f.getNames()+8 z8 x. m) _( a0 g6 X4 H
10. ",mime:"+f.getMimeTypes()+; G' Y- K9 C) ~ {+ \ b6 f
11. ",extension:"+f.getExtensions());
$ t' \% a, }+ ^: \/ d/ I5 _& a" A 12. }
3 H$ ?& [9 B5 ` 输出结果:egine name:Mozilla Rhino,engine version:1.6 release 2,language name:ECMAScript,language version:1.6,names:[js, rhino, javascript, javascript, ECMAScript, ecmascript],mime:[application/javascript, application/ecmascript, text/javascript, text/ecmascript],extension:[js]。9 {0 R9 w% i5 G6 ?
可以看到,Java内置只支持javascript一种脚本。但是,只要遵循 JSR223,便可以扩展支持多种脚本语言,可以从https://scripting.dev.java.net/上查找当前已被支持的脚本的第三方库。! G" d) l/ G* B# V4 L2 q
2、hello script
# P# W0 G- p# I( m 接下来给出在Java中使用javascript的Hello world示例:- l2 A4 }! }4 s2 |0 H
13.ScriptEngineManager manager = new ScriptEngineManager ();
& @3 t/ A3 _2 T 14. ScriptEngine engine = manager.getEngineByName ("js"); F( W+ U; H" U* z! @, F/ W6 o5 F
15. String script = "print ('hello script')";
9 d9 l6 t. |6 C+ c# }* O 16. try {
( @4 Y% B5 B2 m2 z$ I# [ 17. engine.eval (script);
. N$ B8 i8 {% R8 T& o' `" x 18. } catch (ScriptException e) {; B' F; E# `; J. o8 R
19. e.printStackTrace();
z. v _6 i+ q i% R3 ^ 20. }8 Q4 K/ C$ A0 y' l( @8 q. c& E
使用的API还是很简单的,ScriptEngineManager是ScriptEngine的工厂,实例化该工厂的时候会加载可用的所有脚本引擎。从工厂中创建ScriptEngine可以使用getEngineByName、getEngineByExtension或 getEngineByMimeType来得到,只要参数名字能对上。执行脚本调用eval方法即可(效果等同于javascript中的eval)。
4 G7 {9 A* O2 d' N9 @; t& M% g7 y$ N 3、传递变量
0 ~% t' E7 ~1 m* |# y% D8 | 可以向脚本中传递变量,使得Java代码可以和脚本代码交互,示例如下:
. O4 j0 u2 P- F 21.ScriptEngineManager manager = new ScriptEngineManager();0 r6 C4 y2 ?8 I* E( H- C
22. ScriptEngine engine = manager.getEngineByName("js");
, m* R5 Q( K8 @7 H9 C 23. engine.put("a", 4);
( G) W0 s6 s) G4 h6 | 24. engine.put("b", 6);- T. W4 U7 c+ b- \0 b9 E
25. try {& u% R( L. P$ S& S* [& g
26. Object maxNum = engine.eval("function max_num(a,b){return (a>b)?a:b;}max_num(a,b);");% ~2 k7 v' {7 L3 N4 y
27. System.out.println("max_num:" + maxNum);3 n& f# N# c8 x
28. } catch (Exception e) {3 _5 f) L( ]* y9 J
29. e.printStackTrace();$ U+ {* _( _8 L& V# i0 n
30. }
2 q3 F6 y8 ]. ] 输出内容:max_num:69 A" f8 I3 S7 {1 F( a" J$ f
对于上面put的变量,它作用于自身engine范围内,也就是ScriptContext.ENGINE_SCOPE,put 的变量放到一个叫Bindings的Map中,可以通过 engine.getBindings(ScriptContext.ENGINE_SCOPE).get(“a”);得到put的内容。和 ENGINE_SCOPE相对,还有个ScriptContext.GLOBAL_SCOPE 作用域,其作用的变量是由同一ScriptEngineFactory创建的所有ScriptEngine共享的全局作用域。
) [, N$ a( i8 L 4、动态调用! }/ |) a: n/ @
上面的例子中定义了一个javascript函数max_num,可以通过Invocable接口来多次调用脚本库中的函数,Invocable接口是 ScriptEngine可选实现的接口。下面是个使用示例:
% c4 o- `$ v$ h8 U6 U2 X; r+ B 31.ScriptEngineManager manager = new ScriptEngineManager();6 n3 W$ ]! z& i* M$ U! _
32. ScriptEngine engine = manager.getEngineByName("js");
3 f, C* @# _) G* s: } 33. try {
+ ~& e* ]' | y& m5 M 34. engine.eval("function max_num(a,b){return (a>b)?a:b;}"); |