2004年07月14日

数据挖掘技术研究进展 作者:speedfish 日期:2004年06月14日
——————————————————————————–  
 
    1.前 言
      随着计算机技术和信息技术的发展,信息的增长速度呈现指数上升,最近几十年产生了很多超大型数据库,遍及超级市场销售、银行存款、天文学、行政办公、科学研究、信息量的急剧增长,使传统分析方法远远不能满足现实的需求。面对海量数据,如何从中发现有价值的信息或知识,成为一项非常艰巨的任务。人们急切的需要一种去粗存精、去伪存真的技术,能够从海量的数据中提取知识和信息的数据挖掘技术应运而生[1]。
    数据挖掘(Data Mining)就是从大量的、不完全的、有噪声的、模糊的、随机的数据中,提取隐含在其中的、人们事先不知道的、但又是潜在有用的信息和知识的过程[2]。这些数据可以是结构化的,如关系数据库中的数据,也可以是半结构化的,如文本,图形,图像数据,甚至是分布在网络上的异构型数据。发现知识的方法可以是数学的,也可以是非数学的,可以是演绎的,也可以是归纳的。发现了的知识可以被用于信息管理、查询优化、决策支持、过程控制等,还可以进行数据自身的维护。数据挖掘借助了多年来数理统计技术和人工智能以及知识工程等领域的研究成果构建自己的理论体系,是一个交叉学科领域,可以集成数据数据库、人工智能、数理统计、可视化、并行计算等技术。
    2. 数据挖掘技术的发展
      1989年8月,在美国底特律召开的第11届国际人工智能联合会议的专题讨论会上首次出现KDD这个术语,随后在1991,1993,1994年都举行了KDD专题讨论会,集中讨论数据统计、海量数据分析算法、知识表示、知识运用等问题。KDD国际学术大会研究重点逐渐从发现方法转向系统应用,并且注重多种发现策略和技术的集成,以及多种学科之间的相互渗透,数据挖掘和知识发现成为当前计算机科学界的一大热点。1998年在美国纽约举行的第四届知识发现与数据挖掘国际学术会议上有30多家软件公司展示了数据挖掘软件产品,不少软件已经在北美和欧洲的国家得到应用。    
    META Group曾做出这样的评论:“全球重要的企业、组织会发现,到21世纪数据挖掘技术将是他们商业成功与否的至关重要的影响因素”。IBM公司发布了基于标准的数据挖掘技术-IBM DB2智能挖掘器积分服务,可用于个性化的解决方案。两大统计软件公司SAS和SPSS也推出了各自的数据挖掘工具Enterprise Miner和Clementine[3]。此外,在Internet上还有不少KDD电子出版物,其中以半月刊Knowledge Discovery Nuggets最为权威,另一份在线周刊为DS(决策支持),1997年开始出版。自由论坛DM Email Club可以通过电子邮件讨论数据挖掘和知识发现的热点问题。数据挖掘是数据库和信息决策领域的最前沿的研究方向之一,已引起了国内外学术界的广泛关注。在我国已经开始进行数据挖掘技术的研究,但还没有看到数据挖掘技术在我国成功应用的大型案例。

    3.数据挖掘的目的
    数据挖掘并不专用于特定领域,它需要凝结各种技术和创造力去探索可能隐藏在数据中的知识。在很多情况下,应用数据挖掘技术是为了实现以下三种目的:
    ·发现知识:知识发现的目标是从数据库存储的数据中发现隐藏的关系、模式和关联。例如,在商业应用中数据挖掘可用于发现分割、分类、关联、喜好四种知识。发现分割知识可以将客户记录分组,策划为客户度身定做的推销活动。发现分类知识可以将输入的数据分配到预定义的类别中,发现和理解趋势以及对文本文档的进行分类等。发现交叉销售的机会是一种关联知识,以及发现大部分客户的喜好的知识[4]。
    ·使数据可视化:分析人员需搞清楚数据库中存储的大量信息的含意。在做任何分析之前,需先将待处理的数据人性化,并寻找显示数据的好方法。
    ·纠正数据:在结合大规模的数据库时,数据库的数据常常是不完整的,而且通常包含错误和自相矛盾的信息。数据挖掘需要以最稳定的方法识别和纠正这些问题[5]。

    4. 数据挖掘的方法

    数据挖掘方法分为统计方法、机器学习方法、神经网络方法和数据库方法。
    ·统计学的方法是数据挖掘的经典方法。统计方法中包括回归分析(多元回归、自回归等)、判别分析(贝叶斯判别、费歇尔判别、非参数判别等)、聚类分析(系统聚类、动态聚类等)、探索性分析( 主元分析法、相关分析法等)等[6]。
    ·机器学习中包括归纳学习方法(决策树、规则归纳等)、基于范例学习、遗传算法、粗糙集等。粗糙集能够对不确定、不完整信息的进行处理,而遗传算法具有全局最优搜索的能力[7]。
    ·神经网络方法具有处理非线性数据和含噪声数据的能力。神经网络的常用算法包括前向神经网络(BP算法等)、自组织神经网络(自组织特征映射、竞争学习等)等[8]。
    ·数据库方法主要是多维数据分析或OLAP方法[9]。OLAP系统的数据库为高效存储静态数据构建。其存储结构的设计是为了高效检索数据,尤其是聚合数据,比如求总和或是其他运算[10]。

    5. 数据挖掘的主要步骤

    数据挖掘是一个复杂的过程,它的一般步骤是:
    (1)分析问题: 源数据数据库必须经过评估确认其是否符合数据挖掘标准。以决定预期结果,也就选择了这项工作的最优算法。
    (2)提取、清洗和校验数据:提取的数据放在一个结构上与数据模型兼容的数据库中。以统一的格式清洗那些不一致、不兼容的数据。一旦提取和清理数据后,浏览所创建的模型,以确保所有的数据都已经存在并且完整。
    (3)创建和调试模型:将算法应用于模型后产生一个结构。浏览所产生的结构中数据,确认它对于源数据中”事实”的准确代表性,这是很重要的一点。虽然可能无法对每一个细节做到这一点,但是通过查看生成的模型,就可能发现重要的特征。
    (4)查询数据挖掘模型的数据:一旦建立模型,该数据就可用于决策支持了。在微软的数据挖掘解决方案中,该过程通常使用VB或ASP通过OLE DB for Data Mining Provider编写前端查询程序[11]。
    (5)维护数据挖掘模型:数据模型建立好后,初始数据的特征,如有效性,可能发生改变。一些信息的改变会对精度产生很大的影响,因为它的变化影响作为基础的原始模型的性质。因而,维护数据挖掘模型是非常重要的环节[5]。

    6. 数据挖掘的常用工具

    数据挖掘工具的市场一般分为三个组成部分:通用型工具、综合/DSS/OLAP数据挖掘工具和快速发展的面向特定应用的工具。
    通用型工具占有最大和最成熟的那部分市场。从定义上说,它们是非面向特定应用的适合于各种需要的情况,其中包括的主要工具有SAS Enterprise Miner、IBM Intelligent Miner、Oracle Darwin、SPSS Clementine、Unica PRW、SGI MineSet等软件。
    综合数据挖掘工具这一部分市场反映了商业对具有多功能的决策支持工具的真实和迫切的需求。商业要求该工具能提供管理报告、在线分析处理和普通结构中的数据挖掘能力。这些综合工具包括Cognos Scenario和Business Objects等。
    面向特定应用工具这一部分工具正在快速发展,在这一领域的厂商设法通过提供商业方案而不是寻求方案的一种技术来区分自己和别的领域的厂商。这些工具是纵向的、贯穿这一领域的方方面面,其常用工具有重点应用在零售业的KD1、主要应用在保险业的Option&Choices和针对欺诈行为探查开发的HNC软件[12]。

    7. 数据挖掘的应用领域

    数据挖掘技术从一开始就是面向应用的,它不仅可用于特定数据库的简单检索查询调用,而且要对这些数据进行统计、分析、综合和推理,以指导实际问题的求解,发现事件间相互关联关系和进行预测。商业上通过使用面向CRM数据挖掘技术使公司可以快速的对顾客的需求做出反应,并且可以检验商业策略的成效[13]。在科学研究方面,一个天文学上的著名应用系统SKICAT就是相当成功的数据挖掘应用,利用该系统,天文学家已发现16个新的极其遥远的星群。在生物医学和DNA数据分析上,数据挖掘可以完成异构、分布式基因数据库的语义集成,用关联规则分析同时出现的基因序列,用路径分析发现在疾病不同阶段的致病基因等[14]。NBA教练就运用Advanced Scout来挖掘信息,安排阵型,提高了获胜的机率;在金融投资方面,FALCON系统是信用卡欺诈估测系统,已被相当数量的银行采用,FAIS是一个用于识别与洗钱有关的金融交易系统,LBS Capital Management则使用了专家系统、神经网络和基因算法技术来辅助管理多达6亿美元的有价证券;在电信业,利用数据挖掘可以确定潜在的盗用者和他们的非典型使用模式,检测想侵入用户账户的企图以及发现需要引起注意的异常模式,从而保证电信业的正常运转。在电力系统中,应用于数据挖掘技术的数据有电力系统的范围特征(包括是时间和空间上的)与统计特征,通常有几千个状态变量;混合存在的离散信息(如网络拓扑结构的改变或保护动作等)和连续信息(如某些连续变化的状态变量);对某些不确定量的掌握和处理(如噪声和不完整信息等)[15]。在Internet,利用数据挖掘技术可以Web后台数据库进行分类处理,从而向用户提供更快、更准、更有效的信息。同时,也可通过对Web日志进行挖掘,发现Web用户访问模式,在高度相关的站点提供快速有效的访问通道,帮助更好地设计Web主页,改善市场营销决策[16]。

    8.结束语
    越来越多人们已经认识到数据挖掘技术能将原始数据转换为有意义的形式,从中挖掘潜在的巨大商业价值和所蕴含的科学知识,数据挖掘已成为电子商务淘金的首要的手段。具有影响的”MIT技术回顾”最近对数据挖掘技术极力赞扬,认为其已成为十大新兴技术之一[4],将彻底改变数据库的处理模式。随着数据挖掘技术不断被应用到新的领域和各种算法不断被应用到数据挖掘领域中,将更大激发数据挖掘技术的潜力,进一步推进数挖掘技术的发展和普及[17]。

 

 

五大知识管理(KM)的产品与服务

作者:孙定

    知识管理解决方案的核心内容是制定知识管理策略。知识管理策略要解决观念问题,要突破信息时代形成的思维定式,更新知识,使观念向知识时代校正。知识管理策略还要解决机构的文化问题,使机构具有知识时代所要求的组织学习能力并建立知识共享机制。接下来是选择适当的产品,开发知识管理项目。因此,知识管理市场具有咨询服务需求与技术产品需求共生的特点。前者解决知识更新、观念更新、策略制定、文化改造、调整机制等问题;后者解决具体实现的问题。正是基于知识管理的这种特点,重要的知识管理供应商都同时提供咨询服务和技术产品。

  知识管理产品与服务的另一特点是种类繁多,每个供应商都有自已的一套说法,这些说法互不相同,甚至差别巨大。这是由两个原因造成的:首先,目前无论在学术上还是在实际应用中,知识管理都处于非常早期的阶段,其定义有数百种,学术上也有很多不同的观点,供应商当然是各取所需;其次,供应商都是从自已原先的领域进入知识管理领域,拥有不同的技术和产品,而知识管理本身与其说是一种新技术不如说是一种新观念,大量现有产品与技术都与知识管理相关,供应商所做的只是根据知识管理的需求,重新定位现有的产品。

  这里着重讨论一些重要的、具有不同特点的知识管理产品与服务。

  Lotus:以专取胜

  虽说Lotus与IBM本是一家,知识管理论调也一样,但各自有各自的知识管理产品,所以还是要分开说。

  在所有知识管理解决方案厂商中,Lotus给人印象最为深刻。知识管理所必需的文档管理和群件技术在1998年前后已经是Lotus的主打产品。而Lotus Notes本身是一个可完成多种应用的平台,虽然不是浏览器界面,但在原理上已经很接近企业门户,这些都是Lotus进入知识管理市场的先天优势。这两年知识管理的兴起,对Lotus来说实在是一个天赐良机。Lotus在知识管理上狠下一番功夫,拼命赌一把也就在情理之中了。   Lotus、IBM研究中心、IBM知识管理研究所共同对Lotus专业服务以及IBM全球知识管理服务机构在全球的2万个客户的知识管理实践进行了调查,以Lotus现有技术为基本出发点,制定出独特的理论框架,并确立了知识管理产品策略。第一个产品K-Station企业门户和其配套产品Discovery Server已经完成。

  Lotus认为,仅仅将知识管理局限在从海量信息中提取有用资料是不够的,还要找到具有专业知识的人,这些人还要交流、互动、进行创造性的工作。于是,Lotus将数据、资料及处理过程定义为”事物(Thing)”、将建立在网上的虚拟工作环境定义成”场所(Place)”、将员工、客户、专家、合作伙伴等定义成”人(People)”,而在人、场所、事务之间建立有机关联才是理想的知识管理环境。

  其中,K-Station已经具有知识管理系统必备的知识管理功能,Discovery服务器则是对前者的增强。

  在K-Station中,每个人都有自已的场所–个人场所(Personal Place)。个人场所为担任不同角色的人员提供定制的日常工作环境。在个人场所中可进行电子邮件处理、管理日程、讨论、获取订阅资料、编辑文档等操作。沟通场所(Community Place)为由相关人员组成的小组提供了共享与共同工作的环境。所有个人文档都被加上了基于场所的标签,并按场所将文档进行分类归档。这种机制为文档的共享和检索提供了方便。在场所中可以看到何人正在线上,并列出共享场所的清单,在线上的人可以相互进行即时的消息沟通。目前,K-Station必须在Domino环境下运行,因此系统中至少要有一个Domino服务器。

  微软:追求通俗

  微软一方面将现有产品基本上都贴了知识管理的标签,一方面也在开发新一代知识管理产品。微软的新一代知识管理产品正在进行第三版β测试,其产品代号为”Tahoe(太湖)”。与Lotus不同,微软没在知识管理理论上标新立异,在这一点上,微软比Lotus”通俗”得多。

  按照微软的说法,Tahoe是集文档管理、文档索引/检索和协同工作于一身的企业门户。Tahoe的文档管理包括版本控制、文档的作者与密码属性管理、文档发布控制、签发控制等功能。在文件索引方面,Tahoe可以进行全文检索,也可以对网站、文件系统、Exchange服务器、Lotus服务器等多种信息源进行检索。

  除此之外,在Tahoe系统中还可以采用人工方法对文档进行分类处理,在处理过程中,Tahoe的分类助理可以学习人工分类规则,当样本达到一定数量,分类助理就可以自动进行分类。

  Tahoe由文档服务器、索引服务器和检索服务器组成。这些服务器既可以安装在一台机器上,也可以分装在三台机器上。使用时,既可以以WWW方式进入Tahoe,也可以通过MS Office中的Tahoe插件进入,还可以直接从Windows文件系统进入。

  微软的策略是只提供知识管理系统平台,而针对各行各业的知识管理解决方案由经微软认证的合作伙伴提供。

  Lotus与微软在知识管理领域各有所长:Lotus像一个老谋深算的智者,微软更像一个门槛精的小伙。Lotus先建立一个严格的体系,然后再一步步推进;微软则不太在意体系,缺什么就做什么。Lotus的难点在于它所建立的体系是否能被各界人士认同,而微软的问题是体系不严密。   IBM:挖掘文本

  在文本挖掘软件中,IBM的Text Miner很有代表性,其主要功能是特征抽取、文档聚集、文档分类和检索。

  Text Miner的特征抽取器能从文档中抽取人名、组织名和地名以及由多个字组成的复合词。此外,特征抽取器还能抽取表达数字的词汇,例如,”钱”、”百分比”、”时间”等。抽取完特征以后,有相似特征的文档就被自动聚集成一个集合。利用这一功能,知识管理系统可以从大量文档中找到相关文档。Text Miner还可以对文档进行自动分类。

  Autonomy:去除冗余

  在中国,知道Autonomy公司及其技术的人不多。但实际上,Autonomy及其CEO迈可·林奇(Mike Lynch)在知识管理界的知名度很高。迈可·林奇1991年毕业于剑桥大学,主修神经网络。他受模式识别所用的概率算法的启发,创立了Neurodynamics公司,以概率论中的贝叶斯公式和香农的信息论作为其技术的理论基础,开发出文本挖掘产品。1998年,Autonomy公司看中林奇的技术,以400万美元并购了林奇的公司,林奇也成为Autonomy公司的CEO。

  Autonomy最核心的产品是Concept Agents。在经过训练以后,它能自动地从文本中抽取概念。

  在林奇看来,按照香农的信息论,文档中除有效概念外,还有大量的冗余信息。而词或短语是否为冗余可根据它在文档中的随机度(概率)来判定。如果能滤去冗余,就可从文档中自动抽取出表达文档主题的概念。在林奇的方案中,先要对系统进行训练,处理一些文档,由使用者对非冗余概念做出认定和识别。按照贝叶斯概率理论,这一步实际上是让系统获得关于概念的先验概率。系统在随后的自动处理中根据这些概念在文档中出现的实际情况,按贝叶斯公式求出后验概率,以此作为冗余过滤的依据。这一方法与语种无关,由于每个用户都要对系统进行个别训练,因而系统的文本挖掘天然就具有高度个性化的特点。到目前为止,包括报业巨头默多克的新闻集团在内的一批知名公司已经成为Autonomy的客户,Compaq公司也已经将Autonomy的技术和产品纳入其知识管理解决方案并在客户中推广。

  TelTech:服务知识管理

  TelTech的创始人Joe Shuster是一个化学工程师,他曾创建并出售了一个成功的低温工程专业公司。这一段工作使Shuster深切感受到从公司外获取专业知识的困难。基于此,Shuster于1984年创建了TelTech公司。

  TelTech 提供三类服务:第一类服务由专家提供。TelTech拥有数千名签约专家,他们主要是有成就的学者、退休的资深专业人士和愿意提供资询服务的专业人士。TelTech并不试图将这些人的知识存入计算机,再以专家系统的方式提供服务,而是维护专家档案,当客户需要用服务时,TelTech的知识工程师就帮助客户分析问题,并向客户推荐数位专家。第二类服务是专业文献检索,用户可以自已通过TelTech的门户网站进行检索,也可以在知识工程师的帮助下进行检索。第三类服务是产品与厂商检索,这种服务也是通过其门户网站提供。

  TelTech成功的关键是建立了高性能的知识结构。它采用主题法,其主题词表分为不同专业,共有3万多个,由数位知识工程师维护,每周更新500~1200个词。

  目前,计算机世界网也在致力于开发基于公共信息的知识管理系统,所采用的策略与TelTech基本相同。现在,计算机世界网”e海航标”频道提供的实际上就是基于主题法的IT知识管理服务

 

 

 

What’s Next? A Conversation about Web Communication with XML Pioneer, Tim Bray

 

Tim Bray
Tim Bray

Consumers find themselves with a wide array of communications options: snail mail, phone, email, instant messenger, video phone, web publishing, fax, and, increasingly, Really Simple Syndication (RSS) feeds, driven by everything from newspapers to weblogs. Everywhere, individuals and businesses are trying to make the most effective use of communications technology, while IT companies decide which technologies to bet on. In this context, XML pioneer Tim Bray joined Sun Microsystems in March 2004, where, as Director of Web Technologies in the Software CTO Office, he plans to incorporate blogging software and content syndication based on the RSS format into Sun’s software line, and help set the company’s direction with respect to web services and search technology.

Bray was one of the three editors of the XML 1.0 specification and the author of the first “parser” software designed to read XML documents. Prior to coming to Sun, he served as chief technology officer for the visualization software company he founded in 1999, Antarctica Systems, Inc.

We met with him recently to explore the future of RSS and web-based communication.

question James Gosling recently put together from scratch an RSS feed reader called JNN, for “Juicy News Network.” Available under the Berkeley Software Distribution (BSD) License, the Juicy News Network feed reader is an open source project at Sun’s java.net site via JLNP (Java Network Launching Protocol). Gosling commented, “The most interesting thing is what it does to be fast at startup: all news feed reading is done by a swarm of low priority threads, one for each feed. So all feeds get fetched in parallel. This is very easy to do in Java: the threading API and networking support made it all straightforward. All the sources are there, as well as a JAR file that works on any platform, and a Mac OS X installation.” Any reaction?

answer The interesting thing about JNN is that James, to use his words, pulled it together as “a weekend hack.” This illustrates how simple and straightforward syndication technology is. In this domain, the technology is the easy part.


“RSS works well in areas where information arrives at irregular intervals, like news and publications, in which you don’t want to waste time looking for information.”

- Tim Bray,
Director of Web Technologies in the Software CTO Office

question RSS is typically used as a web publishing tool. You have said that you would like an RSS feed to your bank account, credit card, and stock portfolio. You have compared where we are in 2004 with RSS, with 1993 when the web was taking off. Where are we headed with RSS?

answer There are many ways to communicate. There’s email, the telephone, fax, instant messaging, and increasingly, video instant messaging. RSS is one more way to communicate, and the range of communications for which RSS is applicable is quite large. RSS works well in areas where information arrives at irregular intervals, such as news and publications, in which you don’t want to waste time looking for information — you want to be told when it shows up. So, right now, RSS has a huge sweet spot for bloggers and for news sites such as the New York Times and the BBC World Service.

But a lot of useful information, such as stock market portfolios and credit card transactions, arrives at unpredictable intervals. RSS users don’t need to repeatedly visit their favorite web sites to check for updates, because when the site changes, they are notified quickly with a summary of what’s new. To know when one of your investments changes substantially in price, or to be able to track debits in your bank account, is inviting.

Possibilities abound. RSS might be useful for tracking change requests during a software build or for bug tracking. So, there’s a lot of information that people would like to be automatically notified about.

It’s too early to know all of the RSS sweet spots, or when RSS will work better than email, instant messaging, or a phone call. We do know that RSS is going to be a major part of the communications spectrum, along with Java software.

question RSS is strongly identified with blogs, but as you suggest, its uses extend far beyond blogs.

answer Right, blogs, almost by definition, use RSS, but there are many applications of RSS outside the blogging space. Basically, anybody who’s blogging now is producing RSS. The fact that so many RSS feeds exist suggests that, of course, you would want to aggregate them. And there are people who are starting to do that. Technorati (http://www.technorati.com/) aggregates huge numbers of RSS feeds, and allows you to subscribe to the aggregates, or search them in real time. It’s very different from a Google search, and a potential game changer. No one can predict where all of this is going at this point. But it’s a space we’re very interested in, and we want to do the right thing in.

question For developers who have not adopted RSS, how can it impact the way they work, communicate, and organize information?

answer Any business or person providing information to others would probably benefit from RSS. Already, I have spoken with my new colleagues at Sun about providing RSS streams whenever posting new content to a portal. We’re not yet talking about a product, but it could happen.


“Given the decreasing cost and increasing reliability of memory, there’s a growing class of enterprise applications that could run everything out of memory.”

- Tim Bray,
Director of Web Technologies in the Software CTO Office

question What are the biggest misconceptions that developers and IT people have about RSS/XML syndication?

answer People addicted to RSS tell their friends to check it out. Often, their friends say, “I don’t have time to read weblogs.” Remember people in 1993 saying they did not have time to surf the Internet? This is maddening, because RSS is actually a huge time-saver. There are two misconceptions. One is that RSS is just about reading blogs, and the other is that blogs are not worth reading. Some of the most influential voices in technology and business are on weblogs.

question Where do you stand on the effort to merge the RSS standards groups with the Atom group, which provides an alternative or complement to RSS?

answer RSS and syndication in general would benefit from having a formal standard, blessed by a standards body with a carefully reviewed specification that developers could download and use. So I’m 100% in favor of getting such a standard. I don’t really care whether it’s called RSS, or Atom, or RSS/Atom or whatever. There are several similar versions floating around. It’s not rocket science. A solid, single, agreed-upon set of rules would be ideal.

question You mentioned the wide and proliferating spectrum of communication, ranging from snail mail to video phones and so on, that individuals and businesses are trying to make the most effective use of. Do you have any insights as to where this is headed culturally or technologically?

answer The ground is changing beneath us. The actual costs for me to send an email, or write a blog entry, or send an instant message, or to call you on the phone are all pretty close to zero. So, cost isn’t really a factor in choice of medium. Rather, it’s about effectiveness. We’ve gone from speech, to writing, to telephones, to electronic mail. Our methods of communication are now broad. Eventually, we will determine the best use of all these options.

Java Software and .NET

question You have said that the claims of pundits that .NET is a threat to Java technology’s future are silly. And that .NET fails to hit the 80/20 point where you do 20% of the work and see 80% of the benefits.

answer Java 1.0, when it first came out, was very lean and mean. And that was excellent, because people could learn it and become proficient in it quickly. Since then, the Java language has grown into its current, sophisticated, expansive shape. It’s going to be tougher for .NET to replicate that kind of successful growth.

Many of the design decisions about .NET were made before it came out. But with Java 1.0, the community collectively was able to build all the extra layers that make up what we have now.


“I think we’re going to beat spam.”

- Tim Bray,
Director of Web Technologies in the Software CTO Office

.NET was created by a company with a historic focus on desktop applications. My view, though somewhat controversial, is that delivering applications through web browsers versus through custom applications is much preferable. And the CIOs of the world generally agree with me about this, because maintaining desktop applications increases total cost of ownership. It’s much easier to deploy, maintain, and update server-based applications and interact through a web browser. And when the web browser appeared in the mid-90’s, its popularity was obvious. People migrated to the browser for just about everything in very short order. Browser-based applications are the sweet spot for the entire industry.

Cellphones and PDAs with Java applications obviously have a role to play. But for the mainstream enterprise, PC/desktop, browser-based apps are the way to go. And Microsoft is all about being a desktop company. They have a place on 95% of the world’s business desktops, and they have an immense depth of experience about desktop applications and how to build and deliver them. And that shows in .NET. .NET has a huge amount of user interface machinery, which is a distraction from where the real sweet spot in business is, which is on browser-based applications.

Memory — the New Disk

question You made the intriguing comment that memory is the new disk, and disks are the new tape. You argue that enterprise applications aren’t architected taking this into account, and suggest that you have ideas how they could be. Would you share some of your ideas along these lines?

answer Very high-performance global applications, such as Google, achieve much of their performance by running in memory, and not using the traditional disk database. Given the decreasing cost and increasing reliability of memory, there’s a growing class of enterprise applications that could run everything out of memory. This is going to require different thinking, both about how we build applications and about the required infrastructure. And since I think that enterprise applications written in the Java language are going to continue to be written in the Java language, we should think carefully about the kind of infrastructure necessary to support 100% memory-resident applications. I hope to work with people at Sun on this, and perhaps build some prototypes on my own.

XML Clunkiness

question You are one of the three editors of the XML 1.0 specification and the author of the first “parser” software designed to read XML documents. As you know, some developers have complained that XML is too hard. They’ve said it’s too complex, too hard for programs to parse, too verbose, and unreadable for humans to write. They say the benefits of having everyone use XML are more than outweighed by the cost of time, training, and mistakes.

answer I think that, despite XML’s success, the APIs available to programmers for reading, writing and manipulating it have been rather clunky. It’s not surprising, given XML was only finally blessed in 1998. The APIs are getting better. Yet still, the bookkeeping and code required by XML are sources of irritation. There’s lots of room for improvement.

Winning the War with Spam

question What about the war against spam?

answer I think we’re going to beat spam. (You can search for spam on my blog where I’ve written extensively about this.) If everyone paid a penny per email sent, the cost would be very small, but the cost to spammers would be great, and spam would stop. That’s my proposal.

See Also

Tim Bray’s Web Site
Sun Developer Network RSS Feeds
Sun Developer Network Content Syndication FAQs
Technorati
Blogging and Sun

Rich Client Tutorial Part 1

Rich Client Tutorial Part 2

Rich Client Tutorial Part 3

另外,还有IBM采用RCP构建其产品的新闻【转载自:www.eclipsenews.com

Staunch Eclipse supporter IBM didn’t waste any time in adopting the Rich Client Platform features in the new Eclipse 3.0. Big Blue’s Lotus Software brand is expected to release this month a new Workplace Client Technology and supporting collaborative applications on top of the Eclipse Rich Client Platform.

“Eclipse is an extensible integration platform,” said Rick Wilson, Lotus’s architect of the Workplace Client Technology. “It’s a powerful model.”

IBM’s new Workplace Client Technology comprises three server-managed client options that administrators can assign to workers, depending on their computing needs. A Web browser provides a light client for accessing applications, a rich client provides a traditional portal environment for accessing applications, and a microenvironment provides a wireless client for accessing business applications through mobile devices.

Applications that Lotus built for its Workplace platform and also based on Eclipse, including Lotus Workplace Messaging 2.0 and Lotus Workplace Document Management 2.0, can be accessed through the Lotus client model. Those applications also should be available this month.

The model is built using the new Eclipse 3.0 runtime environment features for developing rich client platforms. “Eclipse provided the underpinnings,” Wilson said, for the construction of desktop applications.

The Eclipse Foundation made changes to the 3.0 release that make it possible for developers to build applications on top of Eclipse. “We refactored the basic framework within the Eclipse platform,” said Mike Milinkovich, executive director of the Eclipse Foundation. New rich client platform capability includes Eclipse’s window-based workbench GUI, the dynamic plug-in functional extension mechanism, help subsystem, and update manager.

The Rich Client Platform is a new area for Eclipse, but community interest and user feedback provided the motivation for building the capability into the Eclipse integrated development environment.

Lotus employed Eclipse components like the Standard Widget Toolkit (SWT), JFace, and the workbench to compose user interfaces and create things like rich client platform views and editors in its Workplace Client Technology.

Lotus developers also leveraged the thin client frameworks that traditionally serve browser content in its rich client technology. “The idea is that Lotus Workplace rich client technology can drive the views that show up on the client page through the same model that drives the content for browsers and use a portlet to define the page,” Wilson said. “Portlets can be combined with portal access control and user policy to retrieve components needed by the client to realize that page.” The platform brings middleware in J2EE to the client side.

This server management component of the Workplace clients and applications also is based on the Eclipse rich client platform, and is a big key of how Lotus products add value to the Eclipse platform as a plug-in. Where the Eclipse Rich Client Platform is unmanaged, Lotus added features for a managed environment. The result is a rich client that doesn’t have to roundtrip for data.

“The [Lotus] rich client platform is a browser on steroids,” Wilson continued. “We have a truly unique approach doing this.”

Lotus also contributed to the Eclipse Foundation’s efforts by helping deliver the rich client capability within Eclipse. They helped change the runtime of Eclipse components to make the framework more rich client friendly, Wilson said.
Rita-Lyn Sanders, Eclipse News Senior News Editor

IBM的 alphaWorks 发布了Interoperability Tool for Eclipse and .NET WinForms

其功能介绍如下:

What is Interoperability Tool for Eclipse and .NET WinForms?

Interoperability Tool for Eclipse and .NET WinForms is a JavaTM tool that allows hosting of third-party WinForm controls in Eclipse, handling of .NET events, accessing of .NET properties, invoking of .NET methods, and instantiating of .NET objects. This tool can aid in moving to the Eclipse platform while making use of investments in .NET WinForms controls.

This tool allows the following:

  • hosting of WinForms controls in Eclipse
  • accessing of properties (getting and setting values) of WinForms controls and other common language runtime (CLR) objects from the Java side including properties of complex CLR types
  • addition and removal of event listeners
  • handling of WinForms controls events from the Java side, including standard events that even require handlers of EventHandler type and events that use specialized (that is, defined by the control developer) type for event arguments
  • full access to event arguments on the Java side
  • invocation of methods of WinForms controls and other CLR objects from the Java side, including methods that have many arguments and arguments of complex CLR types
  • invocation of static CLR methods from the Java side, including methods that have many arguments and arguments of complex types
  • construction of instances of CLR types from the Java side, including construction of objects that have many constructors, constructors with many arguments, and constructors with arguments of complex CLR types
  • accessing of CLR enumerations from the Java side — both as values and as enumeration objects.

How does it work?

To host a WinForm control in Eclipse, use a Java helper class and simply specify the assembly that contains the definition of the WinForm control class (either using a strong assembly name or the path to the assembly) and the full control class name. No changes in the WinForm control are required in order to allow hosting in Eclipse.

When the control is hosted in Eclipse, Java helper classes and interfaces can be used in order to access properties of the hosted control and other .NET objects, to handle .NET events, to invoke .NET methods, to instantiate .NET objects, and so on — all from the Java code running in Eclipse.

In this version, the .NET properties, methods, and events are accessed via string names, so it may be desirable to create wrappers for frequently accessed .NET objects in order to have strongly typed access.

Further information is available in the user manual (also included in the zip file).

2004年07月06日
徐志伟: 高性能计算机与网格的研究开发态势

摘要:本文基于2002年8月至2003年12月,通过参加GGF-6、SC02、HPC Asia 2002、GCC2002、GGF-8、HPDC-13、SC03、Cluster 2003、GCC 2003以及与IBM 、HP、Sun、Intel、Platform和国际学术界的交流,对国内外相关市场(包括与计算所伙伴曙光、联想、神州数码、中科力腾、中国联通、铁路、国信办等)调研和技术趋势分析,以及我们自己的研究工作,总结了计算机体系结构、高性能计算与网格的若干研究开发态势。
本文提出了下述几点看法和一些思想:(1)计算机领域正在面临着由网络计算(亦称网格)带来的一次突破性创新。(2)高性能计算机并不等同于网格,两者在今后15年都很重要,而且创新机会很多。随着电脑技术的广泛普及,社会对高性能计算机将成为全球大网格的需求会日益增长。高性能计算机将成为全球大网格的主机;而网络计算与服务将成为高性能计算机的主要工作负载。(3)中国市场和用户正在从跟踪方式向“需求驱动的跨越”方式转移,跟踪式研究不仅必然会导致学术持续落后,而且有落后于市场的危险。(4)这次突破性创新还有很多机会,今后2-4年是我们计算所在计算机系统和软件领域做出经得起历史考验的科研成果的前所未有的时机。(5)我们可以通过“人机社会”凝练科学问题和研究目标,以曙光天剑网格计算机、织女星网格、IPv6网格、AVS网格、Vega-PG网格终端等系统为载体,在2004-2006年内开发出网格资源空间、网程、网格社区、GSML软件包等核心技术,从而提供高效的关键技术和应用平台。

Ian Foster:最近网格界的变化

记者:Mark Baker 译者:lhztop@ytht.net Ian Foster是Argonne国家实验室首席科学家,其分布式系统实验室负责人。他也是芝加哥大家计算机系Arthur Holly Compton教授。他出名的原因可能是和Carl Kesselman、Steve Tuecke一起作为Globus Toolkit的发起人。这个软件是开源的,对广域的分布式计算提供了一个统一的框架,由以下几个组件构成:安全、资源管理、通讯、数据管理等。在1999年出版的《the Gird(网格)》一书中,他和Kesslman首次提到了构成网格的几个主要要素。从此之后,Globus Toolkit已经成为众多网格软件基础件实现中的先锋,网格真正达到可用性的一个关键组件。

从第一版开始,globus Toolkit做了几次大的变化,相当重要的一个变化就是基于服务的(service-based)实现。在2003年7月Globus Toolkit3.0的发布中,它就实现了OGSI标准(译者注:OGSI是一个网格服务的规范)。但是令网格界惊奇的是,在2004年1月20日的GlobusWorld会议上,Foster和他的同事提出把OGSI的概念向网络服务资源框架(WSRF, web service resource Framework)演化。 在Foster提出了WSRF的声明之后,IEEE分布式系统的在线编辑Mark Baker联系了他,探讨了近来的变化及其对网格界的影响。 Mark Baker:基于OGSI的网格服务与以前的网格建构(Grid Architecture)有很大的跳跃。把网格搭建在WSRF之上,是另一个具有重要意义的转变。现在的网格服务与网络服务有趋同的趋势,除此之外,什么人,什么事情有这么大的影响力,以至于要采用WSRF? Ian Foster:WSRF的提出,重新组织了OGSI的概念,这样做的目的是更好地与网络服务一致。网络服务标准制定者承认OGSI概念很重要,但他们并不打算采用目前OGSI所定义的这些概念,在这种情况下,有必要重新组织OGSI,因为不这样,就威胁到那些符合OGSI规范的网格基础件的统一支持。Globus联盟对重新设计OGSI不感兴趣(我们更愿意开发高级服务,而不是基础件)。我们认为如果重新组织OGSI能对网格服务和网络服务的合并产生影响,这种重组就是有意义的、正确的。我们成立了一个网络服务建构小组,专门研究这个问题,其研究成果就是WSRF。 OGSI到WSRF,其中的主要变化是在句法上的,也有一些有用的进展。把OGSI在功能上分成了六个独立的部分,用WS-Addressing是一种进步,更多地运用标准的XML Schema和WSDL2.0,我们就可以用很多现成的工具。对OGSI的分割,以及对网格基础件规范的修订与获得的好处相比,这样做是正确的么?从纯技术角度讲,这是有争议的。但是事实上,网格基础件是一个很大的成就,我们在网络服务界获得了强有力的支持:我们能从核心的网络服务产品中看到WSRF支持,这对网格界来说,真是一个好消息。而且,我们不应该过分夸大变化的范围:当然,从OGSI到WSRF,还是有一定的工作要做,但并不是每一件都是必须的,我们正在试图使这样的转化更少。

问:显然,WSRF的计划和设计已经有一段时间了。现在网格界很多人关心进度如何、有多少参与者,直到2004年1月的GlobusWorld上宣布WSRF,这个计划一直没有被透露。为什么要秘密进行?以前这些进程都是公开的,怎么现在好象和一些商业界的东西一样呢?

答:WSRF的工作在2003年夏末开始,在收到网络服务界对OGSI的反馈之后。幸运的是,我们在这样工作中成功纳入了高级网络服务建构。不幸的是,他们仅仅想把我们放到到一个闭集中。幸运的,通过大量的艰苦工作,我们很快就结束了这个过程,迅速地提出这个规范供大家评论。

我并不会说这个过程是理想的。然而,我们应该从这个过程的结果来看待它。在几个月的封闭讨论之后,我们提出了一系列的规范供大家探讨。这些规范已经被OGSI的作者们接受,许多网络服务界的人也接受了它们。我能想象更好的过程,我也能想象更坏的结果。

问:WSRF的动机,至少部分的,是因为使网格服务更容易让网络服务界接受。这样做,似乎网格服务这一概念也消失了。这样说对么?为什么二年前我们需要网格服务,而现在不需要了?

答:不。风格服务这一概念并没有消失。OGSI和WSRF的精华就是,网络服务所缺少的关键功能:能够创建、使用、探察、发现和管理有状态资源。在OGSI里,有状态资源叫做网格服务;在WSRF里,叫做WS-资源。每一个网格服务都有一个ID、服务数据(service data)和生命期管理机制。术语变了,但需要、概念和机制并没有变。OGSI和WSRF都定义了规范所要求的机制,这些都是建立在OGSA(open grid services architecture)之上。这些变化对OGSA的影响很小。

问:OGSI第一次提出时,其基本特征已经被相当秘密地制定了,Globus项目已经沿着OGSI走了很长的时间了。网格界中大部分人都原谅了你,投入了很大的精力来理解OGSI,修订了他们的项目计划。他们还会再次这样做么?

答:你刚开始说的不对。OGSI并不是在秘密中进行的。从2000年开始,我们就发现在网格界有人把网络服务作为网格的一种实现技术。因此,Globus联盟中的一个小组,与IBM合作,在2002年2月制定了一个OGSI规范的草案。一年半以后,在GGF的一个工作组细致审查之后,最终在2003年6月形成了最终版本。我认为这是一个极好的例子,Globus联盟看到了大家新的要求,而预先研发,并制定了开放的标准。

WSRF的初始动机也是一样,按照同样的进度安排。网格的成功需要广泛地采用标准化的基础件来创建、使用、探察、发现和管理有状态资源。OGSI定义了需要的机制,WSRF采用了能易于使用商业的网格服务工具的陈述(术语)。确实,路中央突起了一块,但并不是一大块,所取得的利益也是很重大的。

问:许多项目都向OGSI靠拢了一段时间了,有些已经在开发网格服务,这些工作是浪费么?另外一些坚持网络服务,希望一旦OGSI基础件到位时,转向网格服务是没有痛苦的、很快乐的一件事情。似乎后者等待WSRF是更明智的,但是对许多项目来说,他们的生命期太短了。而且还有很多坚持用GT2,现在好象可以直接用GT4,而不必理会GT3了。一些人正在考虑是否使用Globus。你怎么能说服大家,与转向所经历的痛苦相比,长期的利益会更大呢?我们是不是阻碍网格的一个大的障碍呢?是不是就象AI的冬天一样,现在也是 网格的冬天了呢?

答:电子科学和电子商务仍在持续增长,最近Oracle、IBM、Sun还有其它一些公司最近都宣布支持它们;美国的Cyberinfrastructure项目和新的EU项目也在进行中。因此,要认识到中间件扮演了一个极重的角色:保证了安全性、可靠性、互操作的资源共享与管理。因此,我并不认为(大家是)一个障碍,网格已经来了,不管我们在构建它时经历多大的痛苦,我们也要接受它。

我没想把你所说的“剧变”降到很小,不过我想,很多情况下大家把它想得太严重了。Globus Toolkit、OGSI和WSRF,他们都有各自的适用范围,并不是适合每一种情况。然而,我们也尽量使跳跃不会很大,以免大家都“我的问题与别的问题不同,我还是自己开发自己的中间件吧”。分布式计算在多个层面上都是很复杂的,从安全性、可靠性到可信度管理;互操作性总是具有挑战性的。在标准框架下工作有很多优势,能解决一些很紧迫的问题:一次登录,多次使用;远程布署;计算管理、数据移动等。采用GT的用户能得到这方面的帮助,还能在一个开发者和用户所组成的全球范围的社区内讨论。

问:提议中的WSRF标准什么时候能被通过?你有信心么?GGF能做为一个独立的标准化组织存在么?

答:GGF的OGSI工作组对WSRF标准的讨论仍然有很多争议。这个规范可能不久就要提交给Oasis(Organization for the Advancement of Structured Information Standards),这是GGF为了保证网格要求能被处理而与Oasis做的正式联系。这么做的原因很简单:WSRF并不是一个排外的网格标准,而是一系列的与网格相关的网络服务标准中的一个,而以往的网络服务标准是由Oasis和W3C制定的。提交之后,什么时间能完成这个标准的制定还是未知的,不过GGF的OGSI小组付出了巨大努力之后,这个进程会更快进行。 有人认为把WSRF提交给Oasis说明GGF并不是一个独立的标准化组织。我不这么想。GGF已经提出了许多正在应用的网格标准,比如GridFTP和GSI。其它的一些规范还在制定中,比如DAIS。很自然地,网格也建立在其它组织(如IETF、W3C和Oasis)的标准之上。一些GGF的合作伙伴也参与了这些组织。OGSI的作者是W3C的WSDL工作组的特邀专家。GGF的CMM和Oasis的WSDM WG也存在交集。我们期望看到更多的这种情况,这些进展都能使GGF不仅仅作为网格标准的制定者,而且也是网格要求能集成进其它标准化组织的工作中去的推进者。 问:除了Globus之外,OGSI规范还有其它的实现。一旦Globus跳票,转向了WSRF,OGSI还会拥有这么多追随者么? 答:如前所说,Globus致力于用WSRF开发Globus Toolkit。据我所知,其它的OGSI的实现,如pyGlobus、OGSI.NET、OGSI::Lite和Unicore也有同样的趋势,就如OGSA相关规范的主要设计者,象WSDM(管理)、DAI(数据访问和集成)和WS-Agreement所做的一样。因此,虽然没有理由不继续在OGSI框架下工作(我们将继续支持GT 3.x的基于网络服务组件一段时间,具体依赖于我们的人力和用户的需要),但应该准备明年向WSRF转化。 问:许多科学家仍然用库风格的API,并不理解网络服务或者网格服务。GT2那样的风格还会继续支持么? 答:我当然期望科学问题的解决环境是面向服务的,我们说服专家不是通过共享程序或者数据,而是创建服务来开发程序,这个概念有国际虚拟天文台的核心里最有体现。稍小一些的美国Fusion Collaboratory项目也取得了很大的成功,通过远程访问相同的代码,不需要远程用户下载并安装这么复杂的程序。更一般的,网络服务是一个建立大规模分布式系统的强有力的框架,通过一个严格的接口,可以不受约束地进行开发。 然而,许多项目和个人仍然需要特殊的功能(比如,访问远程计算机或数据),这是GT2函数库的实现,创建和管理远程计算,交换数据等等。这就是为什么客户端的API仍然在GT3和GT4中保留了这些功能,并且它们仍将会继续获得支持,只要还有类似的需要。确实,我们希望GT以及基于GT的工具中这样的API会更多,这样,更多的高层次的、面向应用的网格工具就会被开发出来。 问:OGSI规范的一个缺点就是对两个独立但兼容的实现的互操作说的很少。例如,GT3的安全模型是GSI和WS-Security的一个不标准的混合体。WS-Addressing应该有助于避免这种应付问题的方法。Globus联盟是不是采取了措施,不会重复这些有害于互操作的事情? 答:OGSI规范主要是网格服务的WSDL接口。互操作性更关心其它问题,如安全、可靠消息等。我们和其它的OGSI/WSRF实现的开发者组成了一个封闭的小组,可能不久就会测试互操作性。这个工作应该能构画出OGSI/WSRF实现的互操作性的轮廓。 最终,互操作性需要一个更大范围的网络服务标准和网格标准的标准化。Grid以网络服务为基础,这样做的价值只有当这些标准正式制定出来,并且适合网格的要求时才会体现出来。因此,我们更大范围参与到网络服务界,还有一些制定这些标准的组织,如WS-Interoperability论坛。这样我们就能提供更好的互操作性,只要是符合WSRF的服务,不管它是网格的,还是其它网络服务中间件。 问:怎样从WSRF网格上构建信息服务?有指定的机制(如监视和发现服务)么?或者说,会用现有的注册技术么? 答:OGSI/WSRF中令人振奋的一个新特征就是信息服务机制的高度集成。任何网格服务(在WSRF中叫WSRF资源)都可以声明服务数据(WSRF中的资源属性),这些服务数据都可以用标准的机制发现、取出、放入。WSRF的WS-Notification规范使我们迈了重要的一步,更广泛地使用基于消息的中间件建立可以探知的接口,就可以提供更健壮的、内容更丰富的信息服务。打个比方,一个程序员开发了一个文件传输服务,它只需要定义一些服务数据(资源属性),这个服务就对别人可见,并可以被监视。在此基础之上,就有可能定义一个更大范围的信息服务组件,来发现、监视、得到它们,对出现的错误也可以捕获到,等等。Globus联盟正在开发这些组件的雏形,包括一个存档服务和注册服务,状态提供者可以更快地更新状态信息。第一版将出现在GT3.2,更完善的将在GT4.0。 问:在可靠的WSRF实现之前,你对开发者有什么建议?我们什么时候能够看到多语言的WSRF组件,而不仅仅是JAVA? 答:先谈一下Globus Toolkit。GT3是GT的pre-WS组件的可靠实现,基于网络服务组件的早期实现。就要发布的GT3.2,对基于网络服务的组件做了重大改进,在继续支持pre-WS组件的同时,更强调了网络服务的可用性、健壮性和性能。GT4.0,可能会在2004年第三季度发布,在继续支持pre-WS组件和网络服务组件的同时,还会支持WSRF。 其它的OGSI实现也计划向WSRF转向,不过我并不知道具体的时间表。Stephen Pickles最近在OGSI WG的邮件列表上宣布他将OGSI::Lite转向WSRF。 下面是我对你所谈及的开发者的建议: 如果你用pre-WS工作得很好,就象很多产品化的网格一样,那么继续。它们仍将在GT3和GT4中得到支持。只要还有需要,我们会继续支持pre-WS组件,我们有人力支持到2005年。 如果你正在用GT3.0的基于网络服务的GT组件,为了得到更好的性能,在GT3.2可用时,转向它。进一步的,如果WSRF对你有意义,转向它。我们会继续支持GT3.x组件,我们有人力支持到2005年。 如果你刚刚开始熟悉网络服务和网格,先用GT3.2,然后到明年的某个时间转向GT4.x。 问:最后,我从英国来,知道英国2002年开始的电子科学项目,在它的基础件里用了很多Globus技术。事后来看,英国的电子科学项目是不是起动的太早了?

答:不是。英国的电子科学项目的起动时机选择得很好,使英国在开发网格是扮演了一个重要的角色。如果没有英国的电子科学资助,OGSA-DAI起动得更晚,或者根本就不能起动,英国就不会在数据服务起先导作用。Globus联盟也不会把Edinburgh大学加入进来。 对这个问题,我更想说与之相关的一个误解。电子科学就是建立21世纪科学的环境。与建筑类似,我们愿意简单地搬到一间已经盖完的房子,很多用户就把Globus看过这个完工的房子。然而,就如它的名字所说,Globus Toolkit仅仅是一系列的工具,并不是一个完整的解决方案。对熟练的开发者来说,只要适当地运用,就能解决认证、发现、远程访问等分布式计算中的许多挑战性课题,产生很好的效果。但是成功并不是仅仅在有了科学家和Globus Toolkit之后,就自然而然地完成了。它需要在科学家和网格技术的合作,可用的高层面上的面向特定应用的解决工具,就象GriPhyN/PPDG的虚拟数据工具包,Access网格和一些portal工具。

所以,从总体上讲,网格的发展需要创造性和理解性。随着各种试验的进行,我们提高了我们的理解,知道怎么更好地建立一个健壮的、可靠的全球的网格。作为一个多少合作才能工作很好的例子,我们看一下今年就要完成的地震模拟网格所组成的网络(Network for Earthquake Engineering Simulation Grid)。Neesgrid用GT3的OGSI软件建立了一个成熟的、分布式的实验控制和协作系统。其中的一些工作需要把OGSI软件转向GT4,不过Neesgrid设计者认为变化的代价与现在已经布署在各个Neesgrid节点上的集成的协作工具取得的巨大进展和对大家的培训相比,仍然很小。去年7月,Neesgrid完成了一个多站点结构的地震试验,试验设备在Colorado和Illinois,模拟系统在Illinois,数据文件和人力参与达12个站点之多。如果没有Neesgrid,这种新的科学就不会完成。

我举的第二个例子是美国的Grid3系统。从2003年11月开始,已经用GT的pre-WS组件,在美国和韩国的27个网格子节点上持续运行了500到2000个数据分析任务,涵盖物理、生物和计算机科学。通过最终用户和GriPhyN/PPDG虚拟数据工具的开发者之间的合作,程序的结果传递过来。GriPhyN/PPDG运用GT提供的机制,来调度多节点上的数据密集的工作流。此外,正在做着的更多的试验,如何建立、运行一个可操作的网格。 后记:

感谢Ian抽出宝贵的时间,回答我提出的这些问题。无疑Ian将会考虑这次会谈中所提出的问题,他也会考虑将在2004年3月在德国柏林召开的GGF10中提出的问题。 Mark Baker是英国Portsmouth大学计算机学院分布式系统的高级讲师,Westminster大学Cavendish计算机学院的计算机科学访问教授。联系方式:
mark.baker@computer.org.
Acronyms
CMM: Common Management Model

DAIS: Data Acquisition for Industrial Systems

GGF: Global Grid Forum

GSI: Grid Security Infrastructure

IETF: Internet Engineering Task Force

MDS: Monitoring and Discovery Service

Neesgrid: Network for Earthquake Engineering Simulation Grid

Oasis: Organization for the Advancement of Structured Information Standards

OGSA: Open Grid Services Architecture

OGSI: Open Grid Service Infrastructure

W3C: World Wide Web Consortium

WG: Working group

WS: Web services

WSDL: Web Services Description Language

WSDM: Web Services Distributed Management

WSRF: Web Services Resource Framework

Sun公司获最佳网格计算奖

Sun公司获得2004年最佳网格计算奖,该奖项是对Sun在领导网格计算技术上不断创新和实现的认可。网格计算是构建众多强调计算任务的首选模型,如财务风险评估,基因排序,地质建模和性能模拟。Sun网格引擎企业版是一个N1网格系统软件产品,是采用基于策略面向服务的架构来创建、访问和管理网络异构系统的网格。Sun公司N1网格系统副总裁David Nelson-Gal认为:Sun网格引擎企业版是Sun基于系统数据中心自动化策略的关键,因为网格计算出现在更广泛的企业计算领域。N1网格系统提供创建、划分、供应和管理企业网格的核心,它使用户在以前昂贵、易出现错误活动自动化的同时,获得更多的资源。

2004年07月05日
驯服 Tiger: 并发集合

英文原文

内容:


介绍 Queue 接口
使用基本队列
使用阻塞队列
使用 ConcurrentMap 实现
使用 CopyOnWriteArrayList 和 CopyOnWriteArraySet
结束语
参考资料
关于作者
对本文的评价
相关内容:
Java theory and practice: Concurrency made simple (sort of)
Java theory and practice: Concurrent collections classes
Introduction to Java threads
IBM developer kits for the Java platform (downloads)

超越 Map、Collection、List 和 Set

级别: 中级

John Zukowskijaz@zukowski.net
总裁, JZ Ventures, Inc.
2004 年 6 月

Doug Lea 最初编写的 util.concurrent 包变成了 JSR-166 ,然后又变成了 J2SE 平台的 Tiger 版本。这个新库提供的是并发程序中通常需要的一组实用程序。如果对于优化对集合的多线程访问有兴趣,那么您就找对地方了。

在 Java 编程的早期阶段,位于 Oswego 市的纽约州立大学(SUNY) 的一位教授决定创建一个简单的库,以帮助开发人员构建可以更好地处理多线程情况的应用程序。这并不是说用现有的库就不能实现,但是就像有了标准网络库一样,用经过调试的、可信任的库更容易自己处理多线程。在 Addision-Wesley 的一本相关书籍的帮助下,这个库变得越来越流行了。最终,作者 Doug Lea 决定设法让它成为 Java 平台的标准部分 —— JSR-166。这个库最后变成了 Tiger 版本的 java.util.concurrent 包。在这篇新的 驯服 Tiger 技巧中,我们将探讨 Collection Framework 中新的 Queue 接口、这个接口的非并发和并发实现、并发 Map 实现和专用于读操作大大超过写操作这种情况的并发 ListSet 实现。

介绍 Queue 接口
java.util 包为集合提供了一个新的基本接口:java.util.Queue。虽然肯定可以在相对应的两端进行添加和删除而将 java.util.List 作为队列对待,但是这个新的 Queue 接口提供了支持添加、删除和检查集合的更多方法,如下所示:

public boolean offer(Object element) public Object remove() public Object poll() public Object element() public Object peek()

基本上,一个队列就是一个先入先出(FIFO)的数据结构。一些队列有大小限制,因此如果想在一个满的队列中加入一个新项,多出的项就会被拒绝。这时新的 offer 方法就可以起作用了。它不是对调用 add() 方法抛出一个 unchecked 异常,而只是得到由 offer() 返回的 false。remove()poll() 方法都是从队列中删除第一个元素(head)。remove() 的行为与 Collection 接口的版本相似,但是新的 poll() 方法在用空集合调用时不是抛出异常,只是返回 null。因此新的方法更适合容易出现异常条件的情况。后两个方法 element()peek() 用于在队列的头部查询元素。与 remove() 方法类似,在队列为空时,element() 抛出一个异常,而 peek() 返回 null。

使用基本队列
在 Tiger 中有两组 Queue 实现:实现了新 BlockingQueue 接口的和没有实现这个接口的。我将首先分析那些没有实现的。

在最简单的情况下,原来有的 java.util.LinkedList 实现已经改造成不仅实现 java.util.List 接口,而且还实现 java.util.Queue 接口。可以将集合看成这两者中的任何一种。清单 1 显示将 LinkedList 作为 Queue 使用的一种方法:

清单 1. 使用 Queue 实现

Queue queue = new LinkedList(); queue.offer("One"); queue.offer("Two"); queue.offer("Three"); queue.offer("Four"); // Head of queue should be One System.out.println("Head of queue is: " + queue.poll());

再复杂一点的是新的 java.util.AbstractQueue 类。这个类的工作方式类似于 java.util.AbstractListjava.util.AbstractSet 类。在创建自定义集合时,不用自己实现整个接口,只是继承抽象实现并填入细节。使用 AbstractQueue 时,必须为方法 offer() poll()peek() 提供实现。像 add()addAll() 这样的方法修改为使用 offer(),而 clear()remove() 使用 poll()。最后,element() 使用 peek()。当然可以在子类中提供这些方法的优化实现,但是不是必须这么做。而且,不必创建自己的子类,可以使用几个内置的实现, 其中两个是不阻塞队列: PriorityQueueConcurrentLinkedQueue

PriorityQueueConcurrentLinkedQueue 类在 Collection Framework 中加入两个具体集合实现。PriorityQueue 类实质上维护了一个有序列表。加入到 Queue 中的元素根据它们的天然排序(通过其java.util.Comparable 实现)或者根据传递给构造函数的 java.util.Comparator 实现来定位。将清单 2 中的 LinkedList 改变为 PriorityQueue 将会打印出 Four 而不是 One,因为按字母排列 —— 字符串的天然顺序 —— Four 是第一个。ConcurrentLinkedQueue 是基于链接节点的、线程安全的队列。并发访问不需要同步。因为它在队列的尾部添加元素并从头部删除它们,所以只要不需要知道队列的大小,ConcurrentLinkedQueue 对公共集合的共享访问就可以工作得很好。收集关于队列大小的信息会很慢,需要遍历队列。

使用阻塞队列
新的 java.util.concurrent 包在 Collection Framework 中可用的具体集合类中加入了 BlockingQueue 接口和五个阻塞队列类。假如不熟悉阻塞队列概念,它实质上就是一种带有一点扭曲的 FIFO 数据结构。不是立即从队列中添加或者删除元素,线程执行操作阻塞,直到有空间或者元素可用。BlockingQueue 接口的 Javadoc 给出了阻塞队列的基本用法,如清单 2 所示。生产者中的 put() 操作会在没有空间可用时阻塞,而消费者的 take() 操作会在队列中没有任何东西时阻塞。

清单 2. 使用 BlockingQueue

class Producer implements Runnable { private final BlockingQueue queue; Producer(BlockingQueue q) { queue = q; } public void run() { try { while(true) { queue.put(produce()); } } catch (InterruptedException ex) { ... handle ...} } Object produce() { ... } } class Consumer implements Runnable { private final BlockingQueue queue; Consumer(BlockingQueue q) { queue = q; } public void run() { try { while(true) { consume(queue.take()); } } catch (InterruptedException ex) { ... handle ...} } void consume(Object x) { ... } } class Setup { void main() { BlockingQueue q = new SomeQueueImplementation(); Producer p = new Producer(q); Consumer c1 = new Consumer(q); Consumer c2 = new Consumer(q); new Thread(p).start(); new Thread(c1).start(); new Thread(c2).start(); } }

五个队列所提供的各有不同:

  • ArrayBlockingQueue:一个由数组支持的有界队列。
  • LinkedBlockingQueue:一个由链接节点支持的可选有界队列。
  • PriorityBlockingQueue:一个由优先级堆支持的无界优先级队列。
  • DelayQueue:一个由优先级堆支持的、基于时间的调度队列。
  • SynchronousQueue:一个利用 BlockingQueue 接口的简单聚集(rendezvous)机制。

前两个类 ArrayBlockingQueueLinkedBlockingQueue 几乎相同,只是在后备存储器方面有所不同,LinkedBlockingQueue 并不总是有容量界限。无大小界限的 LinkedBlockingQueue 类在添加元素时永远不会有阻塞队列的等待(至少在其中有 Integer.MAX_VALUE 元素之前不会)。

PriorityBlockingQueue 是具有无界限容量的队列,它利用所包含元素的 Comparable 排序顺序来以逻辑顺序维护元素。可以将它看作 TreeSet 的可能替代物。例如,在队列中加入字符串 One、Two、Three 和 Four 会导致 Four 被第一个取出来。对于没有天然顺序的元素,可以为构造函数提供一个 Comparator 。不过对 PriorityBlockingQueue 有一个技巧。从 iterator() 返回的 Iterator 实例不需要以优先级顺序返回元素。如果必须以优先级顺序遍历所有元素,那么让它们都通过 toArray() 方法并自己对它们排序,像 Arrays.sort(pq.toArray())

新的 DelayQueue 实现可能是其中最有意思(也是最复杂)的一个。加入到队列中的元素必须实现新的 Delayed 接口(只有一个方法 —— long getDelay(java.util.concurrent.TimeUnit unit))。因为队列的大小没有界限,使得添加可以立即返回,但是在延迟时间过去之前,不能从队列中取出元素。如果多个元素完成了延迟,那么最早失效/失效时间最长的元素将第一个取出。实际上没有听上去这样复杂。清单 3 演示了这种新的阻塞队列集合的使用:

清单 3. 使用 DelayQueue 实现

import java.util.*; import java.util.concurrent.*; public class Delay { /** * Delayed implementation that actually delays */ static class NanoDelay implements Delayed { long trigger; NanoDelay(long i) { trigger = System.nanoTime() + i; } public int compareTo(Object y) { long i = trigger; long j = ((NanoDelay)y).trigger; if (i < j) return -1; if (i > j) return 1; return 0; } public boolean equals(Object other) { return ((NanoDelay)other).trigger == trigger; } public boolean equals(NanoDelay other) { return ((NanoDelay)other).trigger == trigger; } public long getDelay(TimeUnit unit) { long n = trigger - System.nanoTime(); return unit.convert(n, TimeUnit.NANOSECONDS); } public long getTriggerTime() { return trigger; } public String toString() { return String.valueOf(trigger); } } public static void main(String args[]) throws InterruptedException { Random random = new Random(); DelayQueue queue = new DelayQueue(); for (int i=0; i < 5; i++) { queue.add(new NanoDelay(random.nextInt(1000))); } long last = 0; for (int i=0; i < 5; i++) { NanoDelay delay = (NanoDelay)(queue.take()); long tt = delay.getTriggerTime(); System.out.println("Trigger time: " + tt); if (i != 0) { System.out.println("Delta: " + (tt - last)); } last = tt; } } }

这个例子首先是一个内部类 NanoDelay,它实质上将暂停给定的任意纳秒(nanosecond)数,这里利用了 System 的新 nanoTime() 方法。然后 main() 方法只是将 NanoDelay 对象放到队列中并再次将它们取出来。如果希望队列项做一些其他事情,就需要在 Delayed 对象的实现中加入方法,并在从队列中取出后调用这个新方法。(请随意扩展 NanoDelay 以试验加入其他方法做一些有趣的事情。)显示从队列中取出元素的两次调用之间的时间差。如果时间差是负数,可以视为一个错误,因为永远不会在延迟时间结束后,在一个更早的触发时间从队列中取得项。

SynchronousQueue 类是最简单的。它没有内部容量。它就像线程之间的手递手机制。在队列中加入一个元素的生产者会等待另一个线程的消费者。当这个消费者出现时,这个元素就直接在消费者和生产者之间传递,永远不会加入到阻塞队列中。

使用 ConcurrentMap 实现
新的 java.util.concurrent.ConcurrentMap 接口和 ConcurrentHashMap 实现只能在键不存在时将元素加入到 map 中,只有在键存在并映射到特定值时才能从 map 中删除一个元素。

有一个新的 putIfAbsent() 方法用于在 map 中进行添加。这个方法以要添加到 ConcurrentMap 实现中的键的值为参数,就像普通的 put() 方法,但是只有在 map 不包含这个键时,才能将键加入到 map 中。如果 map 已经包含这个键,那么这个键的现有值就会保留。putIfAbsent() 方法是原子的。如果不调用这个原子操作,就需要从适当的同步块中调用清单 4 中的代码:

清单 4. 等价的 putIfAbsent() 代码

if (!map.containsKey(key)) { return map.put(key, value); } else { return map.get(key); }

putIfAbsent() 方法一样,重载后的 remove() 方法有两个参数 —— 键和值。在调用时,只有当键映射到指定的值时才从 map 中删除这个键。如果不匹配,那么就不删除这个键,并返回 false。如果值匹配键的当前映射内容,那么就删除这个键。清单 5 显示了这种操作的等价源代码:

清单 5. 等价的 remove() 代码

if (map.get(key).equals(value)) { map.remove(key); return true; } else { return false; }

使用 CopyOnWriteArrayList 和 CopyOnWriteArraySet
在 Doug Lea 的 Concurrent Programming in Java 一书的第 2 章第 2.4.4 节(请参阅 参考资料)中,对 copy-on-write 模式作了最好的描述。实质上,这个模式声明了,为了维护对象的一致性快照,要依靠不可变性(immutability)来消除在协调读取不同的但是相关的属性时需要的同步。对于集合,这意味着如果有大量的读(即 get()) 和迭代,不必同步操作以照顾偶尔的写(即 add())调用。对于新的 CopyOnWriteArrayListCopyOnWriteArraySet 类,所有可变的(mutable)操作都首先取得后台数组的副本,对副本进行更改,然后替换副本。这种做法保证了在遍历自身更改的集合时,永远不会抛出 ConcurrentModificationException。遍历集合会用原来的集合完成,而在以后的操作中使用更新后的集合。

这些新的集合,CopyOnWriteArrayListCopyOnWriteArraySet,最适合于读操作通常大大超过写操作的情况。一个最常提到的例子是使用监听器列表。已经说过,Swing 组件还没有改为使用新的集合。相反,它们继续使用 javax.swing.event.EventListenerList 来维护它们的监听器列表。

如清单 6 所示,集合的使用与它们的非 copy-on-write 替代物完全一样。只是创建集合并在其中加入或者删除元素。即使对象加入到了集合中,原来的 Iterator 也可以进行,继续遍历原来集合中的项。

清单 6. 展示一个 copy-on-write 集合

import java.util.*; import java.util.concurrent.*; public class CopyOnWrite { public static void main(String args[]) { List list1 = new CopyOnWriteArrayList(Arrays.asList(args)); List list2 = new ArrayList(Arrays.asList(args)); Iterator itor1 = list1.iterator(); Iterator itor2 = list2.iterator(); list1.add("New"); list2.add("New"); try { printAll(itor1); } catch (ConcurrentModificationException e) { System.err.println("Shouldn't get here"); } try { printAll(itor2); } catch (ConcurrentModificationException e) { System.err.println("Will get here."); } } private static void printAll(Iterator itor) { while (itor.hasNext()) { System.out.println(itor.next()); } } }

这个示例程序用命令行参数创建 CopyOnWriteArrayListArrayList 这两个实例。在得到每一个实例的 Iterator 后,分别在其中加入一个元素。当 ArrayList 迭代因一个 ConcurrentModificationException 问题而立即停止时,CopyOnWriteArrayList 迭代可以继续,不会抛出异常,因为原来的集合是在得到 iterator 之后改变的。如果这种行为(比如通知原来一组事件监听器中的所有元素)是您需要的,那么最好使用 copy-on-write 集合。如果不使用的话,就还用原来的,并保证在出现异常时对它进行处理。

结束语
在 J2SE 平台的 Tiger 版中有许多重要的增加。除了语言级别的改变,如一般性支持,这个库也许是最重要的增加了,因为它会被最广泛的用户使用。不要忽视加入到平台中的其他包,像 Java Management Extensions (JMX),但是大多数其他重要的库增强只针对范围很窄的开发人员。但是这个库不是。除了用于锁定和原子操作的其他并发实用程序,这些类也会经常使用。尽早学习它们并利用它们所提供的功能。

参考资料

关于作者
Author photoJohn Zukowski 为 JZ Ventures, Inc. 提供战略性 Java 咨询,并与 SavaJe Technologies 合作开发下一代移动电话平台。他的最新著作有 Mastering Java 2, J2SE 1.4 (Sybex,2002 年 4 月)和 Learn Java with JBuilder 6 (Apress,2002 年 3 月)。可以通过 jaz@zukowski.net 与他联系。
J2EE 应用程序中的数据管理和数据持久性

英文原文

内容:


Java 对象序列化
Java 数据库连接(JDBC)
从 Java 代码调用存储过程
包装
参考资料
作者简介
对本文的评价
相关内容:
J2EE 探险者:持久数据管理,第 2 部分
IBM developer kits for the Java platform (downloads)

JDBC 存储提供了多种数据管理的可能

级别: 中级

G.V.B. SubrahmanyamSubrahmanyam.vb.gampa@citigroup.com) , 顾问, Citigroup Technologies
Shankar Itchapurapushankar.i@polaris.co.in) , 顾问, Citigroup Technologies

2004 年 7 月

本文分析了在 Java 平台上可用的两个数据管理策略:Java 对象序列化和 Java 数据库连接(JDBC)。尽管本质上这两种数据管理策略并不存在孰优孰劣的问题,但在管理企业信息系统时,JDBC 轻而易举地得以胜出。在本文中,Java 开发人员 G.V.B. Subrahmanyam 和 Shankar Itchapurapu 对序列化和 JDBC都进行了介绍,并通过讨论和实例来向您展示了 JDBC 是您的最佳选择的原因。

当您正在建立企业信息系统时,需要确保以某种有效的方式存储、检索和显示企业数据。对于所有业务而言,数据都是独一无二的最大资产。所有软件系统都涉及数据,因此,数据的重要性是无论如何强调都不过分的。

应用程序的数据管理功能包括四个基本操作,通常也需要对企业数据执行这四个操作,它们是:建立、检索、更新删除(即 CRUD)。管理在企业系统的数据涉及在很长一段时间范围之内,始终如一地、成功地执行 CRUD 操作,而不必频繁地更改实际执行这些操作的代码。换句话说,管理数据意味着开发稳健的、可扩展和可维护的软件系统,以确保成功地进行 CRUD 操作,在软件的生命期中能够以一致的方式执行操作。

本文讨论了 J2EE 中的两种可用数据管理策略:Java 对象序列化和 Java 数据库连接(JDBC)。我们将查看这两种方法的优缺点。这两种数据管理策略实质上不存在孰优孰劣。在特定实现中,策略的可用性取决于项目的范围(出现在系统环境中的活动的活动范围),系统的上下文(驱动系统/子系统运行时的值的集合),以及其他的外部因素。然而,Java 序列化并不适合于企业系统,其数据需要用一种定义良好的结构(如RDBMS)来组织。我们首先将快速浏览 Java 对象序列化,然后查看 JDBC 更重要的一些方面,从而了解后者是如何实现前者所缺乏的一些关键特性的。

本文并不打算对 Java 对象序列化或者 JDBC 进行全面介绍。有关这两项技术的更多信息,请回顾参考资料小节。

Java 对象序列化
对象序列化是最简单的 Java 持久性策略。对象序列化是一个将对象图平面化为一个字节的线性序列的过程。对象图是作为对象继承、关联和聚合的结果而实现的一些关系式。对象的非暂态实例属性以字节的形式被写入到持久存储中。实例属性的值就是执行时间序列化时内存中的值。如果一个 Java 对象是可序列化的,那么它至少必须实现 java.io.Serializable 接口,该接口具有如下所示的结构:

package java.io; public interface Serializable {}

您可以看到,java.io.Serializable 接口并没有声明任何方法。它是一个记号或者标记接口。它告诉 Java 运行时环境,该实现类是可序列化的。列表 1 显示实现该接口的一个示例类。

列表 1. MySerializableObject.java

import java.io.Serializable; public class MySerializableObject extends MySuperClass implements Serializable { private String property1 = null; private String property2 = null; public String getProperty1() { return property1; } public void setProperty1(String val) { property1 = val; } public String getProperty2() { return property2; } public void setProperty2(String val) { property2 = val; } private void writeObject(ObjectOutputStream out) throws IOException { out.writeObject (getProperty1 ()); out.writeObject (getProperty2 ()); } private void readObject (ObjectInputStream in) throws IOException, ClassNotFoundException { setProperty1 ((String) in.readObject ()); setProperty2 ((String) in.readObject ()); } }

无需自己实现 writeObject(...)readObject(...) 方法来执行序列化;Java 运行时环境具有使这些方法可用的默认实现。然而,您可以重写这些方法,提供如何存储对象状态的您自己的实现。

关于序列化,您需要记住一些要点。首先,在序列化期间,整个对象图(即,所有父类和被引用类)都将被序列化。其次, Serializable 类的所有实例变量自身都应该是可序列化的,除非已经特别声明它们为暂态,或者已经重写 writeObject(...)readObject(...) 来只序列化那些可序列化的实例变量。如果违反了后一规则,在运行时将出现一个异常。

每个后续 J2SE 版本都对对象序列化系统进行少量的增加。J2SE 1.4 也相应地向 ObjectOutputStream and ObjectInputStream 增加 writeUnshared() and readUnshared()方法。通常,一个序列化的流只包含任何给定对象的一个序列化实例,并且共享对该对象引用的其他对象可以对它进行后向引用。通常期望序列化一个对象独立于其他对象可能维护的任何引用。非共享的读写方法允许对象作为新的、独一无二的对象被序列化,从而获得一个类似于对象克隆但开销更少的效果。

Java 对象序列化存在的问题
序列化涉及到将对象图从内存具体化到持久存储(例如硬盘)中。这涉及到大量 I/O 开销。通常,对应用程序而言,序列化并不是最佳选择:

  • 管理几十万兆字节的存储数据
  • 频繁地更新可序列化对象

对存储企业数据而言,序列化是一个错误选择,因为:

  • 序列化的字节流只对 Java 语言是可读的。这是一个重大缺陷,因为企业系统通常是异构的,许多应用程序要与其他应用程序共同处理相同的数据。

  • 对象检索涉及大量的 I/O 开销。
  • 没有一个用来从序列化对象图中检索获取数据的查询语言。
  • 序列化没有内置的安全机制。
  • 序列化本身并不提供任何事务控制机制,因此不能在那些需要并发访问从而不使用辅助 API 的应用程序中使用它。

Java 数据库连接(JDBC)
Java 数据库连接(JDBC)是一个标准的 API,它使用 Java 编程语言与数据库进行交互。诸如 JDBC 的调用级接口是编程接口,它们允许从外部访问 SQL 命令来处理和更新数据库中的数据。通过提供与数据库连接的库例程,它们允许将 SQL 调用集成到通用的编程环境中。特别是,JDBC 有一个使接口变得极其简单和直观的例程的丰富收集。

在下面几个小节中,我们将查看通过 JDBC 与数据库连接所涉及的一些步骤。我们将特别关注与 Java 对象序列化相比,JDBC 是如何成为一个企业数据管理策略的。

建立一个数据库连接
在利用 JDBC 做任何其他事情之前,需要从驱动程序供应商那里获取数据库驱动程序,并且将该库添加到类路径中。一旦完这项工作,就可以在 Java 程序中使用类似于下面所示的代码来实现实际的连接。

Class.forName(); Java.sql.Connection conn = DriverManager.getConnection();

Java 对象序列化并不需要这个该步骤,因为使用序列化来执行持久性操作并不需要 DBMS。 序列化是一个基于文件的机制;因此,在序列化一个对象之前,需要在目标文件系统中打开一个 I/O 流。

创建 JDBC Statement 和 PreparedStatement
可以用 JDBC Statement 对象将 SQL 语句发送到数据库管理系统(DBMS),并且不应该将该对象与 SQL 语句混淆。 JDBC Statement 对象是与打开连接有关联,而不是与任何单独的 SQL 语句有关联。可以将 JDBC Statement 对象看作是位于连接上的一个通道,将一个或多个(您请求执行的)SQL 语句传送给 DBMS。

为了创建 Statement 对象,您需要一个活动的连接。通过使用我们前面所创建的 Connection 对象 con——下面的代码来完成这项工作。

Statement stmt = con.createStatement();

到目前为止,我们已经有了一个 Statement 对象,但是还没有将对象传递到 DBMS 的 SQL 语句。

当数据库接收到语句时,数据库引擎首先会分析该语句并查找句法错误。一旦完成对语句的分析,数据库就必须计算出执行它的最有效方法。在计算上,这可能非常昂贵。数据库会检查哪些索引可以提供帮助,如果存在这样的索引的话,或者检查是否应该完全读取表中的所有行。数据库针对数据进行统计,找出最佳的执行方式。一旦创建好查询计划,数据库引擎就可以执行它。

生成这样一个计划会占用 CPU 资源。理想情况是,如果我们两次发送相同的语句到数据库,那么我们希望数据库重用第一个语句的访问计划,我们可以使用 PreparedStatement 对象来获得这种效果。

这里有一个主要的特性是,将 PreparedStatement 与其超类 Statement 区别开来:与 Statement 不同,在创建 PreparedStatement 时,会提供一个 SQL 语句。然后了立即将它发送给 DBMS,在那里编译该语句。因而, PreparedStatement 实际上是作为一 个通道与连接和被编译的 SQL 语句相关联的。

那么,它的优势是什么呢?如果需要多次使用相同的查询或者不同参数的类似查询,那么利用 PreparedStatement,语句,只需被 DBMS 编译和优化一次即可。与使用正常的 Statement 相比,每次使用相同的 SQL 语句都需要重新编译一次。

还可以通过 Connection 方法创建PreparedStatement 。下面代码显示了如何创建一个带有三个输入参数的参数化了的 SQL 语句。

PreparedStatement prepareUpdatePrice = con.prepareStatement( "UPDATE Sells SET price = ? WHERE bar = ? AND beer = ?");

注意,Java 序列化不支持类似于 SQL 的查询语言。使用 Java 序列化访问对象属性的惟一途径就是反序列化该对象,并调用该对象上的 getter/accessor 方法。反序列化一个完整的对象在计算上可能很昂贵,尤其是在程序的生命期中,应用程序需要重复执行它。

在执行 PreparedStatement 之前,需要向参数提供值。通过调用 PreparedStatement 中定义的 setXXX() 方法可以实现它。最常使用的方法是 setInt()setFloat()setDouble(),以及 setString()。每次执行已准备的声明之前,都需要设置这些值。

执行语句和查询
执行 JDBC 中的 SQL 语句的方式是根据 SQL 语句的目的而变化的。DDL(数据定义语言)语句(例如表建立和表更改语句)和更新表内容的语句都是通过使用 executeUpdate() 执行的。列表 2 中包含 executeUpdate() 语句的实例。

列表 2. 实际运行中的 executeUpdate()

Statement stmt = con.createStatement(); stmt.executeUpdate("CREATE TABLE Sells " + "(bar VARCHAR2(40), beer VARCHAR2(40), price REAL)" ); stmt.executeUpdate("INSERT INTO Sells " + "VALUES ('Bar Of Foo', 'BudLite', 2.00)" ); String sqlString = "CREATE TABLE Bars " + "(name VARCHAR2(40), address VARCHAR2(80), license INT)" ; stmt.executeUpdate(sqlString);

我们将通过先前插入的参数值(如上所示)执行 PreparedStatement ,然后在这之上调用 executeUpdate(),如下所示:

int n = prepareUpdatePrice.executeUpdate() ;

相比之下,查询期望返回一个行作为它的结果,并且并不改变数据库的状态。这里有一个称为 executeQuery() 的相对应的方法,它的返回值是 ResultSet 对象,如列表 3 所示。

列表 3. 执行一个查询

String bar, beer ; float price ; ResultSet rs = stmt.executeQuery("SELECT * FROM Sells"); while ( rs.next() ) { bar = rs.getString("bar"); beer = rs.getString("beer"); price = rs.getFloat("price"); System.out.println(bar + " sells " + beer + " for " + price + " Dollars."); }

由于查询而产生的行集包含在变量 rs 中,该变量是 ResultSet 的一个实例。集合对于我们来说并没有太大用处,除非我们可以访问每一个行以及每一个行中的属性。ResultSet 提供了一个光标,可以用它依次访问每一个行。光标最初被设置在正好位于第一行之前的位置。每个方法调用都会导致光标向下一行移动,如果该行存在,则返回 true,或者如果没有剩余的行,则返回 false

我们可以使用适当类型的 getXXX() 来检索某一个行的属性。在前面的实例中,我们使用 getString()getFloat() 方法来访问列值。注意,我们提供了其值被期望用作方法的参数的列的名称;我们可以指定用列号来代替列名。检索到的第一列的列号为 1,第二列为 2,依次类推。

在使用 PreparedStatement 时,可以通过先前插入的参数值来执行查询,然后对它调用 executeQuery(),如下所示:

ResultSet rs = prepareUpdatePrice.executeQuery() ;

关于访问 ResultSet 的注释
JDBC 还提供一系列发现您在结果集中的位置的方法:getRow()isFirst()isBeforeFirst()isLast(),以及 isAfterLast()

这里还有一些使可滚动光标能够自由访问结果集中的任意行的方法。在默认情况下,光标只向前滚动,并且是只读的。在为 Connection 创建 Statement 时,可以将 ResultSet 的类型更改为更为灵活的可滚动或可更新模型,如下所示:

Statement stmt = con.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); ResultSet rs = stmt.executeQuery("SELECT * FROM Sells");

不同的类型选项: TYPE_FORWARD_ONLYTYPE_SCROLL_INSENSITIVETYPE_SCROLL_SENSITIVE 。可以通过使用 CONCUR_READ_ONLYCONCUR_UPDATABLE 选项来选择光标是只读的还是可更新的。对于默认光标,可以使用 rs.next() 向前滚动它。对于可滚动的光标,您有更多的选项,如下所示:

rs.absolute(3); // moves to the third retrieved row rs.previous(); // moves back one row in the retrieved result set rs.relative(2); // moves forward two rows in the retrieved result set rs.relative(-3); // moves back three rows in the retrieved result set

对于可滚动光标的工作方式,这里有更多的详细描述。尽管可滚动光标对于特定应用程序是有用的,但是它导致极大的性能损失,所以应该限制和谨慎使用。可以在 参考资料小节中找到关于可滚动 ResultSet 的更多信息。

在序列化中不存在与 JDBC 的 ResultSet 相对应的机制。序列化和 JDBC 观察底层的数据的角度不同。JDBC (通常)假定底层数据是关系型结构的;而序列化假定底层数据是一个对象图。两种技术的底层数据结构存在显著差异。JDBC 的 Set 结构并不能自然地映射到序列化的对象图结构,反之亦然。当通过使用序列化语义将一个 Java 对象持久化时,数据的底层结构变成了一个字节流,该字节流展示了已经序列化了的核心对象的各种内部对象之间的关联。

JDBC 中的 ResultSet 导航是从一个 Set 元素移动到其他元素的过程,而在对象序列化中,这是不可能的,因为序列化涉及到对象关联,而不是将一组行封装到一个实体集合中。因此,Java 对象序列化无法向您提供用这种方式访问数据单独某个部分的能力。

事务
JDBC 允许将 SQL 语句组合到单独一个事务中。因此,我们可以通过使用 JDBC 事务特性来确保 ACID 属性。

Connection 对象执行事务控制。当建立连接时,在默认情况下,连接是自动提交模式下。这意味着每个 SQL 语句自身都被看作是一个事务,并且一完成执行就会被提交。

可以用以下方法开启或关闭自动提交模式:

con.setAutoCommit(false) ; con.setAutoCommit(true) ;

一旦关闭了自动提交,除非通过调用 commit() 显式地告诉它提交语句,否则无法提交 SQL 语句(即,数据库将不会被持久地更新)。在提交之前的任何时间,我们都可以调用 rollback() 回滚事务,并恢复最近的提交值(在尝试更新之前)。

我们还可以设置期望的事务隔离等级。例如,我们可以将设置事务隔离等级为 TRANSACTION_READ_COMMITTED,这使得在提交值之前,不允许对它进行访问。并且禁止脏读。在 Connection 接口中为隔离等级提供了五个这样的值。默认情况下,隔离等级是可序列化的。JDBC 允许我们发现数据库所设置的是什么事务隔离等级(使用 ConnectiongetTransactionIsolation() 方法)以及设置适当的等级(使用 ConnectionsetTransactionIsolation() 方法)。

回滚通常与 Java 语言的异常处理能力结合在一起使用。这种结合为处理数据完整性提供一个简单高效的机制。在下一节中,我们将研究如何使用 JDBC 进行错误处理。

注意,Java 对象序列化并不直接支持事务管理。如果您正在使用序列化,则将需要借助其他的 API,例如 JTA,来获得这个效果。然而,为了获得事务隔离的效果,可以选择在执行一个更新操作时同步该序列化对象,如下所示:

Synchronized(my_deserialized_object) { //Perform the updates etc... }

利用异常处理错误
软件程序中总是出现一些错误。通常,数据库程序是关键性应用程序,而且适当地捕获和处理错误是有必要的。程序应该恢复并且让数据库处于某种一致的状态下。将回滚与 Java 异常处理程序结合使用是达到这种要求的一种简便方法。

访问服务器(数据库)的客户(程序)需要能够识别从服务器返回的所有错误。JDBC 通过提供两种等级的错误条件来访问这种信息:SQLExceptionSQLWarningSQLException 是 Java 异常,它(如果未被处理)将会终止该应用程序。SQLWarningSQLException 的子类,但是它们代表的是非致命错误或意想不到的条件,因此,可以忽略它们。

在 Java 代码中,希望抛出异常或者警告的语句包含于 try 块中。如果在 try 块中的语句抛出异常或者警告,那么可以在对应的某个 catch 语句中捕获它。每个捕获语句都指出了它准备捕获的异常。

换句话说,如果数据类型是正确的,但是数据库大小超出其空间限制并且不能建立一个新表,则可能会抛出一个异常。 可以从 ConnectionStatement,以及 ResultSet 对象中获取 SQLWarning。每个对象都只是存储最近 SQLWarning。因此,如果通过 Statement 对象执行其他语句,则将放弃所有早期的警告。列表 4 举例说明了 SQLWarning 的使用。

列表 4. 实际运行中的 SQLWarnings

ResultSet rs = stmt.executeQuery("SELECT bar FROM Sells") ; SQLWarning warn = stmt.getWarnings() ; if (warn != null) System.out.println("Message: " + warn.getMessage()) ; SQLWarning warning = rs.getWarnings() ; if (warning != null) warning = warning.getNextWarning() ; if (warning != null) System.out.println("Message: " + warn.getMessage()) ;

实际上,SQLWarning 在某种程度上比 SQLException 更为罕见。最常见的是 DataTruncation 警告,它表示在从数据库读或写数据时存在问题。

Java 并没有提供序列化所使用的特定的异常类。使用序列化时发生的大多数异常都与执行的 I/O 操作有关,因此,在这些情况中 I/O 异常类将满足要求。

批处理
JDBC 2.0 提供一个用于批处理的强大API。批处理允许积累一组 SQL 语句,并且将它们一起发送并处理。一个典型的批处理就是银行应用程序,该应用程序每隔一刻钟就要更新许多账号。在减少从 Java 代码到数据库的往返次数方面,批处理是一个强大功能。

Statement 接口提供 addBatch(String) 方法,将 SQL 语句添加到一个批处理中。一旦已经将所有的 SQL 语句都增加到该批处理中,就可以使用 executeBatch() 方法一起执行它们。

然后,用executeBatch() 方法执行 SQL 语句,并返回 int 值的一个数组。该数组包含受每条语句影响的行数。将 SELECT 语句或者其他返回 ResultSet 的 SQL 语句放在一个批处理中会导致 SQLException

列表 5 中列出了利用 java.sql.Statement 进行批处理的一个简单实例。

列表 5. 实际运行中的批处理

Statement stmt = conn.createStatement(); stmt.insert("DELETE FROM Users"); stmt.insert("INSERT INTO Users VALUES('rod', 37, 'circle')"); stmt.insert("INSERT INTO Users VALUES('jane', 33, 'triangle')"); stmt.insert("INSERT INTO Users VALUES('freddy', 29, 'square')"); int[] counts = stmt.executeBatch();

在您不知道特定语句将运行的次数时,批处理是一个处理 SQL 代码的好方法。例如,如果在不使用批处理的情况下试图插入 100 条记录,那么性能可能会受到影响。如果编写一个脚本,增加 10000 条记录,那么情况会变得更糟。添加批处理可以帮助提高性能,后者甚至能够提高代码的可读性。

Java 对象序列化并不支持批处理。通常,会在某个对象的范围(联系图)上运用序列化,在这种情况下,批处理没有意义。因此,批处理在数据更新的定时和分组方面为您提供一定的灵活性,而这些对于序列化来说不一定是可用的。

从 Java 代码调用存储过程
存储过程是一组 SQL 语句,它们建立了一个逻辑单元,并执行特定任务。可以用存储过程来封装一个操作或者查询的集合,这些操作或查询都将在一个数据库服务器上执行。存储过程是在数据库服务器中被编译和存储的。因此,每次调用存储过程时,DBMS 都将重用已编译的二进制代码,因此执行速度会更快。

JDBC 允许您从 Java 应用程序中调用数据库存储过程。第一步是创建 CallableStatement 对象。与 StatementPreparedStatement 对象一样,这项操作是用一个打开的 Connection 对象完成的。CallableStatement 对象包含对存储过程的调用;但它并不包含存储过程自身。列表 6 中的第一行代码使用 con 连接建立了对存储过程 SHOW_ACCOUNT 的调用。波形括号中括住的部分是存储过程的转义语法。当驱动程序遇到 {call SHOW_ACCOUNT} 时,它将该转义语法翻译成数据库所使用的本地 SQL,从而调用名为 SHOW_ACCOUNT 的存储过程。

列表 6. 实际运行中的存储过程

CallableStatement cs = con.prepareCall("{call SHOW_ACCOUNT(?)}"); cs.setInt(1,myaccountnumber); ResultSet rs = cs.executeQuery();

假设 Sybase 中的存储过程 SHOW_ACCOUNT 包含列表 7 中所示的代码。

Listing 7. SHOW_ACCOUNT stored procedure

CREATE PROCEDURE SHOW_ACCOUNT (@Acc int) AS BEGIN Select balance from USER_ACCOUNTS where Account_no = @Acc END

ResultSet rs 看起来类似于:

balance ---------------- 12000.95

注意,用来执行 cs 的方法是 executeQuery(),由于 cs 调用的存储过程只包含一个查询,所以只产生一个结果集。如果该过程只包含一个更新或者一个 DDL 语句,则将使用 executeUpdate() 方法。然而,有时候存在存储过程包含多个 SQL 语句的情况,在这种情况下,它将产生多个结果集、多个更新计数,或者结果集和更新计数的某种结合。因此,应该使用 execute() 方法执行 CallableStatement

CallableStatement 类是 PreparedStatement 的子类,因此 CallableStatement 对象可以接受与 PreparedStatement 对象相同的参数。而且,CallableStatement 对象可以接受输出参数,并将该参数用于输入和输出。INOUT 参数和 execute() 方法通常很少使用。要想处理 OUT 参数,需要通过使用 registerOutParameter(int, int) 方法将 OUT 参数注册到存储过程。

举例说明,我们假设 GET_ACCOUNT 过程包含列表 8 中的代码。

列表 8. GET_ACCOUNT

CREATE PROCEDURE GET_ACCOUNT (@Acc int, @balance float OUTPUT) AS BEGIN Select @balance = balance from USER_ACCOUNTS where Account_no = @Acc END

在这个实例中,参数 balance 被声明是一个 OUT 参数。现在,调用该过程的 JDBC 代码如列表 9 所示。

列表 9. 调用一个存储过程的 JDBC 代码

CallableStatement csmt = con.prepareCall("{GET_ACCOUNT(?,?)"); csmt.setInt(1,youraccountnumber); csmt.registerOutParamter(2,java.sql.Types.FLOAT); csmt.execute();

正使用 Java 序列化时,并不需要访问任何外部的系统,如 DBMS。换句话说,序列化是一个纯 Java 语言现象,它不涉及执行一个外部环境中的已编译代码。因此,在序列化中不存在与 CallableStatement 对象相对应的机制。这意味着您不能将数据处理转移到外部系统或者组件中,尽管这些系统或者组件可能更适合它。

包装
在读完本文之后,我们希望您赞同:对于数据管理和持久化而言, JDBC 是比 Java 对象序列化要好得多的方法。

JDBC 是一个用来访问数据存储的极好的 API。 JDBC 最好的东西是它提供单一的 API 集合来访问多种数据源。用户只需要学习一个 API 集合,就可以访问任何数据源,这些数据源可以是关系型的、层次型的或者任何其他格式。您需要的只是一个 JDBC 驱动程序,用它连接到目标数据源。JDBC 做了大量工作,将所有技术细节都封装到了一个实现软件包中,从而将程序员从供应商特定的桎梏中解放出来。

表 1 对比了 JDBC 和 Java 对象序列化的各种特性。

表 1. JDBC 对 Java 序列化

对象序列化 JDBC
数据管理 使用文件系统存储序列化对象格式。这些系统中不包括特定的数据管理系统。序列化对象(存储在普通文件中的)通常是以自己的特殊方式通过底层 OS 来管理的。 使用一个 EAI/数据库来存储数据。EAI 或者数据库具有一个用来管理数据源中的数据指定的数据库管理系统(DBMS)。JDBC 是将请求发送到 DBMS 的 JVM 和 DBMS 之间的接口。JDBC 自身并不具有任何数据管理功能。
数据结构 底层的数据结构是一个对象图。序列化将 Java 对象的状态写入到文件系统。 底层的数据结构可以是关系型的、层次型的,或者是网络形状。但是数据的逻辑视图通常是一个表。
数据定义 数据定义涉及到使用序列化语义建立一个可序列化对象并持久化该对象。 数据定义涉及到在目标数据存储中建立必要的表,并且提供实体集之间的域级关系的明确定义。这一般是通过使用目标 DBMS 所提供的软件来完成的。
数据检索 数据检索涉及反序列化对象,并使用访问者方法读取对象的属性。 DBMS 提供一个特殊的数据子语言来检索数据。通过 JDBC API 可以将以这种数据子语言编写的语句传递给目标数据源。DBMS 负责验证、执行和返回该语句的结果。
安全 没有可以使用的定义良好的安全机制。然而,底层的 OS 可以提供已序列化文件的安全。 DBMS 提供一个广泛的安全特性集合。它可以完成认证和授权的工作。在可以访问或者操作 DBMS 上的数据之前,JDBC API 需要给目标 DBMS发送证书。
事务 没有可以使用的特定的事务控制机制。通过使用其他的 J2EE API,例如 JTA 或者 JTS,可以在程序上维护事务。 DBMS 提供复杂的事务管理。JDBC API 提供有用的方法来提交和回滚事务。
并发控制 没有可以使用的特定的并发控制机制。不过,通过使用 Java 语言中的同步技术可以获得并发控制的效果。 DBMS 提供多种等级的事务隔离。可以使用 JDBC API 方法来选择一个特定等级的隔离。

Java 对象序列化和 JDBC 是 Java 技术领域中许多数据持久化机制中的两种。在需要在多个 JVM 之间以 Java 语言特定格式共享数据(例如用 RMI 的按值传递机制共享数据)时,序列化最适合不过。然而,Java 序列化并不适用于企业数据,需要以一种定义良好的结构对这些数据进行组织。在这样的企业系统中,需要在多个系统和子系统之间共享数据,而这些系统并不一定都与 Java 语言兼容。在这种情况中,对象序列化根本不能工作。

JDBC 提供一个公用 API来访问异构的数据存储。它是 JVM 和目标 DBMS 之间的粘合剂。它提供了一个使用 Java 平台访问数据存储和维护企业数据的纲领性方法。然而,执行 CRUD 操作所需的所有代码都是由开发人员编写。

为了在企业环境中最有效地使用 JDBC,架构设计人员需要分析其企业中的数据,并开发一个用于数据持久性的框架。由于使用 JDBC 持久化数据的机制与系统想要解决的商业问题无关,因此强烈建议将数据持久性层与应用程序的商业逻辑相分离。设计模式对设计这种框架非常有帮助。

参考资料

作者简介
G.V.B. Subrahmanyam 博士拥有技术领域的硕士学位和 IIT Kharagpur 授予的博士学位,还有 BITS, Pilani 授予的软件系统硕士学位。可以通过 Subrahmanyam.vb.gampa@citigroup.com 联系他。


Shankar Itchapurapu 拥有计算机应用方面的硕士学位。可以通过 shankar.i@polaris.co.in 联系他。

使用 Eclipse 作为 Jakarta Tomcat 的开发环境

英文原文

内容:


采用 Eclipse 和 Tomcat 的原因
下载组件
安装
配置
同时测试 Tomcat 和 Eclipse
结束语
参考资料
关于作者
对本文的评价
相关内容:
什么是 Eclipse? 它可以用来做什么?
Tomcat 的故事

一种快速集成 Eclipse 和 Tomcat 的方法

级别: 初级

Geoffrey R. Duck
软件开发人员, IBM
2004 年 6 月

Eclipse 是一种很好的 Java 开发环境。Eclipse Tomcat 插件可以帮助程序员更好地组织并集成 Java 与 Web 开发项目。本文将逐步介绍 Eclipse、 Jakarta Tomcat 以及一个 Eclipse Tomcat 启动插件(这个插件可以实现Eclipse 与 Tomcat的集成)安装过程。

采用 Eclipse 和 Tomcat 的原因
从很早以前,我就一直使用 Eclipse 进行开发工作,我发现对于自己的 Java 开发工作来说,Eclipse 是最好的工具之一。 我原来是一个具有 Linux 背景的 Java 程序员,只能使用 vi 和 JDK 进行编程,当时编写和调试 Java 程序是非常冗长乏味的任务。现在有了 Eclipse 的帮助,我很容易就可以快速搭建起基于 Java 的原型。然后我就考虑为什么不将 JSP 的开发环境也集成到 Eclipse 环境中呢?这样就可以更容易地编写 Java 代码和 JSP 代码了。本文的目的是节省 JSP 开发人员设置 Eclipse 与 Tomcat 一起工作环境的时间。

下载组件
在设置 Eclipse 与 Tomcat 一起工作的环境时,需要使用几个组件。这些组件如表 1 所示。

表 1. 本文中使用的组件及其版本号

组件 版本
Eclipse IDE 2.1.2
Sun Java SDK 1.4.1 1.4.1_06
Tomcat 5.0.16
Sysdeo 的 Eclipse Tomcat 启动插件 Sysdeo tomcat 插件 2.2.1

下载所需要的组件。在本文的 参考资料 一节中列出了可以下载这些文件的站点,这些站点在本文发表时都还可以访问。

Eclipse IDE: eclipse IDE 用作 JSP 页面和 Java 文件的开发环境。Eclipse 是一个非常简单易用的 IDE 环境,它具有很多特性,可以帮助程序员快速编写并调试 Java 程序。加上 tomcat 插件之后,这个 IDE 就是管理整个 Web 项目(包括 HTML 和 JSP 页面、图标和 servlet)的一个非常优秀的工具。

Sun SDK: Tomcat Eclipse 插件要正常工作所必需的一个 SDK。这个 SDK 未必一定是 Sun SDK,但是必须是一个 SDK,(不能是一个 JRE,因为这样不能正常工作)。为了让 Tomcat 能够与 Eclipse 一起正常工作,在 SDK 中必须有一个 Java 编译器。

Tomcat: 驱动 JSP 页面需要使用 Tomcat。Tomcat 引擎是非常好的一个 servlet 引擎,可以自由下载,而且非常容易安装。

Sysdeo 的 Eclipse Tomcat 启动插件: 这是用于 Jakarta Tomcat 的众多 Eclipse 插件之一。这是非常优秀的一个插件,它为我节省了很多时间,可以很好地集成 Web 项目与 Java 代码,我通常都是使用 Eclipse 来编写这些代码。

安装

将所有的组件解压
下载了所需要的组件之后,下一个步骤就是将每个文件解压。将这些文件解压缩并将其全部放到同一个目录中,这样就可以找到所有解压之后的文件。

将 Tomcat 插件拷贝到 Eclipse/plugins 目录中
在所有的文件全部被解开压缩之后,将 Tomcat 插件目录拷贝到 Eclipse 目录中的 plugins 子目录中。我从 Sysdeo 的 zip 文件中解压开的目录名是 com.sysdeo.eclipse.tomcat_2.2.1,将这整个目录都拷贝到 Eclipse/plugins 目录中。

安装 SDK
接下来安装刚才下载的 SDK。tomcat 的 Eclipse 插件要求在 Eclipse 工作空间中设置的 JRE 是一个具有 Java 编译器的真正 SDK。这是使用 Sysdeo Tomcat 插件的一个要求。在安装好 SDK 之后,就可以启动 Eclipse 工作台了。

Eclipse 缺省的 JRE 必须是来自于一个 SDK
Tomcat 插件要求 Eclipse 设置的缺省 JRE 是一个 SDK, 否则 Tomcat 插件就不能正常工作。

配置

将这个 SDK 的 JRE 设置为 Eclipse 缺省的 JRE
在启动 Eclipse之前,需要在工作台的 preferences 页中配置一些选项。选择 Window > Preferences,打开 preferences 对话框,如图 1 所示。

图 1. Eclipse 的 preferences 对话框
Eclipse 的 preferences 对话框

在左侧的树视图中选择 Java 选项。展开 Java 元素,并选择 Installed JRE,如图 2 所示。

图 2. JRE 的 preference 设置
JRE preference settings

单击 “Add” 并切换到在上面配置的安装阶段所安装的 JRE 目录,如图 3 所示。单击 “OK”。

图 3. 向 Eclipse 的 preference 设置添加一个 JRE
向 eclipse 的 preference 设置添加一个 JRE

选中刚才安装 SDK 时所添加的 JRE 边上的检查框,如图 4 所示。这样将 JRE 设置为 Eclipse 使用的缺省 JRE。只有正确设置了这个步骤,Tomcat 插件才能工作。Tomcat 插件要求在这些设置中选择的缺省 JRE 是一个 SDK。

图 4. 为 Eclipse 和 Tomcat 设置缺省的 JRE
为 Eclipse 和 Tomcat 设置缺省的 JRE

在 Tomcat 的 preferences 中设置 Tomcat 的 Home 变量
接下来设置 Tomcat 插件的 preferences。现在 Preferences 对话框仍然打开着,在左边的菜单中选择 “Tomcat”, 如图 5 所示。

图 5. 设置 Tomcat 插件的 preferences
Tomcat 插件的 preferences 设置

在上面的单选按钮中选择 Tomcat 的版本。我使用的 Tomcat 的版本号为 5.0.16, 因此选择最后一个单选按钮 “Version 5.x”。

然后必须设置 Tomcat Home 变量。点击 “Tomcat Home” 对话框边上的 “Browse” 按钮,浏览刚才解压开的版本的 Tomcat 的根目录,然后点击 “OK” 按钮。配置文件会自动被选中,并在对话框中添上相应的内容。如果要想为 Tomcat 选择一个与此不同的配置文件, 现在就可以浏览这些文件。否则就正常使用缺省值。

现在我们已经实现了使用 Eclipse 和 Sysdeo Tomcat Launcher 插件来启动和运行 Tomcat 的最低要求。浏览以下 Eclipse 的 preference 对话框中对 Tomcat 的其他参数设置,注意在 Tomcat 的参数设置中还有很多其他选项可以使用。例如,可以为 Tomcat 服务器使用的 JVM 添加一个参数,从工作空间中选择 Java 项目添加到 Tomcat 的 classpath 中,以及进行一些设置从而允许 Tomcat 管理应用程序

同时测试 Tomcat 和 Eclipse

创建一个新 Tomcat 项目
要对 Tomcat 和 Eclipse 进行集成测试,可以从创建一个新项目入手。选择 File > New > Project,并检查新项目的向导内容。在这个项目向导的 Java 部分中有一个新项 “Tomcat Project”(见图 6)。选择这个选项,然后点击 Next。

图 6. 创建一个新 Tomcat 项目
创建一个新 tomcat 项目

为这个新的 Tomcat 项目取一个名字。例如 “TomcatProject”, 如图 7 所示。点击 Next。

图 7. 设置 Tomcat 项目的名字
设置 Tomcat 项目的名字

现在我们已经看到可以为 Web 项目的 Context 指定名字,还可以指定一个子目录作为 Web 应用程序的根目录。现在我们保留缺省值不变(见图 8)。 点击 Finish。

图 8. 设置 Tomcat Web 应用程序的根目录
设置 Web 应用程序的根目录

现在在工作空间中创建了一个具有 WAR 结构的项目,如图9 所示。

图 9. 创建的 Tomcat 项目
创建的 Tomcat 项目

创建一个 JSP 文件进行测试
测试安装过程的最简单方法是在 WAR 项目的根文件夹中创建一个新文件。先创建一个新文件,此处称之为 “index.jsp”。要实现这种功能,请在工作空间中选择自己的项目,然后在其上点击鼠标右键。选择 New > File,将其命名为 “index.jsp”,如图 10 所示,然后点击 Finish。

图 10. 创建 index.jsp 文件测试配置
创建 index.jsp 文件测试配置

将清单 1 中的内容添加到 index.jsp 文件中,并保存这个文件。

清单 1. index.jsp 文件样例

 <html> <body> <%java.util.Date d = new java.util.Date();%> Todays date is <%= d.getDate()%> and this jsp page worked! </body> </html> 

使用 Sysdeo 插件启动 Tomcat
现在伟大的时刻到来了。要启动 Tomcat 服务器,只需简单的点击工具条中的 Start Tomcat 按钮即可,如图 11 所示。也可以先在主菜单中选择 Tomcat 菜单,然后再选择“Start Tomcat”。

图 11.使用 Sysdeo 插件启动 Tomcat 服务器
使用 Sysdeo 插件启动 Tomcat服务器

Tomcat 服务器现在就会启动,在 Eclipse 工作台的 Console 视图中会显示启动时的文字,如图 12 所示。检查启动日志,并注意是否有错误发生。

图 12. 在 Eclipse 的 Console 视图中显示的 Tomcat 的启动信息
在 Eclipse 的 Console 视图中查看 Tomcat 的启动信息

启动浏览器并查看 index.jsp 文件
当服务器已经启动之后,再启动一个 Web 浏览器。转到 URL http://localhost:8080/TomcatProject。此时会装入一个页面,您应该会看到类似于下面的一条消息:

Todays date is 30 and this jsp page worked! (我的屏幕上显示的日期是 30,因为今天就是 30 号。)

结束语
现在您应该已经正确设置了 Eclipse,并对其进行了配置,使其可以与 Jakarta Tomcat 一起工作。现在就可以快速开发并对 JSP 和 Java 代码快速进行集成测试了,这个优秀的程序可以提高我们的生产率。使用 Eclipse 来编写 Java 代码并将其与 Jakarta Tomcat 进行集成,这样可以使 JSP 的开发变得更有趣,也更容易。

参考资料

关于作者
Geoff Duck 是 IBM Canada Ltd 的一名软件开发人员,他在位于加拿大 BC Burnaby 的 IBM 中心从事电子商务创新方面的研究。Geoff 专注于 Java 编程与设计,以及基于 Web 方面的应用程序开发工作。