`
abruzzi
  • 浏览: 455869 次
  • 性别: Icon_minigender_1
  • 来自: 西安
社区版块
存档分类
最新评论

Java脚本技术应用实例

阅读更多

前言

一直以来都很喜欢可以自由扩展的软件,这一点应该已经在很多文章里提到,也重复过很多次了。但是,可扩展性,灵活性是开发人员最喜欢的东西了,本性难改。平时使用的开发环境如vim/emacs, IDE中的Eclipse/Netbeans, 浏览器FF/Chrome都具有强大而灵活的可扩展支持。而关于Java的脚本支持,我已经在数篇文章中提及,大多是关于JavaScript引擎rhino和宿主Java之间的合成,但是Java的脚步支持远不止这些,这篇文章尝试讨论一下,Java对其他语言的支持。

 

文中实现一个简单的工资计算器,本来是在来到新公司不久,用以和同事们交流脚本技术的应用时做的,后来又进行了一些改动,由于只是一个示例,界面很简单:


 

工资计算器

这个计算器很简单,从脚本中获取转换表(convertTable)及基数(base),即:当工资低于base时,直接返回工资数目,如果高于base,则根据转换表来查找税率,然后扣除税款,得到实际工资。由于在实际生活中,税率会不断的调整,这部分内容就应该放入脚本:

 

 

//base salary
var base = 2000;

/**
 * range and tax-rage convert table
 */
var convertTable = {
	"0~1000" : 0.1,
	"1000~2000" : 0.15,
	"2000~3000" : 0.2,
	"3000~5000" : 0.25,
	"5000~8000" : 0.3,
	"8000~-1" : 0.4
}

 

这里用-1表示不限。

 

在本文的示例中,每一个脚本会被作为一个"插件",插件可以被创建,激活,安装到应用程序中,安装之后的插件,存在于应用程序的运行时环境(RuntimeEnv),并可以在需要的时候被调用执行。比如在本文中,初始化应用程序的时候,init方法将被调用:

 

 

public void init(){
	Plugin system = new SimplePlugin("scripts/calc.js");
	system.activate();
	SimplePluginManager.getInstance().install(system);
}

 

然后,当按钮[计算实际工资 ]被点击的时候,会调用:

 

 

btnCalc.addActionListener(new ActionListener(){

	public void actionPerformed(ActionEvent e) {
		SimplePluginManager.getInstance().getPlugin("calc").activate();
		String salary = textSalary.getText();
		Double d = Double.parseDouble(salary);
		Double r = (Double)RuntimeEnv.getInstance().invokeFunction("calc", d);
		textReal.setText(String.valueOf(r));
	}
	
});

 

仔细观察会发现,在actionPerformed方法中,首先会将get出来的插件做激活(activate)动作,这是因为,如果应用程序在运行期间,脚本做过修改,则可以事实的反映在结果上。这里去掉了一些验证,比如根据脚本文件的lastModified 来判断是否需要激活等。

 


我将script做了一个简单的包装,成为插件,这个示例中的插件结构如上图所示。RuntimeEnv 为一个单例的实例,在应用中是始终有一个,每个组件都可以向这个实例请求执行脚本中的函数,至于函数的参数传递,类型转换等工作,由底层的脚本引擎来负责执行。

 

为了脚本可以被重复使用,可以将脚本先编译为“已编译脚本”对象:

 

 

/**
 * compile the script-file into an <code>CompiledScript</code> object
 * @return
 */
public CompiledScript compile(File file){
	Date scriptDate = new Date(file.lastModified());
	if(lastModified == null || scriptDate.after(lastModified)){
		Reader reader = null;
		try {
			reader = new FileReader(file);
			compiledScript = 
				RuntimeEnv.getInstance().getCompilableEngine().compile(reader);
			lastModified = scriptDate;
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (ScriptException e) {
			e.printStackTrace();
		}finally{
			if(reader != null){
				try {
					reader.close();
				} catch (IOException e) {}	
			}
		}
	}
	
	this.status = Plugin.STATUS_LOADED;
	
	return compiledScript;
}
 

 

JavaScript版本的实现

下面为JavaScript版本的脚本,包含完整的计算逻辑,如果税率有新的调整,则仅仅需要修改脚本文件,甚至是在应用程序已处于运行状态。

 

 

//base salary
var base = 2000;

/**
 * range and tax-rage convert table
 */
var convertTable = {
	"0~1000" : 0.1,
	"1000~2000" : 0.15,
	"2000~3000" : 0.2,
	"3000~5000" : 0.25,
	"5000~8000" : 0.3,
	"8000~-1" : 0.4
}

/**
 * if the value is in the range?
 */
function inRange(value, range){
	var vs = range.split("~");
	var low, high;
	low = parseFloat(vs[0]);
	high = parseFloat(vs[1]);
	if(high == -1){//-1 means infinity
		high = Number.MAX_VALUE;
	}
	return (value >= low && value <= high);
}

/**
 * This is the function will be invoked by java program
 * @param salary
 * @return
 */
function calc(salary){
	var value;
	
	// less that or equals to base
	if(salary <= base){
		value = salary;
	}else{
		var f = salary - base;
		for(var item in convertTable){
			if(inRange(f, item)){
				value = salary - salary * convertTable[item];
				break;
			}
		}
	}
	
	return value;
}
 

 

Python版本的实现 

python版本仅仅作为JavaScript版本的翻译,但是在应用程序的角度来看,是没有任何差别的(可能在有错误的时候,会产生不同的异常)。

 

 

#
# author : juntao.qiu@gmail.com
#

# salary base
base = 2000

# convert table of range and rate
convertTable = {
	"0~1000" : 0.1,
	"1000~2000" : 0.15,
	"2000~3000" : 0.2,
	"3000~5000" : 0.25,
	"5000~8000" : 0.3,
	"8000~-1" : 0.4
}

# test value in range or not
def inRange(value, range):
	vs = range.split("~")
	low = float(vs[0])
	high = float(vs[1])
	
	if(high == -1):
		high = "inf"
	return (value >= low and value <= high)
	
# calculate salary without tax, invoked by java code
def calc(salary):
	value = None
	if(salary <= base):
		return salary
	else:
		f = salary - base
		for item in convertTable:
			if(inRange(f, item)):
				value = salary - salary * convertTable[item]
				break;
	return value

 

 

应该注意的是,jython的版本应该等于或者大于2.5.1,在2.5.1中,jython才实现了java的脚本扩展接口,我在测试的时候,jython的最新版本为2.5.1,不知道现在是否已经更新。

 

=========================================================

更新:

2011/1/23:添加了代码下载,感兴趣的朋友可以自行下载,需要注意的是,尽量使用JDK1.6版本,如果要验证jython,请使用2.5.1以上版本。JDK1.6中吧有JavaScript的实现

  • 大小: 18.5 KB
  • 大小: 181.3 KB
分享到:
评论
10 楼 guoyunsky 2011-01-24  
Java可以支持脚本语言,可以带来很大的便捷性,很有价值!
9 楼 czjxdm 2011-01-24  
楼主这个思路不错
好好研究一下
8 楼 hu437 2011-01-23  
楼主现在是2011年了,呵呵~~
7 楼 freish 2011-01-23  
动态脚本执行的效率较低,尤其是js在java高并发的时候
6 楼 abruzzi 2011-01-23  
glovebx 写道
复杂脚本能支持吗?


你是说例子中的计算器是否支持复杂脚本吗?由于内部使用的rhino引擎,并没有进行任何方面的限制,因此理论上,可以支持任意复杂的脚本。比如自己用JavaScript来实现OO语言系统,利用宿主语言Java的多线程,UI等便利来改善JS应用的性能和外观等。
5 楼 glovebx 2011-01-23  
复杂脚本能支持吗?
4 楼 abruzzi 2011-01-23  
kaneg 写道
楼主的这个想法很好。

将插件机制和动态语言结合起来到时候个很好的做法

不知有代码share否?


不好意思,之前忘记附代码了,更新后已经加到了文章的后面,如有需要请自行下载。
3 楼 kaneg 2011-01-23  
楼主的这个想法很好。

将插件机制和动态语言结合起来到时候个很好的做法

不知有代码share否?
2 楼 abruzzi 2011-01-22  
lugionline 写道
这位兄弟,所得税不是这么计算的啦...

不管你代码写的多优雅,注释写的多好,设计用了多少UML图,设计得多灵活,你的业务错掉了,对客户来说你的软件就是一分不值,哈哈。



呵呵,这个只是凭借我自己的想法做的,我个人根本不了解所得税是怎么算的,只是为了演示Java脚本的使用(JavaScript,Python等脚本),见笑,见笑。
1 楼 lugionline 2011-01-22  
这位兄弟,所得税不是这么计算的啦...

不管你代码写的多优雅,注释写的多好,设计用了多少UML图,设计得多灵活,你的业务错掉了,对客户来说你的软件就是一分不值,哈哈。

相关推荐

    测试的java脚本

    由于标签中提到了“android test”,这可能意味着这个Java脚本是专门为Android应用设计的测试工具,可能使用了如Espresso、Robolectric或Mockito等针对Android平台的测试库。这些库可以帮助开发者模拟用户交互,进行...

    Java脚本教程(学习资料)

    总之,Java脚本教程涵盖了如何在Java应用程序中集成和执行脚本语言的各个方面,包括如何发现和实例化脚本引擎,以及如何与不同的脚本环境进行交互。通过学习这些内容,开发者可以更好地利用Java的多语言支持,提高...

    第 1 部分: 引入 Java 脚本 API

    虽然描述中没有提供具体信息,但通常介绍一个引入Java脚本API的主题可能涉及如何将脚本引擎集成到Java应用中,以及如何使用这些引擎来执行动态代码。在实际开发中,这可能包括以下步骤: 1. **添加依赖**:为了使用...

    JAVA 脚本各种特效

    本教程聚焦于"JAVA 脚本各种特效",通过JavaScript代码实例来深入理解其在网页动态效果和用户交互方面的应用。 首先,我们来探讨JavaScript的基础。JavaScript是基于ECMAScript规范的,它的核心语法包括变量声明...

    Rhino脚本引擎技术介绍

    Rhino脚本引擎可以嵌入Java应用程序中执行,其最大的特点是脚本的修改不需要重启Java虚拟机(JVM)就能生效,这使得它非常适合在需要频繁更新和测试的场景中使用。Rhino的优势在于它的简单、灵活性以及强大的功能,...

    Java脚本编程:语言、框架与模式

    根据给定的信息,“Java脚本编程:语言、框架与模式”这一主题包含了三个核心部分:Java作为一门编程语言的基础知识、流行的Java开发框架以及在Java编程中常用的软件设计模式。 ### Java编程语言 #### 1. Java语言...

    择日算命神煞java脚本数据库

    主要内容包括:择日与算命的基本概念、神煞在择日中的应用、Java脚本语言的特点及其在数据库操作中的实现。 ### 择日与算命概述 1. **择日**:在中国传统文化中,择日是指选择合适的日子进行某些重要的活动或仪式...

    脚本化Java

    在后续章节(例如第23章)中,会进一步探讨JavaScript在Web浏览器环境中的应用,特别是在Java applet和Java插件中的脚本化Java技术。这涵盖了JavaScript如何在浏览器环境中与Java代码交互,增强了Web应用程序的功能...

    Java脚本语言程序员手册

    《Java脚本语言程序员手册》是一本专门为Java脚本编程者设计的指南,旨在帮助开发者深入理解和高效利用Java脚本语言。手册详细介绍了Java Scripting API(JSR 223)以及相关的脚本框架,如Rhino和Nashorn,这些都是...

    精通Java EE:精通Java EE 整合应用案例\源代码第三章

    《精通Java EE:精通Java EE 整合应用案例\源代码第三章》是关于Java企业级应用开发的深度学习资源,主要聚焦于实际项目中的整合应用。本章内容可能涵盖多个Java EE技术的综合运用,如Servlet、JSP、EJB、JPA、JSF、...

    Java Web应用开发技术实用教程

    Java Web应用开发技术实用教程是针对大学学习者设计的一本应用教程,主要涵盖了使用Java语言进行Web应用程序开发的各种核心技术。本教程旨在帮助学生和初学者深入理解如何利用Java技术栈构建功能丰富的Web应用。 ...

    精通Java EE:精通Java EE 整合应用案例随书光盘案例数据库部分

    本书“精通Java EE”显然旨在帮助开发者深入理解和掌握Java EE技术,通过整合应用案例来增强实践能力。光盘案例数据库部分是书中理论知识的实践补充,提供了丰富的实际操作示例,以便读者能够更直观地学习如何在真实...

    脚本特效(java+jsp)

    在IT行业中,脚本特效是Web开发中一个重要的组成部分,特别是在Java和JSP技术的应用上。Java是一种广泛使用的面向对象的编程语言,而JSP(Java Server Pages)是基于Java平台的一种动态网页技术,它允许开发者将静态...

    Java脚本言程序手册语员

    Java脚本API设计用于在Java应用程序中嵌入脚本引擎的能力,无需依赖具体的脚本语言。这一API的核心价值在于提供了一种灵活的方式,使得开发者能够根据实际需求选择最适合项目的脚本语言,同时也允许最终用户根据个人...

    Java 8 Nashorn 脚本引擎

    Java 8 Nashorn脚本引擎是Java平台上的一个强大工具,它允许开发者在Java应用程序中直接执行JavaScript代码。Nashorn引擎是Oracle公司为Java 8引入的一个重要特性,其目的是提升Java与JavaScript之间的互操作性,...

    用BeanShell来运行java脚本

    标题中的“用BeanShell来运行Java脚本”指的是利用BeanShell这个开源库在Java环境中执行动态的、交互式的Java代码。BeanShell是一个轻量级的Java Scripting引擎,它允许你在运行时执行Java代码,无需编译,极大地...

    JAVA PHP的应用实例

    【标题】"JAVA PHP的应用实例"揭示了这个压缩包文件主要涵盖了使用Java和PHP两种编程语言在实际web开发中的应用。Java和PHP都是广泛应用于Web开发的后端编程语言,它们各自具有不同的特点和优势。 Java,作为一种...

    java脚本引擎.pdf

    Java脚本引擎是Java平台提供的一种机制,使得...总之,Java脚本引擎和Rhino提供了一种强大而灵活的方式,使得Java应用程序能够充分利用脚本语言的优势,扩展Java的功能范围,同时也为Java应用开发提供了更多的可能性。

Global site tag (gtag.js) - Google Analytics