一、脚本语言的支持

JSR 223中规范了在Java虚拟机上运行的脚本语言与Java程序之间的交互方式。JSR 233是JavaSE6的一部分,在Java表中API中的包是javax.script。目前Java虚拟机支持比较多的脚本语言,比较流行的有JavaScript、Scala、JRuby、Jython和Groovy等。

1. 脚本引擎 
    Java中执行脚本需要脚本语言对应的脚本引擎,JSR 223定义了脚本引擎的注册和查找机制。JavaSE6中自带了JavaScript语言的脚本引擎,基于Mozilla的Rhino实现,可以通过三种方式查找脚本引擎: 
    ① 通过脚本名称获取: 
      ScriptEngine engine = new ScriptEngineManager().getEngineByName("JavaScript");

② 通过文件扩展名获取: 
     ScriptEngine engine = new ScriptEngineManager().getEngineByExtension("js");

③ 通过MIME类型来获取: 
        ScriptEngine engine = new ScriptEngineManager().getEngineByMimeType("text/javascript");

如下代码,查找注册JavaScript脚本引擎,打印"Hello!",JavaScript脚本中的println是Rhino引擎额外提供的方法。

public class BasicScripting {  public void greet() throws ScriptException {  ScriptEngineManager manager = new ScriptEngineManager();  ScriptEngine engine = manager.getEngineByName("JavaScript");  //ScriptEngine engine = manager.getEngineByExtension("js");  //ScriptEngine engine = manager.getEngineByMimeType("text/javascript");  if (engine == null) {  throw new RuntimeException("找不到JavaScript语言执行引擎。");  }  engine.eval("println('Hello!');");  }  public static void main(String[] args) {  try {  new BasicScripting().greet();  } catch (ScriptException ex) {  Logger.getLogger(BasicScripting.class.getName()).log(Level.SEVERE, null, ex);  }  }
} 

2. 语言绑定 
   脚本语言支持API使用语言绑定对象实现Java语言编写的程序与脚本语言间的数据传递。语言绑定对象实际上就是一个简单的哈希表,用来存放和获取需要共享的数据,其定义的接口为javax.script.Bindings,继承自java.util.Map接口。一个脚本引擎在执行过程中可能会使用多个语言绑定对象,不同语言绑定对象的作用域不同。ScriptEngine类提供out和get方法对脚本引擎中特定作用域的默认语言绑定对象进行操作。

使用默认的语言绑定对象:

public void useDefaultBinding() throws ScriptException {  ScriptEngine engine = getJavaScriptEngine();  engine.put("name", "Alex");  engine.eval("var message = 'Hello, ' + name;");  engine.eval("println(message);");  Object obj = engine.get("message");  System.out.println(obj);
}  

亦可以自定义语言绑定对象(如语言绑定对象中包含程序自己独有的数据等情形……):

public void useCustomBinding() throws ScriptException {  ScriptEngine engine = getJavaScriptEngine();  Bindings bindings = new SimpleBindings();  bindings.put("hobby", "playing games");  engine.eval("println('I like ' + hobby);", bindings);
}  

3. 脚本执行的上下文      脚本引擎通过执行过程中的上下文对象获取与脚本执行相关的信息,同时允许程序员通过此对象配置脚本引擎的行为。其上下文对象来自javax.script.ScriptContext接口,类似于J2EE中javax.servlet.ServletContext接口,该接口主要包含3类信息:

① 输入输出

默认情况下,脚本输入输出都是在标准控制台中,可以通过setReader和setWriter方法对输出流进行重定向,可以通过setErrorWriter方法进行错误输出重定向。

//例:将输出重定向到文件
public void scriptToFile() throws IOException, ScriptException {  ScriptEngine engine = getJavaScriptEngine();  ScriptContext context = engine.getContext();  context.setWriter(new FileWriter("output.txt"));  engine.eval("println('Hello World!');");
}  

② 自定义属性

上下文中通过setAttribute和getAttribute方法获取和设置属性,类似于ServletContext中设置和获取属性操作。与ServletContext中不同的是,ScriptContext中的属性是有作用域之分的,ScriptContext按不同的顺序在不同的作用域中进行属性查找(类似于JSP中EL表达式属性的作用域)。通过ScriptContext的getScopes可以得到其中所有可用的作用域,其中预定义了两个作用域:常量ScriptContext.ENGINE_SCOPE(当前的脚本引擎)和ScriptContext.GLOBAL_SCOPE(从同一引擎工厂中创建的所有脚本引擎对象)。

public void scriptContextAttribute() {  ScriptEngine engine = getJavaScriptEngine();  ScriptContext context = engine.getContext();  context.setAttribute("name", "Alex", ScriptContext.GLOBAL_SCOPE);  context.setAttribute("name", "Bob", ScriptContext.ENGINE_SCOPE);  context.getAttribute("name"); //值为Bob
}  

③ 语言绑定对象

语言绑定对象位于ScriptContext中,同样也有作用域之分,范围越小,优先级越高。执行如下代码,输出的name值为Bob。

public void scriptContextBindings() throws ScriptException {  ScriptEngine engine = getJavaScriptEngine();  ScriptContext context = engine.getContext();  Bindings bindings1 = engine.createBindings();  bindings1.put("name", "Alex");  context.setBindings(bindings1, ScriptContext.GLOBAL_SCOPE);  Bindings bindings2 = engine.createBindings();  bindings2.put("name", "Bob");  context.setBindings(bindings2, ScriptContext.ENGINE_SCOPE);  engine.eval("println(name);");    //Bob
}  

也可以通过ScriptContext获取语言绑定对象:

public void useScriptContextValues() throws ScriptException {  ScriptEngine engine = getJavaScriptEngine();  ScriptContext context = engine.getContext();  Bindings bindings = context.getBindings(ScriptContext.ENGINE_SCOPE);  bindings.put("name", "Alex");  engine.eval("println(name);");
}  

前面说到语言绑定对象存在于上下文环境中,故context中保存的自定义属性其实也是保存于语言绑定对象中的,如2中的语言绑定。

public void attributeInBindings() throws ScriptException {  ScriptEngine engine = getJavaScriptEngine();  ScriptContext context = engine.getContext();  context.setAttribute("name", "Alex", ScriptContext.GLOBAL_SCOPE);  engine.eval("println(name);");
}  

4. 脚本编译

脚本语言一般均是解释执行的,相对于编译执行的语言,效率较低一些。当脚本语言需要多次重复执行时,可以先对煎熬本进行编译,避免重复解析,提高效率(注:脚本编译需要脚本引擎支持,实现javax.script.Compilable接口)。JavaSE中自带的JavaScript引擎是支持对脚本进行编译的,编译的脚本用javax.script.CompiledScript来表示。

public class ScriptCompile extends JsScriptRunner {  //对脚本进行编译  public CompiledScript compile(String scriptText) throws ScriptException {  ScriptEngine engine = getJavaScriptEngine();  if (engine instanceof Compilable) {  CompiledScript script = ((Compilable) engine).compile(scriptText);  return script;  }  return null;  }  //先编译再执行  public void run(String scriptText) throws ScriptException {  CompiledScript script = compile(scriptText);  if (script == null) {  return;  }  for (int i = 0; i < 100; i++) {  script.eval();  }  }  public static void main(String[] args) {  ScriptCompile sc = new ScriptCompile();  try {  sc.run("println('Hello');");  } catch (ScriptException ex) {  Logger.getLogger(ScriptCompile.class.getName()).log(Level.SEVERE, null, ex);  }  }
}  

5. 方法调用      Java虚拟机支持脚本的意义在于实现函数式的编程,即脚本中最重要的便是方法。一些脚本引擎允许使用者单独调用脚本中的某个方法,支持此操作的脚本引擎可以通过实现javax.script.Invocable接口,支持顶层方法或者某对象中成员方法的调用。使用方法调用时最好先检查脚本引擎是否实现了Invocable接口,JavaSE中的JavaScript引擎已实现了Invocable接口。

① 在Java中调用脚本中的顶层方法

public void invokeFunction() throws ScriptException, NoSuchMethodException {  ScriptEngine engine = getJavaScriptEngine();  String scriptText = "function greet(name) { println('Hello, ' + name); } ";  engine.eval(scriptText);  Invocable invocable = (Invocable) engine;  invocable.invokeFunction("greet", "Alex");
}  

② 调用脚本中某对象的成员方法

public void invokeMethod() throws ScriptException, NoSuchMethodException {  ScriptEngine engine = getJavaScriptEngine();  String scriptText = "var obj = { getGreeting : function(name) { return 'Hello, ' + name; } }; ";  engine.eval(scriptText);  Invocable invocable = (Invocable) engine;  Object scope = engine.get("obj");  Object result = invocable.invokeMethod(scope, "getGreeting", "Alex");   //第一个参数为方法所属对象  System.out.println(result);
}  

③ 指定脚本中的方法为Java接口的实现

Greet是Java实现的接口,包含一个方法getGreeting,通过Invocable.getInterface()方法指定脚本中的方法为Java接口的实现。

public void useInterface() throws ScriptException {  ScriptEngine engine = getJavaScriptEngine();  String scriptText = "function getGreeting(name) { return 'Hello, ' + name; } ";  engine.eval(scriptText);  Invocable invocable = (Invocable) engine;  Greet greet = invocable.getInterface(Greet.class);  System.out.println(greet.getGreeting("Alex"));
}  

Java ScriptEngine 解析js相关推荐

  1. java解析js_Java ScriptEngine 解析js

    1.脚本引擎① 通过脚本名称获取:ScriptEngine engine = new ScriptEngineManager().getEngineByName("JavaScript&qu ...

  2. java解析js代码----笔记

    笔记直接贴代码了 package top.demo.js;import javax.script.Invocable; import javax.script.ScriptEngine; import ...

  3. java scriptengine e-_Java使用ScriptEngine(javax.script)

    1.可用的脚本引擎 Java 6提供对执行脚本语言的支持,这个支持来自于JSR223规范,对应的包是javax.script.默认情况下,Java 6只支持javascript脚本,它底层的实现是Mo ...

  4. 如何在java中调用js方法

    [java] view plain copy/* * 加载脚本引擎,并在java中调用js方法 */ public void test2() { ScriptEngineManager manager ...

  5. java 怎么调用js代码_在Java中直接调用js代码

    JDK1.6版添加了新的ScriptEngine类,允许用户直接执行js代码. 在Java中直接调用js代码 不能调用浏览器中定义的js函数,会抛出异常提示ReferenceError: " ...

  6. java爬虫拉勾网_[Java教程]node.js爬虫爬取拉勾网职位信息

    [Java教程]node.js爬虫爬取拉勾网职位信息 0 2017-03-14 00:00:21 简介 用node.js写了一个简单的小爬虫,用来爬取拉勾网上的招聘信息,共爬取了北京.上海.广州.深圳 ...

  7. Java如何解析markdown_Java类库解析markdown文本

    Java类库解析markdown文本 朋也社区之前使用的方法是,在java代码里调用js,然后通过调用js里的方法来解析markdown的,但性能太渣,然后在github上找了找,发现 pegdown ...

  8. 基于javaweb的物流快递管理系统(java+ssm+html+js+jsp+mysql)

    基于javaweb的物流快递管理系统(java+ssm+html+js+jsp+mysql) 运行环境 Java≥8.MySQL≥5.7.Tomcat≥8 开发工具 eclipse/idea/myec ...

  9. json java typeof_java解析json

    1:下载另外一个Java的小包就可以了: http://www.JSON.org/java/json_simple.zip 里面有源码和文档例题和编程的lib包:编程只需要json_simple.ja ...

最新文章

  1. iOS 中socket的总结
  2. 以下关于python的赋值_单选(1分) 以下关于Python的赋值说法中错误的是哪一个选项?...
  3. 软链接和硬链接的解读
  4. 印中合作国际农民丰收节贸易会-张志祥:谋定农业大健康
  5. 【数据竞赛】一文看懂CCF BDCI 2020赛题任务与解析
  6. boost::log::sinks::synchronous_sink用法的测试程序
  7. 数据结构——进制转换(10—n)
  8. IC卡设备驱动模块的代码
  9. (195)FPGA上电后IO的默认状态(ISE软件默认为1)
  10. PHP使用CodeIgniter笔记
  11. html5证书,免费获得微软MCSD证书赶快行动吧!_html5教程技巧
  12. HTTP 压力测试工具 wrk和ab
  13. 服务器硬盘品牌型号认识,服务器的硬盘和主板能和FBD内存搭配的,现在主流的是什么品牌和型号啊?...
  14. 如何配置企业微信开发者
  15. 嵌入式软件工程师是前端还是后端_软件开发工程师与嵌入式软件工程师有区别吗...
  16. 【算法】扩展卢卡斯详解
  17. zookeeper的重连思考
  18. 鸿蒙系统2.0崩溃了,集体失声?鸿蒙系统官宣后,鸿蒙系统的真实现状显现
  19. Python妙用|给小外甥生成10以内加减运算数学作业
  20. Apache HttpClient连接池泄露问题排查

热门文章

  1. CF1722A Spell Check 题解
  2. 《JavaWeb从入门到改行》过滤器学习笔记
  3. 线上招生太难?教育行业裂变方案奉上
  4. 原生JS生成PDF文件、生成pdf功能
  5. 程序猿之歌:一人我编程累
  6. 【手撕代码】同步 FIFO、LIFO/Stack
  7. 20221129今天的世界发生了什么
  8. BLC100型无线继电器
  9. CodeForces刷题C语言:Next Test、Spit Problem、Traffic Lights、Reconnaissance、Borze
  10. CodeForces - 29A Spit Problem【水题】