java语言的动态性支持_JDK1.7新特性(3):java语言动态性之脚本语言API

1 packagecom.rampage.jdk7.chapter2;2

3 importjava.io.FileWriter;4 importjava.io.IOException;5

6 importjavax.script.Bindings;7 importjavax.script.Compilable;8 importjavax.script.CompiledScript;9 importjavax.script.Invocable;10 importjavax.script.ScriptContext;11 importjavax.script.ScriptEngine;12 importjavax.script.ScriptEngineManager;13 importjavax.script.ScriptException;14 importjavax.script.SimpleBindings;15

16 /**

17 * 简单的脚本引擎使用方法18 *19 *@authorzyq20 *21 */

22 public classSimpleScriptAPI {23 public static void main(String[] args) throwsScriptException, IOException, NoSuchMethodException {24 SimpleScriptAPI simpleScriptEngine = newSimpleScriptAPI();25

26 //Part 1: 通用的脚本引擎用法

27 ScriptEngine engine =simpleScriptEngine.getJavaScriptEngine();28 if (engine == null) {29 throw new RuntimeException("找不到JavaScript脚本执行引擎!");30 }31 engine.eval("var a = 12;");32

33 //Part 2: 不同脚本语言与java之间的对象绑定

34 engine.put("name", "Alex");35 engine.eval("var message = 'hello ' + name");36 Object message = engine.get("message");37 System.out.println(message); //hello Alex38

39 //当然也可以通过SimpleBinds对象来进行变量绑定或者通过脚本引擎的createBindings方法

40 Bindings bindings = newSimpleBindings();41 bindings =engine.createBindings();42 bindings.put("hobby1", "java");43 bindings.put("hobby2", "dota");44 engine.eval("var message2 = 'I like ' + hobby1 + ' and ' + hobby2", bindings);45 //使用binding来绑定的变量只能在脚本语言内部是使用,java语言内获取不到对应的变量

46 System.out.println(engine.get("message2")); //null

47 System.out.println(engine.get("hobby1")); //null

48 System.out.println(engine.get("hobby2")); //null

49 engine.put("hobby1", "java");50 engine.put("hobby2", "dota");51 engine.eval("var message2 = 'I like ' + hobby1 + ' and ' + hobby2");52 System.out.println(engine.get("message2")); //I like java and dota

53 System.out.println(engine.get("hobby1")); //java

54 System.out.println(engine.get("hobby2")); //dota55

56 //Part 3: 脚本执行上下文57 //ScriptContext的setReader/setWriter/setErrorWriter可以分别设置脚本执行时候的输入来源,输出目的地和错误输出目的地

58 ScriptContext context =engine.getContext();59 context.setWriter(new FileWriter("output.txt"));60 engine.eval("var a = 13");61 //ScriptContext中也有setAttribute和getAttribute方法来自定义属性。属性有不同的作用域之分。62 //每个作用域都以一个对应的整数表示其查找顺序,该整数越小,说明查找时的顺序更优先。63 //因此在设置属性时需显示的指定所在的作用域,在获取属性的时候可以指定查找的作用域。也可以选择根据作用域优先级64 //自动进行查找。65 //但是脚本执行上下文所能包含的作用域可以通过 getScopes 方法得到而不能随意指定

66 System.out.println(context.getScopes()); //[100, 200]67 //ScriptContext预先定义了两个作用域: ENGINE_SCOPE(当前脚本引擎) 和 GLOBAL_SCOPE(从同一引擎工厂创建出来的所有脚本引擎),前者的优先级更高

68 context.setAttribute("name", "Alex", ScriptContext.GLOBAL_SCOPE);69 context.setAttribute("name", "Bob", ScriptContext.ENGINE_SCOPE);70 System.out.println(context.getAttribute("name")); //Bob71 //ScriptContext的setbindings方法设置的语言绑定对象会影响到ScriptEngine在执行脚本时的变量解析。72 //ScriptEngine的put和get方法所操作的实际上就是ScriptContext中作用域为ENGINE_SCOPE的语言绑定对象。73 //从ScriptContext中得到语言绑定对象之后,可以直接对这个对象进行操作。如果在ScriptEngine的eval中没有74 //指明所使用的语言绑定对象,实际上起作用的是ScriptContext中作用域为ENGINE_SCOPE的语言绑定对象。

75 Bindings binding1 =engine.createBindings();76 binding1.put("name", "Alex");77 context.setBindings(binding1, ScriptContext.GLOBAL_SCOPE);78 Bindings binding2 =engine.createBindings();79 binding2.put("name", "Bob2");80 context.setBindings(binding2, ScriptContext.ENGINE_SCOPE);81 System.out.println(engine.get("name")); //Bob2

82 Bindings binding3 =context.getBindings(ScriptContext.ENGINE_SCOPE);83 binding3.put("name", "Alex2");84 System.out.println(engine.get("name")); //Alex2

85 context.setAttribute("name", "Bob3", ScriptContext.ENGINE_SCOPE);86 System.out.println(engine.get("name")); //Bob387

88 //Part 4: 脚本的编译89 //脚本语言一般是解释执行的,脚本引擎在运行时需要先解析脚本之后再执行。一般来说90 //通过解释执行的方式运行脚本的速度比先编译再运行会慢一些。所以对于需要多次执行的脚本,我们91 //可以选择先编译,以防止重复解析。不是所有的脚本语言都支持对脚本进行编译,如果脚本支持92 //编译,他会实现 javax.script.Compilable接口。编译的结果用CompiledScript来表示。

93 if (engine instanceofCompilable) {94 CompiledScript script = ((Compilable) engine).compile("var a = 12; b = a * 3;");95 script.eval();96 }97

98 //Part 5: 方法调用99 //有些脚本引擎允许使用者单独调用脚本中的某个方法。支持这种调用方法的脚本引擎可以实现100 //javax.script.Invocable 接口。通过Invocable接口既可以调用脚本中的顶层方法,也可一101 //调用对象中的成员方法。如果脚本中的顶层方法或者对象中的成员方法实现了java中的接口,102 //可以通过Invocable接口中的方法来获取及脚本中对应的java接口 的实现对象。这样就可以103 //在java中定义借口,在脚本中实现接口。程序中使用该接口的其他部分代码并不知道接口是104 //由脚本来实现的。

105 String scriptText = "function greet(name) {return 'hello ' + name; }";106 engine.eval(scriptText);107 Invocable invocable =(Invocable) engine;108 System.out.println(invocable.invokeFunction("greet", "Alex")); //hello Alex109 //如果调用的是脚本中对象的成员方法,则需要用invokeMethod.

110 scriptText = "var obj = {getGreeting: function(name) {return 'hello ' + name;}};";111 engine.eval(scriptText);112 Object scope = engine.get("obj");113 System.out.println(invocable.invokeMethod(scope, "getGreeting", "Bob")); //hello Bob114 //在脚本中实现接口

115 scriptText = "function getGreeting(name) {return 'Hello ' + name;}";116 engine.eval(scriptText);117 Greet greet = invocable.getInterface(Greet.class); //接口必须是public类型的

118 System.out.println(greet.getGreeting("KiDe"));119 }120

121 privateScriptEngine getJavaScriptEngine() {122 ScriptEngineManager manager = newScriptEngineManager();123 //PS: 通过脚本引擎管理者来获取对应引擎,有三种方法:一是通过getEngineByName(这时只能是 javascript 或者124 //JavaScript)

125 ScriptEngine engine = manager.getEngineByName("JavaScript");126 //第二种方法是通过 getEngineByExtension (这时候只能是全小写的js)127 //engine = manager.getEngineByExtension("js");128 //第三种方法是通过 getEngineByMimeType (这时候也必须是全小写的 text/javascript)129 //engine = manager.getEngineByMimeType("text/javascript");

130

131 returnengine;132 }133 }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值