Script Support (JDK1.6+)

一: 简介
JDK1.6加入了对Script(JSR223)的支持,使Host Application有能力执行Script。这将带来如下便利:
(1) 对程序的定制更加容易灵活:您可以将很容易变化的算法如企业促销返利算法等写到script中
(2) 可以使用您喜爱的script语言完成任务(如Prototype,生成web页面等),同时可以利用强大的Java平台资源
(3) 您的JavaScript可以进行JUnit测试了
二: Script Engine发现机制
Main.java
package com.rainsoft.execise.script;   
  
import javax.script.*;   
import java.util.List;   
  
/**  
 * List all available script engine  
 * @author RainS.Y  
 * @version 1.0  
 */  
public class Main {   
    public static void main(String[] args) {   
        ScriptEngineManager mgr = new ScriptEngineManager();   
        List  factorys = mgr.getEngineFactories();   
        for (ScriptEngineFactory factory : factorys) {   
            String name     = factory.getEngineName();   
            String version  = factory.getEngineVersion();   
            String langName = factory.getLanguageName();   
            String langVer  = factory.getLanguageVersion();   
  
            System.out.printf("Engine:%s(%s), Language:%s(%s)/n",    
                              name, version, langName, langVer);   
        }   
    }   
}  
运行结果:
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文件内容:
#script engines supported   
com.sun.script.javascript.RhinoScriptEngineFactory #javascript  
三: 使用ScriptEngine使程式定制更容易
    您已经可以用properties档或xml档configure您的程式,但对于经常变化的算法而言却是不易,有了Script Support,这就容易多了。
    比如您为客户开发计算个税的程式,在国家计税方法变化时,您固然可以modify java src, compile, test, deploy完成,但如果仅仅改一下configure档就能搞定也许让人更愉快 :-)
    让我们用代码说明:
TaxCalculator.java
package com.rainsoft.execise.script;   
  
import javax.script.*;   
import java.io.FileReader;   
import java.io.FileNotFoundException;   
import org.apache.log4j.Logger;   
  
public class TaxCalculator {   
    Logger  logger = Logger.getLogger(TaxCalculator.class);   
       
    // const   
    private static final String TAX_CALCULATOR_JS = "TaxCalculator.js";   
    private static final String SCRIPT_NAME = "ECMAScript";   
    private static final String FUNC_CAL_PERSONAL_TAX = "calPersonalTax";   
       
    // private   
    private ScriptEngine engine = null;   
    private Invocable    invocableEngine = null;   
       
    /**  
     * Constructor intializing script engine  
     */  
    public TaxCalculator() throws FileNotFoundException, ScriptException {   
        ScriptEngineManager engineMgr = new ScriptEngineManager();   
        engine = engineMgr.getEngineByName(SCRIPT_NAME);   
        if (engine == null) {   
            throw new ScriptException("Can not initialize ECMAScript engine!");   
        }   
  
        Object ret = engine.eval(new FileReader(TAX_CALCULATOR_JS));   
        if (ret != null && logger.isDebugEnabled()) {   
            logger.debug("Following is returned by eval " + TAX_CALCULATOR_JS);   
            logger.debug(ret.toString());   
        }   
           
        if (!(engine instanceof Invocable)) {   
            throw new ScriptException("Engine does not support Invocable interface!");   
        }   
        invocableEngine = (Invocable)engine;   
    }   
       
    /**  
     * Calculate personal income tax  
     */  
    public double calPersonalIncomeTax(Employee emp)    
            throws NoSuchMethodException, ScriptException {   
        Object ret = invocableEngine.invokeFunction(FUNC_CAL_PERSONAL_TAX, emp);   
           
        assert(ret instanceof Double); // VM parameter "-ea" to enable "assert"   
        return (Double)ret;   
    }   
}  
(1) Constructor完成初始化JS引擎的工作
(2) calPersonalIncomeTax完成计算个税工作,方法体仅仅调用js脚本中的相关(同名)function
(3) 代码品质可以进一步提高:实现为Singleton; 将部分const放到properties档中。至于并发,让engine自己管理好了[1]
(4) 程式通过传参让js知晓emp的存在,对于更适合让js当作内建对象的Object来说,可以用如下代码做到
engine.getContext().setAttribute("BuildinObject",  anInstance, ScriptContext.ENGINE_SCOPE);      
TaxCalculator.js
/* Personal income tax algrithm demo */  
function calPersonalTax(emp) {   
    taxSalary = emp.salary - emp.the4Money - 1600;   
       
    taxRate = 0;   
    if (taxSalary > 0 && taxSalary <= 500) {   
        taxRate = 0.05;   
    }   
    else if (taxSalary > 500 && taxSalary <= 2000) {   
        taxRate = 0.1;   
    }   
    else {   
        taxRate = 0.15; // just demo
    }   
  
    return taxSalary * taxRate;   
}  
简单测试一下:
public static void main(String[] args) throws Exception {   
    Employee emp = new Employee(1, 8000, 900);   
    double tax = new TaxCalculator().calPersonalIncomeTax(emp);   
    System.out.printf("Tax:%.0f", tax);   
}  
结果:
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 增加"一:简介"第三条,谢谢网友"抛出异常的爱"的贡献

    Java SE 6.0(代号Mustang,野马)RC1已经发布,详情请见 Java SE 6.0 候选发布版现在提供下载 ,它给我们带来了哪些新的特性了。

    首先,我们看看JDK 6.0包含了大量的JSR,分为四组,分别为:

    在简化开发方面:

199: Compiler API
269: Annotation Processors
260: Javadoc™ Tag Update Ease of Development
221: JDBC™ 4.0
223: Scripting for the Java Platform

在XML方面:
105: XML Digital Signature(数字签名)
173: Streaming API for XML XML
222: JAXB 2.0

在Web 服务方面
250: Common Annotations
181: WS Metadata Web Services
224: JAX-WS 2.0

其它:

202: Java Class 文件规范升级

    详情参见JSR 270,其链接为 http://jcp.org

    除了制定相应的一系列的JSR之外,野马所有的新特性是围绕下面的目标展开的:

• 兼容性和稳定性(Compatibility and stability)
• 可诊断性,监控和管理(Diagnosability, monitoring, and management)
• 减轻开发量(Ease of development)
• 企业级桌面(Enterprise desktop)
• XML和Web 服务(XML and web services)
• 透明性(Transparency)

要实现这些目标,必然要增加不少代码。其结果是JDK的个头比原来的大了不少,安装后JDK 6.0的大小为(169,346,858 字节);而JDK 5.0 update 7的大小为(124,808,838 字节)。

    从源代码结构上来看,增加了如下的新包:

包名

描述

java.text.spi

java.text包的服务提供者类

java.util.spi

java.util包的服务提供者类

javax.activation

激活框架

javax.annotation

标注处理支持

javax.jws

Web 服务支持类

javax.jws.soap

SOAP 支持类

javax.lang.model.*

支持编程语言的建模和语言元素与类型的处理

javax.script

Java 脚本语言引擎支持框架

javax.tools

提供类工具的访问,譬如编译器

javax.xml.bind.*

与 JAXB 相关的支持

javax.xml.crypto.*

与XML 密码系统相关的支持

javax.xml.soap

支持建立和构建SOAP 消息

javax.xml.stream.*

支持XML

Streaming API

javax.xml.ws.*

支持JAX-WS

        在今年九月份的Sun Tech Day China上,Sun 的一个讲师说,有十个可能忽视的有趣的东东,现列表如下:

10. 按需即附监视;

9. JConsole 插件 API;

8. jhat OQL (jmap heap dump);

7. Solaris 动态跟踪(DTrace)支持(在Solaris OS下);

6. 由 javac 完成标注处理;

5. 类路径(Class-path)*匹配;

4. 磁盘剩余空间 API;

3. 密码提示;

2. Swing 新增布局管理器javax.swing.GroupLayout;

1. JDK 内置一个服器,JAX-WS 完成web 服务。

此为Java SE 6.0的新特性的开篇,今后将陆续就新特性进行详细说明。

 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值