论坛首页 Java企业应用论坛

Script Support (JDK1.6+)

浏览 13296 次
该帖已经被评为良好帖
作者 正文
   发表时间:2006-12-08  
: 简介<o:p></o:p>

JDK1.6加入了对Script(JSR223)的支持,使Host Application有能力执行Script。这将带来如下便利:

(1) 对程序的定制更加容易灵活:您可以将很容易变化的算法如企业促销返利算法等写到script

(2) 可以使用您喜爱的script语言完成任务(如Prototype,生成web页面等),同时可以利用强大的Java平台资源

(3) 您的JavaScript可以进行JUnit测试了

: Script Engine发现机制

Main.java
  1. package com.rainsoft.execise.script;   
  2.   
  3. import javax.script.*;   
  4. import java.util.List;   
  5.   
  6. /**  
  7.  * List all available script engine  
  8.  * @author RainS.Y  
  9.  * @version 1.0  
  10.  */  
  11. public class Main {   
  12.     public static void main(String[] args) {   
  13.         ScriptEngineManager mgr = new ScriptEngineManager();   
  14.         List <scriptenginefactory></scriptenginefactory>  factorys = mgr.getEngineFactories();   
  15.         for (ScriptEngineFactory factory : factorys) {   
  16.             String name     = factory.getEngineName();   
  17.             String version  = factory.getEngineVersion();   
  18.             String langName = factory.getLanguageName();   
  19.             String langVer  = factory.getLanguageVersion();   
  20.   
  21.             System.out.printf("Engine:%s(%s), Language:%s(%s)\n",    
  22.                               name, version, langName, langVer);   
  23.         }   
  24.     }   
  25. }  

运行结果:

  1. Engine:Mozilla Rhino(1.6 release 2), Language:ECMAScript(1.6)  

ScriptEngineManager使用service provider mechanism来实现ScriptEngine的发现.

  Sun JDK1.6自带Rhino Javascript Engine,其service描述文件在resources.jar的/META-INF/services/ javax.script.ScriptEngineFactory中,内容为:

resources.jar的/META-INF/services/ javax.script.ScriptEngineFactory文件内容:
  1. #script engines supported   
  2. com.sun.script.javascript.RhinoScriptEngineFactory #javascript  

: 使用ScriptEngine使程式定制更容易

    您已经可以用properties档或xml档configure您的程式,但对于经常变化的算法而言却是不易,有了Script Support,这就容易多了。

    比如您为客户开发计算个税的程式,在国家计税方法变化时,您固然可以modify java src, compile, test, deploy完成,但如果仅仅改一下configure档就能搞定也许让人更愉快 :-)
    让我们用代码说明:
TaxCalculator.java
  1. package com.rainsoft.execise.script;   
  2.   
  3. import javax.script.*;   
  4. import java.io.FileReader;   
  5. import java.io.FileNotFoundException;   
  6. import org.apache.log4j.Logger;   
  7.   
  8. public class TaxCalculator {   
  9.     Logger  logger = Logger.getLogger(TaxCalculator.class);   
  10.        
  11.     // const   
  12.     private static final String TAX_CALCULATOR_JS = "TaxCalculator.js";   
  13.     private static final String SCRIPT_NAME = "ECMAScript";   
  14.     private static final String FUNC_CAL_PERSONAL_TAX = "calPersonalTax";   
  15.        
  16.     // private   
  17.     private ScriptEngine engine = null;   
  18.     private Invocable    invocableEngine = null;   
  19.        
  20.     /**  
  21.      * Constructor intializing script engine  
  22.      */  
  23.     public TaxCalculator() throws FileNotFoundException, ScriptException {   
  24.         ScriptEngineManager engineMgr = new ScriptEngineManager();   
  25.         engine = engineMgr.getEngineByName(SCRIPT_NAME);   
  26.         if (engine == null) {   
  27.             throw new ScriptException("Can not initialize ECMAScript engine!");   
  28.         }   
  29.   
  30.         Object ret = engine.eval(new FileReader(TAX_CALCULATOR_JS));   
  31.         if (ret != null && logger.isDebugEnabled()) {   
  32.             logger.debug("Following is returned by eval " + TAX_CALCULATOR_JS);   
  33.             logger.debug(ret.toString());   
  34.         }   
  35.            
  36.         if (!(engine instanceof Invocable)) {   
  37.             throw new ScriptException("Engine does not support Invocable interface!");   
  38.         }   
  39.         invocableEngine = (Invocable)engine;   
  40.     }   
  41.        
  42.     /**  
  43.      * Calculate personal income tax  
  44.      */  
  45.     public double calPersonalIncomeTax(Employee emp)    
  46.             throws NoSuchMethodException, ScriptException {   
  47.         Object ret = invocableEngine.invokeFunction(FUNC_CAL_PERSONAL_TAX, emp);   
  48.            
  49.         assert(ret instanceof Double); // VM parameter "-ea" to enable "assert"   
  50.         return (Double)ret;   
  51.     }   
  52. }  

(1) Constructor完成初始化JS引擎的工作

(2) calPersonalIncomeTax完成计算个税工作,方法体仅仅调用js脚本中的相关(同名)function

(3) 代码品质可以进一步提高:实现为Singleton; 将部分const放到properties档中。至于并发,让engine自己管理好了[1]

(4) 程式通过传参让js知晓emp的存在,对于更适合让js当作内建对象的Object来说,可以用如下代码做到

  1. engine.getContext().setAttribute("BuildinObject",  anInstance, ScriptContext.ENGINE_SCOPE);      

TaxCalculator.js

  1. /* Personal income tax algrithm demo */  
  2. function calPersonalTax(emp) {   
  3.     taxSalary = emp.salary - emp.the4Money - 1600;   
  4.        
  5.     taxRate = 0;   
  6.     if (taxSalary > 0 && taxSalary <= 500) {   
  7.         taxRate = 0.05;   
  8.     }   
  9.     else if (taxSalary > 500 && taxSalary <= 2000) {   
  10.         taxRate = 0.1;   
  11.     }   
  12.     else {   
  13.         taxRate = 0.15; // just demo
  14.     }   
  15.   
  16.     return taxSalary * taxRate;   
  17. }  

简单测试一下:

  1. public static void main(String[] args) throws Exception {   
  2.     Employee emp = new Employee(18000900);   
  3.     double tax = new TaxCalculator().calPersonalIncomeTax(emp);   
  4.     System.out.printf("Tax:%.0f", tax);   
  5. }  

结果:

  1. Tax:825  

Oh,yeah!

四:附录

[1] JSR223 P135: Scripts are executed synchronously. There is no mechanism defined in this specification to execute them asynchronously or to interrupt script execution from another thread. These must be implemented at application level.

五:修订历史

2006-12-12 增加"一:简介"第三条,谢谢网友"抛出异常的爱"的贡献

  • src.rar (2 KB)
  • 描述: 本文的源程序,JDK6下通过.
  • 下载次数: 229
   发表时间:2006-12-11  
是否原创?
可否转贴?

xinyu_yang77 写道
谢谢关注
是原创,可以转贴但希望能注明出处
(http://xinyu-yang77.iteye.com/)

谢谢....正在试验...(不过下载jdk比较慢...)
0 请登录后投票
   发表时间:2006-12-11  
谢谢关注
是原创,可以转贴但希望能注明出处
(http://xinyu-yang77.iteye.com/)
0 请登录后投票
   发表时间:2006-12-11  
JAVA解析JS文件的意义是什么? 是不是有什么更深奥的意义?
0 请登录后投票
   发表时间:2006-12-12  
在我这里就可以用junit测试页面JS文件了...
0 请登录后投票
   发表时间:2006-12-12  
不错不错,可以实现很多东西的动态的配置和更改了。
0 请登录后投票
   发表时间:2006-12-12  
只支持js吗?
有没有ruby之类的规则?
0 请登录后投票
   发表时间:2006-12-12  
mustang 的js支持是fork了mozilla的rhino, 这个事儿被不少人批评. 不过有标准的脚本执行界面终究是好事, 但是我大概看了一下jdk6版rhino的封装, 感觉从原生的mozilla rhion界面封装到javax.scripting界面有点生硬, 因为两个管理执行上下文和环境的思路不太以致, 似乎封装中间有一些速度和内存的牺牲. 不过只是感觉, 哪位有实践经验的不妨评比一下, 我现在也有点东西直接通过mozilla rhino支持js, 正在考虑是不是改到javax.scripting接口.
0 请登录后投票
   发表时间:2006-12-13  
我觉得大家应该更加深入的讨论一下mustang在架构设计、应用开发上带来的改变和作用。
在JDK以前的版本中加入JS引擎也是可以调用JavaScript的
0 请登录后投票
   发表时间:2006-12-14  
若是真的就好了,,写JS文件有提示功能吗?
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics