根据The Standish Group International, Inc.的研究报告,40%的软件开发项目在完成前被取消,33%的项目延期或超支。如果像这样搞建筑项目,您能够想象一下纽约城会变成什么样子?
协同是关键
从开发环境到版本控制,你常常会走过又一个循环:采购工具,使用培训,围绕着工具使用建立内部开发过程,日常应用等等。希望在合同到期时能够顺利完成并且没有超支...
让我们来问这样一个问题:下一步是什么?
在你让开发小组提高了一点点效率之后,在你配置了开发工具之后,你仍然需要保持竞争力,下一步改善那里能够获得最大的生产力?
我们要求你看一下目前你周围的信息组织,你一定能看到不同的开发小组,同时你也能够发现其它许多技术上的协作者,如文档、外部资源、客户、设计人员等等。你将发现不同的开发小组的数量在增加,麻烦也在增加。你还能发现合作者分散在不同的部门或不同的地方。
当你看到这一切时,相信你会认识到项目组织中存在的噪音和混乱带来了沉重的经济负担。你将意识到这是下一步提高生产力的突破点,不是其它的技术工具,也不是下一个更快的编译器。
下一个效益增长点将来自管理,简化技术协作,使不同的小组以一种更快速而简单的方式共享工作中的相关信息,从而降低“项目组织中的噪音”,而且使优秀的小组不会被拖住后腿。换句话说,你的下一个效益增长点将来自实现你的信息组织中所有成员之间的协同工作。
|
“我只需要版本控制,或许是软件配置管理...
何必要协同呢?”
|
获得协同的动机依赖于企业内信息组织的个体:应用开发组(如上图中的Tom),应用开发管理(如Ann)和技术协作者(如文档、帮助平台和客户等等),他们参与不同的软件活动,所以会有各自的看法。
例如,让我们考虑一下Tom,作为软件开发组长,他可能在应用开发和维护领域有特长,因此自然会倾向于采用专门技术,如版本控制等。那么Tom是否需要技术协作?
从哪儿提高生产力
|
版本控制和软件配置管理通过加强日常开发环境的控制,很快得到了大家的认可。但是它们能进一步提高生产力吗?
|
许多已经使用了版本控制和软件配置管理工具和软件组织,很快发现生产力的提高比预期的要低,下面列出了其中一些原因:
不同的项目组使用不同的工具,降低了效率。但搞统一是不合理的,违背自然规律。
不同工具之间有“隔阂”,难于重用数据,也减少了项目组之间的交流。
已有的版本控制工具不能支持远程用户,或者性能明显退化(如一个基于文件服务器的工具,当在WAN或Internet上使用时,会变得非常迟缓)。
考虑到上述因素,很明显Tom肯定会对技术协作发生兴趣:
- 建立在版本控制和软件配置管理之上,提供对信息技术资源的准确访问。
- 通过无缝访问不同的版本控制工具促进代码共享。
- 从任何地方访问(LAN/WAN/Internet/WEB),改善已有的版本控制工具
- 从其它平台(通过统一的JAVA客户端),扩展垮平台的代码共享和重用。
- 提供一个具有高度伸缩性的现代化体系结构,使得将工具扩展到其它领域和功能范畴成为可能。
StarTeam满足所有上述需求,它具有:
- 与PVCS和SourceSafe的互操作性,
- 完全的地理位置独立性,
- 客户/服务器体系结构,为Internet和WAN开发环境特别优化,
- 能够运行在任何JAVA平台上的统一的客户端应用。
更重要的是,StarTeam支持开发队伍建立一个协同工作的稳固基础的需要。
队伍中的其它部分怎么办?
|
我的需求还未满足:我要求所有的项目组能够协调工作!我要求他们能够共享和重用,不管他们用什么样的版本控制工具,并且我需要能够完全有关联性地访问技术上的协作者,即使他们可能并不是技术方面的。
|
迄今为止,Tom已有了他所需要的版本控制和软件配置管理工具,如StarTeam Versions、 PVCS或Visual SourceSafe等。
但这仍然无法解决团队中其它人员的需要,如Ann。这些需要是:
- 项目组之间的协同:
Tom、John和Mary使用不同的工具,他们之间在代码共享和重用上有一定的困难。
- 系统资源的公共访问,而不管使用哪个版本数据库。像PVCS和SourceSafe这样的配置管理工具都是很专门的,使用不同的术语和操作。因此,你可能需要访问John和Mary使用的两种完全不同的系统。
- 需要支持位于不同地点的项目组成员,而且可能是动态变化的,比如你需要在用户现场干一段。
- 快速、直观地访问开发相关的内容,包括文档、计划、外部资源、管理、帮助平台和客户等不具有“软件开发头脑”的对象。除非选择一个非常容易使用、高度集成和直观的解决方案,否则要将技术协作集成到开发功能中几乎是不可能的。
因此,单纯的技术工具与期望尚有一段距离。版本控制和软件配置管理是不可缺少的工具(否则如何安全地管理信息技术财富?),但它们不是设计成用于解决协同工作需要的。
协同将他们结合在一起
|
一个真正的协同解决方案支持所有的功能范畴和团队,无论他们是处在传统软件开发环境之内还是之外。
|
StarTeam提供了真正的协同工作,使得开发环境内外的所有的功能范畴和团队能够积极参与共同的活动。协同自底向上建立:底层是安全地控制和管理信息技术财富,上层是协同:
-
版本控制和配置管理功能没有这一关键的功能。
-
透明的跨引擎(不同的工具)互操作性。
- 一个提供访问你的所有软件资源的协同框架。
- 允许已有的用户继续使用其版本控制工具的能力,保护已有的投资。
- 完全的位置独立性。
-
平台独立性(LAN/WAN/Internet/WEB)。
- 一个获奖的、非常容易使用的图形用户界面,非技术性用户也能应付自如。
- 文件、交流和变化请求等所有应用资源之间的关联。
-
虚拟的信息资源视图,允许每个项目成员将信息资源看作只与自己有关,并支持直观的进度、生命周期状态、产品版本、基线版本和私有配置。
- 完全集成的变化请求管理,集成在一个更高、更有意义的层次上。
你可以发现,这些额外的功能特性并不仅仅提供了对软件配置管理的支持。更重要的是,在软件配置管理的基础上建立技术协同。
StarTeam所提供的协同能力,能够真正提高生产力并取得竞争优势:所有成员主动合作和共享相关资源,实现更快、更好的目标。
总之,StarTeam是一个真正的技术协同解决方案。
|
从里到外建立协同。 |
所有的协同工具都有一个共同的目标:允许一起工作的人们快速有效地共享关联信息。这样就容易确定专业范围,并使在公共领域中的交流更方便。
因此,技术和事务协同解决方案适合于建立一个公共的、易于实现的工作人员协同工作的环境。
但是,技术和事务协同在一下三方面有重要差别:
-
使用的技术财富:事务协同的对象是办公文档和文件,而技术协同的对象是软件财富。
- 核心人员:事务协同将办公人员集合在一起;技术协同的首要也是最重要的目的是解决软件开发人员(包括管理和技术合作者)的需求。
- 使用的关联信息的复杂性:技术协同必须共享高度复杂的关联信息,其中这些关系不是立即显现的,也不会包含所有的交流内容(即交谈内容必须能被以后的合作者多次访问)。而事务合作更有时效性,简单的关联和短期的交流。
版本控制和配置管理基础
由于技术协同要求安全可靠、可审核以及有效地访问企业的关键应用,它必须建立在强大的版本控制和配置管理上...一个事务文件通常随着版本发展,而应用部件必须是可以在时间上游动的,即能够支持频繁的回溯和修订。
进一步,技术协同必须与开发人员日常使用的工具和环境紧密集成在一起。
特别支持软件开发
除非软件开发小组利用技术协同系统,否则所有的协同将会停止在与信息组织的其余部分分隔开来的地方。这就是StarTeam为什么提供扩展的开发支持功能的原因,如差异比较、可视化合并、版本标签(version labeling)、审核印迹(audit trails)、表示阶段的虚拟视图、时间游动事例(time-travel instances)和私有对象等等。
信息关联的表达和共享
为了支持复杂关联信息的共享和重用,技术协同工具必须能够做到:
- 适当地表示关系,通过一个通用化的链接引擎支持所有在协同信息库中跟踪的对象之间的扩展链接。StarTeam将这种链接扩充到文件、版本、变化请求和会话。
- 支持同一个数据库的多虚拟视图,因此每一个功能范围都能够“看到”与之有关的关联内容。StarTeam通过最先进的虚拟视图支持这种需求,从协同环境的所有对象中虚拟选择,从而实现生命周期阶段化、时间游动、调试、私有视图和其它许多功能。
- 不断积累应用开发中产生的知识,使得诸如文档、帮助平台、质量保证人员等等能够快速有效地共享这些知识,而不会额外增加沟通成本。
| 因此,技术协同加强了“同心环”之间的合作,从开发环境向外扩展到:- 技术协同
- 程序管理办公室(PMO)
- 项目管理功能(PM)
下面我们将看到,这些不同的功能组的需求是有差别的,但是它们都有一个共同的目标-技术协同。 |
开发需求
当前的分布式开发环境强调软件配置管理解决方案的能力:
产品化的信息库:StarTeam提供一个可伸缩、成熟的信息库,完全面向对象,版本化所有的对象(包括文件、目录、视图和变化请求),完全支持多重实体关系。StarTeam信息库使用了扩展的行业标准,如ODBC、COM、JAVA beans和Active-X等等。
- 真正的客户/服务器体系结构:基于文件系统的工具(如PVCS和SourceSafe)很难有效地运行在WAN、Internet或WEB环境中,因为其性能是难以接受的。
- WAN/WEB优化:StarTeam特别针对WAN、Internet和WEB进行了优化,增强了诸多特性,如加密、压缩、增量式提交(即只提交差异部分而不是这个文件)、数据库的远程同步(无需传输所有相关的文件)等等。
- 可视化配置管理:特别方便使用,且功能强大,允许开发人员以一种可视化和直观的方式定义任何数量的数据库切片,支持分阶段、“时间游动”和调试。
- 所有信息库对象之间的通用化链接:用户自然地用关系表示上下文相关的内容,而与其他开发人员共享这些关联内容对他们的工作来说是至关重要的。StarTeam支持对这种关系的要求,跨所有对象类型(文件、版本、会话和变化请求等)的通用化链接简便易用。
- 功能集成:为什么开发人员不得不使用两个单独的应用:一个制作变化,另一个跟踪这些变化和外部变化请求之间的关系?StarTeam在一个高效率的用户界面下集成了所有这些功能。
- 易于使用:屡获殊荣的StarTeam图形用户界面是一个高效率、直观、使用方便的开发环境。
- 与开发工具集成:StarTeam与所有主流的开发工具集成。同时,StarTeam提供应用接口开发的能力(通过COM和JAVA beans)。
- 与其它配置管理软件的透明互操作:如果你的开发队伍已经使用了其它版本控制工具,如PVCS和 SourceSafe,StarTeam保护和继承你当前的工作和投资,你可以在一个用户界面下透明地使用三个产品的版本档案(单独或通过StarTeam)。这不是导入/导出功能,这是完全的透明互操作!
技术协同
传统上将开发环境划分为开发、测试、集成和产品,越来越独立于与其它技术功能,如文档、设计、计划、外部资源、管理、帮助平台、经营主管、客户等等。
作为一个例子,让我们考虑WEB应用开发:JAVA开发人员如何能够没有说明文档、设计人员、手册编写人员等的密切协同?
如果不能满足下列关键需求,则这些技术协同将不能发挥作用:
非常容易使用:传统的开发工具需要大量的使用培训。而让管理人员去上课是乎有些困难。
- 熟悉文件管理界面:用于存取文件夹、文件和任何其它对象的界面应该与Windows资源管理器相似,绝大多数合作者都会使用它。
- 地理位置独立:管理人员和开发人员都可能分布在不同的地方,或临时变动工作地点,但他们都需要随时访问有关系统。
- 直接的关联导航:StarTeam的多向链接能给技术协同者带来巨大的好处,因为链接提供了一个容易跟随、直观的导航机制,轻松访问与特定对象关联的文件、变化请求和会话等。
- 线索化的会话:在开发和维护过程中,StarTeam用线索化的会话的形式保持日常的活动和决定,用户将从中积累大量有价值的知识,这些知识库可以直接被其它技术协同者访问。
程序管理办公室(PMO)
在大型项目中,经常需要一个程序办公室,是管理这个应用的中心。
根据行业专家的研究报告,如果不使用集中的记录数据库,程序办公室将无法开展工作,集中数据库中所有受影响的对象会被跟踪。
StarTeam 2000是StarTeam Professional的一个特别版本,增加了以上功能,提供对依从跟踪系统(Compliance Tracking System)的综合支持。
CTS变成了建立记录数据库的理想工具,通过与StarTeam的集成,将数字化财富、依从工作及其在软件部件上的表示形成了一个闭环。
项目管理功能
开发环境处理文件、变化和资源,项目管理针对任务、工作分配、依赖关系和时间。
尽管有许多项目管理产品,如Microsoft Project,但通常都不能很好地支持开发项目,因为跟踪制作变化的时间、执行它们所用的资源和更新贯穿整个生命周期的项目信息需要很高的开销。
这是很不幸的,因为开发人员确实希望从项目管理功能中获得好处,并且因为诸如应用软件这样关键的财富游离于项目管理框架之外。
要提高团队生产力,必须将项目管理功能与开发环境集成在一起。集成必须能够:
- 支持任务,任务是一个完全激活的对象,用于关联资源、变化请求 、工作分配和变化。
- 完全集成任务对象与开发信息库中维护的其它对象。
- 支持项目模板,因此任务和工作分配能够自动应用到相似的项目中。
- 开发信息库和MS Project引擎之间透明、双向的数据更新。
StarBase支持上述功能,为你提供了一个完整的应用开发项目管理解决方案。
协同的所有原理是-自底向上。即从低层的服务到高层次的协同功能。
首先,协同提供的最基本的服务是产品化的、成熟的版本控制和软件配置管理。因为协同是建立在应用财富之上的,它们必须被安全地管理、审查、保护和版本化。
StarTeam提供的版本控制引擎支持典型的软件开发事务,如文件差异分析和合并、版本标签、建立支持和文件管理等等。
StarTeam的版本控制引擎与Oracle、Symantec、Allaire、Haht Software等其它许多软件公司提供的版本控制工具是一样的。
共同访问信息技术财富
多少年来,开发队伍已经使用版本控制保护其信息技术财富。因此,当在开发小组之间实现协同时,你将发现开发小组会逐渐抛弃传统的版本控制工具。
StarTeam是唯一能保护你的版本控制工具投资的这种产品,提供与其它版本控制工具(如PVCS和SourceSafe)的透明互操作。不仅是导入/导出功能:完全的真实的互操作。即用户A可以使用SourceSafe建立一个文件的版本,用户B使用StarTeam,那么任一用户都可以通过SourceSafe和StarTeam访问自己或他人的版本。
协同框架
在版本控制引擎互操作之上,StarTeam建立了它最重要的功能层:协同框架。StarTeam这一独特的体系结构,是建立世界级产品的基础。
该功能层的技术描述是:强壮的,可伸缩的,基于标准的,面向对象的信息数据库,完全版本化的,支持多向通用化链接。用通俗的话来说就是,协同框架是StarTeam允许所有团队成员快速有效地进行协同工作的功能性(表示和共享关联信息)。
协同框架提供:
从任何地方进行安全有效的访问:StarTeam是一个客户/服务器产品,针对宽带和窄带连接进行了优化设计。用户能够使用下列方式访问PVCS、SourceSafe和StarTeam版本库:
- 运行在LAN、WAN或TCP/IP连接(如Internet)上的StarTeam客户端应用。
- 运行在任何JAVA平台并连接在LAN、WAN或Internet上的StarTeam JAVA客户端。
- 一个标准的浏览器,不需要装入插件程序和JAVA小程序。
- 获奖的易于使用的图形用户界面:StarTeam已经多次被专家和用户一致评定为软件配置管理类中最容易使用的产品。无论你是开发人员或是不懂版本控制的技术协同者,都可以立即学会使用StarTeam,并且其功能性将会给你留下深刻的影响。
- 直观的文件管理界面:StarTeam让你通过熟悉的Windows风格访问项目中的文件目录结构。你可以在许多文件夹中使用相同的文件名:StarTeam使用的文件和版本名字没有限制,这与Windows环境不同(许多基于文件相同的工具是有限制的)。
- 通用化链接引擎:StarTeam数据库中所有的对象,无论文件、版本、变化请求或会话,都可以被任意链接,以表示它们之间逻辑和/或物理关系中包含的关联信息。你要想了解一个对象的上下文关系,只需跟着链接走。
- 可视化配置管理:定义信息库的虚拟视图的能力对用户来说总是有吸引力的,但通常在高端的SCM工具中才会有。StarTeam实现了这一特性并且更进一步,包括用户界面的所有可视化元素。StarTeam用户能够可视化定义和维护虚拟视图实现隔离应用场合、阶段化(例如开发、测试、集成和产品等)、对应用过去的任何精确的日期和时间的时间游动、执行增量式调试等等。
协同框架中的所有功能可应用于信息库中的所有对象、建立在其上的任何生产力模块以及任何与StarTeam通讯的应用。
标准接口
StarTeam基于标准的集成接口层能够扩展信息数据库的功能性。它提供了从任何使用COM或JAVA Beans的应用完全存取所有信息库对象的能力。因此用Visual Basic、JAVA以及COM或JAVA兼容的语言编写的应用都能存取StarTeam中保存的版本、变化请求、会话、任务或其它任何对象。想象一下这样的可能性,将自己内部开发的应用和第三方的软件包集成在一个保存有你的信息技术财富的透明的信息库中,不管它们是在StarTeam还是在SourceSafe数据库中,这不是很美妙吗?
生产力模块
生产力模块是集成的部件,它增加了对象定义和功能性,如变化请求管理、会话、任务管理等等。
生产力模块自动集成到StarTeam的用户界面。要在StarTeam客户端应用中实现一个新对象只要有一个动态连接库.DLL即可。将一个.DLL拿走,与该特殊对象(如变化请求)有关的所有功能性将立即从用户界面上消失。
这一独特、最先进的对象集成技术是StarTeam强大的协同框架体系和信息数据库实现的副产品。
集成自己的应用
前面描述的基于标准的集成,同样适用于你自己内部开发的应用,可以用VB或任何COM或JAVA Beans兼容的语言实现。
集成多厂家的应用
互操作层让版本控制引擎协同工作,协同框架使用户合作。同样,标准接口层实现技术的协同。
StarTeam正在推出StarPartner软件合作伙伴策略,通过StarTeam SDK,保证其它技术能够利用StarTeam生产力模块同样的机制使用产品信息数据库的服务。
StarTeam是目前唯一的企业级协同解决方案。
StarTeam是一个集成的解决方案,为企业信息组织中从开发人员到项目管理人员的所有成员带来了好处。
这一革命性的解决方案事实上正在成为标准。许多全球性的大型企业正在采用StarTeam,通过建立跨团队、跨部门、跨专业的协同工作,提高应用队伍的效率。
对商业用户来说,他们后面是成百上千个供应商,前面是成千上万个消费顾客。怎样利用软件管理错综复杂的供应商和消费顾客,如何做好精细到一个小小调料包的进、销、调、存的商品流通工作,这些都是商业企业需要信息管理系统的理由。软件开发的意义也就在于此。而弄清商业用户如此复杂需求的真面目,正是软件开发成功的关键所在。
--- 经理:“我们要建立一套完整的商业管理软件系统,包括商品的进、销、调、存管理,是总部-门店的连锁经营模式。通过通信手段门店自动订货,供应商自动结算,卖场通过扫条码实现销售,管理人员能够随时查询门店商品销售和库存情况。另外,我们也得为政府部门提供关于商品营运的报告。”
-- -分析员:“我已经明白这个项目的大体结构框架,这非常重要,但在制定计划之前,我们必须收集一些需求。”
-- -经理觉得奇怪:“我不是刚告诉你我的需求了吗?”
-- -分析员:“实际上,您只说明了整个项目的概念和目标。这些高层次的业务需求不足以提供开发的内容和时间。我需要与实际将要使用系统的业务人员进行讨论,然后才能真正明白达到业务目标所需功能和用户要求,了解清楚后,才可以发现哪些是现有组件即可实现的,哪些是需要开发的,这样可节省很多时间。”
-- -经理:“业务人员都在招商。他们非常忙,没有时间与你们详细讨论各种细节。你能不能说明一下你们现有的系统?”
--- 分析员尽量解释从用户处收集需求的合理性:“如果我们只是凭空猜想用户的要求,结果不会令人满意。我们只是软件开发人员,而不是采购专家、营运专家或是财务专家,我们并不真正明白您这个企业内部运营需要做些什么。我曾经尝试过,未真正明白这些问题就开始编码,结果没有人对产品满意。”
--- 经理坚持道:“行了,行了,我们没有那么多的时间。让我来告诉您我们的需求。实际上我也很忙。请马上开始开发,并随时将你们的进展情况告诉我。”
--- 风险躲在需求的迷雾之后- --以上我们看到的是某客户项目经理与系统开发小组的分析人员讨论业务需求。在项目开发中,所有的项目风险承担者都对需求分析阶段备感兴趣。这里所指的风险承担者包括客户方面的项目负责人和用户,开发方面的需求分析人员和项目管理者。这部分工作做得到位,能开发出很优秀的软件产品,同时也会令客户满意。若处理不好,则会导致误解、挫折、障碍以及潜在的质量和业务价值上的威胁。因此可见——需求分析奠定了软件工程和项目管理的基础。
-- -拨开需求分析的迷雾--- 像这样的对话经常出现在软件开发的过程中。客户项目经理的需求对分析人员来讲,像“雾里看花”般模糊并令开发者感到困惑。那么,我们就拨开雾影,分析一下需求的具体内容:
-- -·业务需求——反映了组织机构或客户对系统、产品高层次的目标要求,通常在项目定义与范围文档中予以说明。
--- ·用户需求——描述了用户使用产品必须要完成的任务,这在使用实例或方案脚本中予以说明。
--- ·功能需求——定义了开发人员必须实现的软件功能,使用户利用系统能够完成他们的任务,从而满足了业务需求。
-- -·非功能性的需求——描述了系统展现给用户的行为和执行的操作等,它包括产品必须遵从的标准、规范和约束,操作界面的具体细节和构造上的限制。
--- ·需求分析报告——报告所说明的功能需求充分描述了软件系统所应具有的外部行为。“需求分析报告”在开发、测试、质量保证、项目管理以及相关项目功能中起着重要作用。
--- 前面提到的客户项目经理通常阐明产品的高层次概念和主要业务内容,为后继工作建立了一个指导性的框架。其他任何说明都应遵循“业务需求”的规定,然而“业务需求”并不能为开发人员提供开发所需的许多细节说明。
--- 下一层次需求——用户需求,必须从使用产品的用户处收集。因此,这些用户构成了另一种软件客户,他们清楚要使用该产品完成什么任务和一些非功能性的特性需求。例如:程序的易用性、健壮性和可靠性,而这些特性将会使用户很好地接受具有该特点的软件产品。
--- 经理层有时试图代替实际用户说话,但通常他们无法准确说明“用户需求”。用户需求来自产品的真正使用者,必须让实际用户参与到收集需求的过程中。如果不这样做,产品很可能会因缺乏足够的信息而遗留不少隐患。
--- 在实际需求分析过程中,以上两种客户可能都觉得没有时间与需求分析人员讨论,有时客户还希望分析人员无须讨论和编写需求说明就能说出用户的需求。除非遇到的需求极为简单;否则不能这样做。如果您的组织希望软件成功,那么必须要花上数天时间来消除需求中模糊不清的地方和一些使开发者感到困惑的方面。
--- 优秀的软件产品建立在优秀的需求基础之上,而优秀的需求源于客户与开发人员之间有效的交流和合作。只有双方参与者都明白自己需要什么、成功的合作需要什么时,才能建立起一种良好的合作关系。
--- 由于项目的压力与日俱增,所有项目风险承担者有着一个共同目标,那就是大家都想开发出一个既能实现商业价值又能满足用户要求,还能使开发者感到满足的优秀软件产品。
-- -客户的需求观-- -客户与开发人员交流需要好的方法。下面建议20条法则,客户和开发人员可以通过评审以下内容并达成共识。如果遇到分歧,将通过协商达成对各自义务的相互理解,以便减少以后的磨擦(如一方要求而另一方不愿意或不能够满足要求)。
--- 1、 分析人员要使用符合客户语言习惯的表达--- 需求讨论集中于业务需求和任务,因此要使用术语。客户应将有关术语(例如:采价、印花商品等采购术语)教给分析人员,而客户不一定要懂得计算机行业的术语。
--- 2、分析人员要了解客户的业务及目标--- 只有分析人员更好地了解客户的业务,才能使产品更好地满足需要。这将有助于开发人员设计出真正满足客户需要并达到期望的优秀软件。为帮助开发和分析人员,客户可以考虑邀请他们观察自己的工作流程。如果是切换新系统,那么开发和分析人员应使用一下目前的旧系统,有利于他们明白目前系统是怎样工作的,其流程情况以及可供改进之处。s
--- 3、 分析人员必须编写软件需求报告--- 分析人员应将从客户那里获得的所有信息进行整理,以区分业务需求及规范、功能需求、质量目标、解决方法和其他信息。通过这些分析,客户就能得到一份“需求分析报告”,此份报告使开发人员和客户之间针对要开发的产品内容达成协议。报告应以一种客户认为易于翻阅和理解的方式组织编写。客户要评审此报告,以确保报告内容准确完整地表达其需求。一份高质量的“需求分析报告”有助于开发人员开发出真正需要的产品。
--- 4、 要求得到需求工作结果的解释说明--- 分析人员可能采用了多种图表作为文字性“需求分析报告”的补充说明,因为工作图表能很清晰地描述出系统行为的某些方面,所以报告中各种图表有着极高的价值;虽然它们不太难于理解,但是客户可能对此并不熟悉,因此客户可以要求分析人员解释说明每个图表的作用、符号的意义和需求开发工作的结果,以及怎样检查图表有无错误及不一致等。
--- 5、 开发人员要尊重客户的意见--- 如果用户与开发人员之间不能相互理解,那关于需求的讨论将会有障碍。共同合作能使大家“兼听则明”。参与需求开发过程的客户有权要求开发人员尊重他们并珍惜他们为项目成功所付出的时间,同样,客户也应对开发人员为项目成功这一共同目标所做出的努力表示尊重。
--- 6、 开发人员要对需求及产品实施提出建议和解决方案--- 通常客户所说的“需求”已经是一种实际可行的实施方案,分析人员应尽力从这些解决方法中了解真正的业务需求,同时还应找出已有系统与当前业务不符之处,以确保产品不会无效或低效;在彻底弄清业务领域内的事情后,分析人员就能提出相当好的改进方法,有经验且有创造力的分析人员还能提出增加一些用户没有发现的很有价值的系统特性。
--- 7、 描述产品使用特性--- 客户可以要求分析人员在实现功能需求的同时还注意软件的易用性,因为这些易用特性或质量属性能使客户更准确、高效地完成任务。例如:客户有时要求产品要“界面友好”或“健壮”或“高效率”,但对于开发人员来讲,太主观了并无实用价值。正确的做法是,分析人员通过询问和调查了解客户所要的“友好、健壮、高效所包含的具体特性,具体分析哪些特性对哪些特性有负面影响,在性能代价和所提出解决方案的预期利益之间做出权衡,以确保做出合理的取舍。
--- 8、 允许重用已有的软件组件--- 需求通常有一定灵活性,分析人员可能发现已有的某个软件组件与客户描述的需求很相符,在这种情况下,分析人员应提供一些修改需求的选择以便开发人员能够降低新系统的开发成本和节省时间,而不必严格按原有的需求说明开发。所以说,如果想在产品中使用一些已有的商业常用组件,而它们并不完全适合您所需的特性,这时一定程度上的需求灵活性就显得极为重要了。
--- 9、 要求对变更的代价提供真实可靠的评估--- 有时,人们面临更好、也更昂贵的方案时,会做出不同的选择。而这时,对需求变更的影响进行评估从而对业务决策提供帮助,是十分必要的。所以,客户有权利要求开发人员通过分析给出一个真实可信的评估,包括影响、成本和得失等。开发人员不能由于不想实施变更而随意夸大评估成本。
--- 10、 获得满足客户功能和质量要求的系统--- 每个人都希望项目成功,但这不仅要求客户要清晰地告知开发人员关于系统“做什么”所需的所有信息,而且还要求开发人员能通过交流了解清楚取舍与限制,一定要明确说明您的假设和潜在的期望,否则,开发人员开发出的产品很可能无法让您满意。
--- 11、 给分析人员讲解您的业务--- 分析人员要依靠客户讲解业务概念及术语,但客户不能指望分析人员会成为该领域的专家,而只能让他们明白您的问题和目标;不要期望分析人员能把握客户业务的细微潜在之处,他们可能不知道那些对于客户来说理所当然的“常识”。
--- 12、 抽出时间清楚地说明并完善需求--- 客户很忙,但无论如何客户有必要抽出时间参与“头脑高峰会议”的讨论,接受采访或其他获取需求的活动。有些分析人员可能先明白了您的观点,而过后发现还需要您的讲解,这时请耐心对待一些需求和需求的精化工作过程中的反复,因为它是人们交流中很自然的现象,何况这对软件产品的成功极为重要。
--- 13、 准确而详细地说明需求--- 编写一份清晰、准确的需求文档是很困难的。由于处理细节问题不但烦人而且耗时,因此很容易留下模糊不清的需求。但是在开发过程中,必须解决这种模糊性和不准确性,而客户恰恰是为解决这些问题作出决定的最佳人选,否则,就只好靠开发人员去正确猜测了。
--- 在需求分析中暂时加上“待定”标志是个方法。用该标志可指明哪些是需要进一步讨论、分析或增加信息的地方,有时也可能因为某个特殊需求难以解决或没有人愿意处理它而标注上“待定”。客户要尽量将每项需求的内容都阐述清楚,以便分析人员能准确地将它们写进“软件需求报告”中去。如果客户一时不能准确表达,通常就要求用原型技术,通过原型开发,客户可以同开发人员一起反复修改,不断完善需求定义。
--- 14、 及时作出决定--- 分析人员会要求客户作出一些选择和决定,这些决定包括来自多个用户提出的处理方法或在质量特性冲突和信息准确度中选择折衷方案等。有权作出决定的客户必须积极地对待这一切,尽快做处理,做决定,因为开发人员通常只有等客户做出决定才能行动,而这种等待会延误项目的进展。
--- 15、 尊重开发人员的需求可行性及成本评估--- 所有的软件功能都有其成本。客户所希望的某些产品特性可能在技术上行不通,或者实现它要付出极高的代价,而某些需求试图达到在操作环境中不可能达到的性能,或试图得到一些根本得不到的数据。开发人员会对此作出负面的评价,客户应该尊重他们的意见。
--- 16、 划分需求的优先级--- 绝大多数项目没有足够的时间或资源实现功能性的每个细节。决定哪些特性是必要的,哪些是重要的,是需求开发的主要部分,这只能由客户负责设定需求优先级,因为开发者不可能按照客户的观点决定需求优先级;开发人员将为您确定优先级提供有关每个需求的花费和风险的信息。
--- 在时间和资源限制下,关于所需特性能否完成或完成多少应尊重开发人员的意见。尽管没有人愿意看到自己所希望的需求在项目中未被实现,但毕竟是要面对现实,业务决策有时不得不依据优先级来缩小项目范围或延长工期,或增加资源,或在质量上寻找折衷。
--- 17、 评审需求文档和原型--- 客户评审需求文档,是给分析人员带来反馈信息的一个机会。如果客户认为编写的“需求分析报告”不够准确,就有必要尽早告知分析人员并为改进提供建议。
--- 更好的办法是先为产品开发一个原型。这样客户就能提供更有价值的反馈信息给开发人员,使他们更好地理解您的需求;原型并非是一个实际应用产品,但开发人员能将其转化、扩充成功能齐全的系统。
--- 18、 需求变更要立即联系--- 不断的需求变更,会给在预定计划内完成的质量产品带来严重的不利影响。变更是不可避免的,但在开发周期中,变更越在晚期出现,其影响越大;变更不仅会导致代价极高的返工,而且工期将被延误,特别是在大体结构已完成后又需要增加新特性时。所以,一旦客户发现需要变更需求时,请立即通知分析人员。
--- 19、 遵照开发小组处理需求变更的过程--- 为将变更带来的负面影响减少到最低限度,所有参与者必须遵照项目变更控制过程。这要求不放弃所有提出的变更,对每项要求的变更进行分析、综合考虑,最后做出合适的决策,以确定应将哪些变更引入项目中。
--- 20、 尊重开发人员采用的需求分析过程--- 软件开发中最具挑战性的莫过于收集需求并确定其正确性,分析人员采用的方法有其合理性。也许客户认为收集需求的过程不太划算,但请相信花在需求开发上的时间是非常有价值的;如果您理解并支持分析人员为收集、编写需求文档和确保其质量所采用的技术,那么整个过程将会更为顺利。
--- “需求确认”意味着什么--- 在“需求分析报告”上签字确认,通常被认为是客户同意需求分析的标志行为,然而实际操作中,客户往往把“签字”看作是毫无意义的事情。“他们要我在需求文档的最后一行下面签名,于是我就签了,否则这些开发人员不开始编码。”
--- 这种态度将带来麻烦,譬如客户想更改需求或对产品不满时就会说:“不错,我是在需求分析报告上签了字,但我并没有时间去读完所有的内容,我是相信你们的,是你们非让我签字的。”
--- 同样问题也会发生在仅把“签字确认”看作是完成任务的分析人员身上,一旦有需求变更出现,他便指着“需求分析报告”说:“您已经在需求上签字了,所以这些就是我们所开发的,如果您想要别的什么,您应早些告诉我们。”
--- 这两种态度都是不对的。因为不可能在项目的早期就了解所有的需求,而且毫无疑问地需求将会出现变更,在“需求分析报告”上签字确认是终止需求分析过程的正确方法,所以我们必须明白签字意味着什么。
--- 对“需求分析报告”的签名是建立在一个需求协议的基线上,因此我们对签名应该这样理解:“我同意这份需求文档表述了我们对项目软件需求的了解,进一步的变更可在此基线上通过项目定义的变更过程来进行。我知道变更可能会使我们重新协商成本、资源和项目阶段任务等事宜。”对需求分析达成一定的共识会使双方易于忍受将来的摩擦,这些摩擦来源于项目的改进和需求的误差或市场和业务的新要求等。
--- 需求确认将迷雾拨散,显现需求的真面目,给初步的需求开发工作画上了双方都明确的句号,并有助于形成一个持续良好的客户与开发人员的关系,为项目的成功奠定了坚实的基础。
摘要: 1.1 门户建设服务器(Portal Builder Server)EIP门户建设服务器主要的功能是实现系统的基本架构管理,包括:门户管理、多站点建设、工作流、系统安全与权限、节点与频道管理、模块管理与接口、模版管理、资源管理等模块组成,通过EIP门户架构服务器可以实现对于门户框架的全部管理功能,主要的特点如下: 1. 适应普通用户。提供类似Web浏览器这样直观的工具来满足...
阅读全文
JSP 标准标记库(JSP Standard Tag Library,JSTL)是一个实现 Web 应用程序中常见的通用功能的定制标记库集,这些功能包括迭代和条件判断、数据管理格式化、XML 操作以及数据库访问。在 developerWorks 上其新系列的第一篇文章中,软件工程师 Mark Kolb 向您展示了如何使用 JSTL 标记来避免在 JSP 页面中使用脚本编制元素。您还将了解如何通过从表示层删除源代码来简化软件维护。最后,您将了解 JSTL 经过简化的表达式语言,它允许在不必使用功能齐全的编程语言的情况下对 JSTL 操作指定动态属性值。
JavaServer Pages(JSP)是用于 J2EE 平台的标准表示层技术。JSP 技术提供了用于执行计算(这些计算用来动态地生成页面内容)的脚本编制元素和操作。脚本编制元素允许在 JSP 页面中包括程序源代码,在为响应用户请求而呈现页面时可以执行这些源代码。操作将计算操作封装到很象 HTML 或 XML 标记的标记中,JSP 页面的模板文本通常包含这些标记。JSP 规范只将几种操作定义成了标准,但从 JSP 1.1 开始,开发人员已经能够以定制标记库的方式创建其自己的操作了。
JSP 标准标记库(JSTL)是 JSP 1.2 定制标记库集,这些标记库实现大量服务器端 Java 应用程序常用的基本功能。通过为典型表示层任务(如数据格式化和迭代或条件内容)提供标准实现,JSTL 使 JSP 作者可以专注于特定于应用程序的开发需求,而不是为这些通用操作“另起炉灶”。
当然,您可以使用 JSP 脚本编制元素(scriptlet、表达式和声明)来实现此类任务。例如,可以使用三个 scriptlet 实现条件内容,清单 1 中着重显示了这三个 scriptlet。但是,因为脚本编制元素依赖于在页面中嵌入程序源代码(通常是 Java 代码),所以对于使用这些脚本编制元素的 JSP 页面,其软件维护任务的复杂度大大增加了。例如,清单 1 中的 scriptlet 示例严格地依赖于花括号的正确匹配。如果不经意间引入了一个语法错误,则条件内容中的嵌套其它 scriptlet 可能会造成严重破坏,并且在 JSP 容器编译该页面时,要使所产生的错误信息有意义可能会很困难。
清单 1. 通过 scriptlet 实现条件内容
<% if (user.getRole() == "member")) { %>
<p>Welcome, member!</p>
<% } else { %>
<p>Welcome, guest!</p>
<% } %>
|
修正此类问题通常需要相当丰富的编程经验。尽管通常会由十分精通页面布局和图形设计的设计人员来开发和维护 JSP,但是同一页面中的脚本编制元素出现问题时,需要程序员的介入。这种状况将单个文件中代码的责任分担给多人,因而使得开发、调试和增强此类 JSP 页面成为很麻烦的任务。通过将常用功能包装到定制标记库的标准集合中,JSTL 使 JSP 作者可以减少对编制脚本元素的需求,甚至可以不需要它们,并避免了相关的维护成本。
JSTL 1.0
JSTL 1.0 发布于 2002 年 6 月,由四个定制标记库( core
、 format
、 xml
和 sql
)和一对通用标记库验证器( ScriptFreeTLV
和 PermittedTaglibsTLV
)组成。 core
标记库提供了定制操作,通过限制了作用域的变量管理数据,以及执行页面内容的迭代和条件操作。它还提供了用来生成和操作 URL 的标记。顾名思义, format
标记库定义了用来格式化数据(尤其是数字和日期)的操作。它还支持使用本地化资源束进行 JSP 页面的国际化。 xml
库包含一些标记,这些标记用来操作通过 XML 表示的数据,而 sql
库定义了用来查询关系数据库的操作。
两个 JSTL 标记库验证器允许开发人员在其 JSP 应用程序中强制使用编码标准。可以配置 ScriptFreeTLV
验证器以在 JSP 页面中禁用各种类型的 JSP 脚本元素 ― scriptlet、表达式和声明。类似地, PermittedTaglibsTLV
验证器可以用来限制可能由应用程序的 JSP 页面访问的定制标记库集(包括 JSTL 标记库)。
尽管 JSTL 最终将会成为 J2EE 平台的必需组件,但目前只有少数应用程序服务器包括它。JSTL 1.0 的参考实现可作为 Apache 软件基金会(Apache Software Foundation)的 Jakarta Taglibs 项目(请参阅 参考资料)的一部分而获得。可以将该参考实现中的定制标记库合并到任何支持 JSP 1.2 和 Servlet 2.3 规范的服务器,以添加对 JSTL 的支持。
表达式语言
在 JSP 1.2 中,可以使用静态字符串或表达式(如果允许的话)指定 JSP 操作的属性。例如,在清单 2 中,对 <jsp:setProperty>
操作的 name
和 property
属性指定了静态值,而用表达式指定了其 value
属性。这个操作的效果是将请求参数的当前值赋予命名的 bean 特性。以这种形式使用的表达式被称为 请求时属性值(request-time attribute value),这是构建到 JSP 规范中的用于动态指定属性值的唯一机制。
清单 2. 合并请求时属性值的 JSP 操作
<jsp:setProperty name="user" property="timezonePref"
value='<%= request.getParameter("timezone") %>'/>
|
因为请求时属性值是用表达式指定的,所以它们往往有和其它脚本元素一样的软件维护问题。因此,JSTL 定制标记支持另一种用于指定动态属性值的机制。可以用简化的 表达式语言(EL)而不使用完整的 JSP 表达式来指定 JSTL 操作的属性值。EL 提供了一些标识符、存取器和运算符,用来检索和操作驻留在 JSP 容器中的数据。EL 在某种程度上以 EcmaScript(请参阅 参考资料)和 XML 路径语言(XML Path Language,XPath)为基础,因此页面设计人员和程序员都应该熟悉它的语法。EL 擅长寻找对象及其特性,然后对它们执行简单操作;它不是编程语言,甚至不是脚本编制语言。但是,与 JSTL 标记一起使用时,它就能使用简单而又方便的符号来表示复杂的行为。EL 表达式的格式是这样的:用美元符号($)定界,内容包括在花括号({})中,如清单 3 所示。
清单 3. 说明 EL 表达式定界符的 JSTL 操作
<c:out value="${user.firstName}"/>
|
此外,您可以将多个表达式与静态文本组合在一起以通过字符串并置来构造动态属性值,如清单 4 所示。单独的表达式由标识符、存取器、文字和运算符组成。标识符用来引用存储在数据中心中的数据对象。EL 有 11 个保留标识符,对应于 11 个 EL 隐式对象。假定所有其它标识符都引用 限制了作用域的变量。存取器用来检索对象的特性或集合的元素。文字表示固定的值 ― 数字、字符、字符串、布尔型或空值。运算符允许对数据和文字进行组合以及比较。
清单 4. 组合静态文本和多个 EL 表达式以指定动态属性值
<c:out value="Hello ${user.firstName} ${user.lastName}"/>
|
限制了作用域的变量
JSP API 通过 <jsp:useBean>
操作允许从 JSP 容器内的四个不同作用域中存储和检索数据。JSTL 通过提供用于指定和除去这些作用域中的对象的附加操作来扩展这一能力。此外,EL 提供将这些对象作为限制了作用域的变量进行检索的内置支持。特别地,任何出现在 EL 表达式中但不对应于任何 EL 隐式对象的标识符,都被自动假定为引用存储在四个 JSP 作用域的其中某个中的对象,这四个作用域是:
- 页面作用域
- 请求作用域
- 会话作用域
- 应用程序作用域
您可能还记得,只有在为特定请求处理页面期间才能检索存储在该页面作用域中的对象。如果对象是存储在请求作用域中的,可以在处理所有参与处理某请求的页面期间检索这些对象(譬如在对某个请求的处理中遇到了一个或多个 <jsp:include>
或 <jsp:forward>
操作)。如果对象是存储在会话作用域中的,则在与 Web 应用程序的交互式会话期间,可以由用户访问的任何页面检索它(即,直到与该用户交互相关联的 HttpSession
对象无效为止)。可以由任何用户从任何页面访问存储在应用程序作用域中的对象,直到卸载 Web 应用程序本身为止(通常是由于关闭 JSP 容器所致)。
通过将字符串映射为期望作用域中的对象来将对象存储到该作用域。然后,就可以通过提供相同字符串来从该作用域检索该对象。在作用域的映射中查找字符串,并返回被映射的对象。在 Servlet API 中,将此类对象称为相应作用域的 属性。但是,在 EL 的上下文中,也将与属性相关联的字符串看作变量的名称,该变量通过属性映射的方式获得特定的值。
在 EL 中,与隐式对象无关联的标识符被认为是存储在四个 JSP 作用域中的名称对象。首先对页面作用域检查是否存在这样的标识符,其次对请求作用域、然后对会话作用域、最后对应用程序作用域依次进行这样的检查,然后测试该标识符的名称是否与存储在该作用域中的某个对象的名称匹配。第一个这样的匹配作为 EL 标识符的值被返回。通过这种方法,可以将 EL 标识符看作引用限制了作用域的变量。
从更技术的方面来说,没有映射到隐式对象的标识符是用 PageContext
实例的 findAttribute()
方法求值的,该实例表示对页面的处理,在该页面上,当前正在处理用于请求的表达式。标识符的名称作为参数传递给这个方法,然后该方法依次在四个作用域中搜索具有相同名称的属性。并将所找到的第一个匹配项作为 findAttribute()
方法的值返回。如果未在这四个作用域中找到这样的属性,则返回 null
。
最终,限制了作用域的变量是四个 JSP 作用域的属性,这些属性具有可以用作 EL 标识符的名称。只要对限制了作用域的变量赋予由字母数字组成的名称,就可以通过 JSP 中提供的用于设置属性的任何机制来创建它们。这包括内置的 <jsp:useBean>
操作,以及由 Servlet API 中的几个类定义的 setAttribute()
方法。此外,四个 JSTL 库中定义的许多定制标记本身就能够设置作为限制了作用域的变量使用的属性值。
隐式对象
表 1 中列出了 11 个 EL 隐式对象的标识符。不要将这些对象与 JSP 隐式对象(一共只有九个)混淆,其中只有一个对象是它们所共有的。
表 1. EL 隐式对象
类别
|
标识符
|
描述
|
JSP |
pageContext
|
PageContext 实例对应于当前页面的处理 |
作用域 |
pageScope
|
与页面作用域属性的名称和值相关联的 Map 类 |
requestScope
|
与请求作用域属性的名称和值相关联的 Map 类 |
sessionScope
|
与会话作用域属性的名称和值相关联的 Map 类 |
applicationScope
|
与应用程序作用域属性的名称和值相关联的 Map 类 |
请求参数 |
param
|
按名称存储请求参数的主要值的 Map 类 |
paramValues
|
将请求参数的所有值作为 String 数组存储的 Map 类 |
请求头 |
header
|
按名称存储请求头主要值的 Map 类 |
headerValues
|
将请求头的所有值作为 String 数组存储的 Map 类 |
Cookie |
cookie
|
按名称存储请求附带的 cookie 的 Map 类 |
初始化参数 |
initParam
|
按名称存储 Web 应用程序上下文初始化参数的 Map 类 |
尽管 JSP 和 EL 隐式对象中只有一个公共对象( pageContext
),但通过 EL 也可以访问其它 JSP 隐式对象。原因是 pageContext
拥有访问所有其它八个 JSP 隐式对象的特性。实际上,这是将它包括在 EL 隐式对象中的主要理由。
其余所有 EL 隐式对象都是映射,可以用来查找对应于名称的对象。前四个映射表示先前讨论的各种属性作用域。可以用它们来查找特定作用域中的标识符,而不用依赖于 EL 在缺省情况下使用的顺序查找过程。
接下来的四个映射用来获取请求参数和请求头的值。因为 HTTP 协议允许请求参数和请求头具有多个值,所以它们各有一对映射。每对中的第一个映射返回请求参数或头的主要值,通常是恰巧在实际请求中首先指定的那个值。每对中第二个映射允许检索参数或头的所有值。这些映射中的键是参数或头的名称,但这些值是 String
对象的数组,其中的每个元素都是单一参数值或头值。
cookie 隐式对象提供了对由请求设置的 cookie 名称的访问。这个对象将所有与请求相关联的 cookie 名称映射到表示那些 cookie 特性的 Cookie
对象。
最后一个 EL 隐式对象 initParam
是一个映射,它储存与 Web 应用程序相关联的所有上下文的初始化参数的名称和值。初始化参数是通过 web.xml
部署描述符文件指定的,该文件位于应用程序的 WEB-INF
目录中。
存取器
因为 EL 标识符是作为隐式对象或限制了作用域的变量(通过属性来实现)解析的,因此有必要将它们转换成 Java 对象。EL 可以自动包装和解包其相应的 Java 类中的基本类型(例如,可以在后台将 int
强制转换成 Integer
类,反之亦可),但大多数的标识符将成为指向完整的 Java 对象的指针。
结果是,对这些对象的特性或(在对象是数组和集合的情况下)对其元素的访问通常是令人满意的。就为了实现这种用途,EL 提供了两种不同的存取器(点运算符( .
)和方括号运算符( []
)),也支持通过 EL 操作特性和元素。
点运算符通常用于访问对象的特性。例如,在表达式 ${user.firstName}
中,使用点运算符来访问 user
标识符所引用对象的名为 firstName
的特性。EL 使用 Java bean 约定访问对象特性,因此必须定义这个特性的 getter 方法(通常是名为 getFirstName()
的方法),以便表达式正确求值。当被访问的特性本身是对象时,可以递归地应用点运算符。例如,如果我们虚构的 user
对象有一个实现为 Java 对象的 address
特性,那么也可以用点运算符来访问这个对象的特性。例如,表达式 ${user.address.city}
将会返回这个地址对象嵌套的 city
特性。
方括号运算符用来检索数组和集合的元素。在数组和有序集合(也即,实现了 java.util.List
接口的集合)的情况下,把要检索的元素的下标放在方括号中。例如,表达式 ${urls[3]}
返回 urls
标识符所引用的数组或集合的第四个元素(和 Java 语言以及 JavaScript 中一样,EL 中的下标是从零开始的)。
对于实现 java.util.Map
接口的集合,方括号运算符使用关联的键查找存储在映射中的值。在方括号中指定键,并将相应的值作为表达式的值返回。例如,表达式 ${commands["dir"]}
返回与 commands
标识符所引用的 Map
中的 "dir"
键相关联的值。
对于上述两种情况,都可允许表达式出现在方括号中。对嵌套表达式求值的结果将被作为下标或键,用来检索集合或数组的适当元素。和点运算符一样,方括号运算符也可以递归应用。这使得 EL 能够从多维数组、嵌套集合或两者的任意组合中检索元素。此外,点运算符和方括号运算符还可以互操作。例如,如果数组的元素本身是对象,则可以使用方括号运算符来检索该数组的元素,并结合点运算符来检索该元素的一个特性(例如 ${urls[3].protocol}
)。
假定 EL 充当指定动态属性值的简化语言,EL 存取器有一个有趣的功能(与 Java 语言的存取器不同),那就是它们在应用于 null
时不抛出异常。如果应用 EL 存取器的对象(例如, ${foo.bar}
和 ${foo["bar"]}
中的 foo
标识符)是 null
,那么应用存取器的结果也是 null
。事实证明,在大多数情况下,这是一个相当有用的行为,不久您就会了解这一点。
最后,点运算符和方括号运算符可能实现某种程度的互换。例如,也可以使用 ${user["firstName"]}
来检索 user
对象的 firstName
特性,正如可以用 ${commands.dir}
获取与 commands
映射中的 "dir"
键相关联的值一样。
运算符
EL 还可以通过使用标识符和存取器,遍历包含应用程序数据(通过限制了作用域的变量公开)或关于环境的信息(通过 EL 隐式对象)的对象层次结构。但是,只是访问这些数据,通常不足以实现许多 JSP 应用程序所需的表示逻辑。
最终,EL 还包括了几个用来操作和比较 EL 表达式所访问数据的运算符。表 2 中汇总了这些运算符。
表 2. EL 运算符
类别
|
运算符
|
算术运算符 |
+ 、 - 、 * 、 / (或 div )和 % (或 mod ) |
关系运算符 |
== (或 eq )、 != (或 ne )、 < (或 lt )、 > (或 gt )、 <= (或 le )和 >= (或 ge ) |
逻辑运算符 |
&& (或 and )、 || (或 or )和 ! (或 not ) |
验证运算符 |
empty
|
算术运算符支持数值的加法、减法、乘法和除法。还提供了一个求余运算符。注:除法和求余运算符都有替代的、非符号的名称(为的是与 XPath 保持一致)。清单 5 中显示了一个演示算术运算符用法的示例表达式。对几个 EL 表达式应用算术运算符的结果是将该算术运算符应用于这些表达式返回的数值所得的结果。
清单 5. 利用算术运算符的 EL 表达式
${item.price * (1 + taxRate[user.address.zipcode])}
|
关系运算符允许比较数字或文本数据。比较的结果作为布尔值返回。逻辑运算符允许合并布尔值,返回新的布尔值。因此,可以将 EL 逻辑运算符应用于嵌套的关系或逻辑运算符的结果,如清单 6 所示。
清单 6. 利用关系和逻辑运算符的 EL 表达式
${(x >= min) && (x <= max)}
|
最后一种 EL 运算符是 empty
,它对于验证数据特别有用。 empty
运算符采用单个表达式作为其变量(也即, ${empty input}
),并返回一个布尔值,该布尔值表示对表达式求值的结果是不是“空”值。求值结果为 null
的表达式被认为是空,即无元素的集合或数组。如果参数是对长度为零的 String
求值所得的结果,则 empty
运算符也将返回 true
。
表 3 显示了 EL 运算符的优先级。正如清单 5 和 6 所示,可以用圆括号对表达式分组,高于普通的优先级规则。
表 3. EL 运算符优先级(自顶到底,从左到右)
[] , . |
()
|
unary - 、 not 、 ! 、 empty |
* 、 / 、 div 、 % 、 mod |
+ 、binary - |
() <</code> 、 > 、 <= 、 >= 、 lt 、 gt 、 le 、 ge |
== 、 != 、 eq 、 ne |
&& 、 and |
|| 、 or |
文字
在 EL 表达式中,数字、字符串、布尔值和 null
都可以被指定为文字值。字符串可以用单引号或双引号定界。布尔值被指定为 true
和 false
。
Taglib 伪指令
正如我们先前讨论的,JSTL 1.0 包括四个定制标记库。为了演示 JSTL 标记和表达式语言的交互,我们将研究几个来自 JSTL core
库的标记。和使用任何 JSP 定制标记库一样,必须在您想要使用这个库标记的任何页面中包括 taglib
伪指令。清单 7 显示了用于这个特定库的伪指令。
清单 7. 用于 JSTL core 库 EL 版本的 taglib 伪指令
<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>
|
实际上,对应于 JSTL core
库的 taglib
伪指令有两种,因为在 JSTL 1.0 中,EL 是可选的。所有四个 JSTL 1.0 定制标记库都有使用 JSP 表达式(而不是 EL)指定动态属性值的备用版本。因为这些备用库依赖于 JSP 的更传统的请求时属性值,所以它们被称为 RT库,而那些使用表达式语言的则被称为 EL 库。开发人员用不同的 taglib
伪指令来区分每个库的这两个版本。清单 8 显示了使用 core 库的 RT 版本的伪指令。但是,由于现在我们讨论的重点是 EL,所以首先需要这些伪指令。
清单 8. 用于 JSTL core 库 RT 版本的 taglib 伪指令
<%@ taglib uri="http://java.sun.com/jstl/core_rt" prefix="c_rt" %>
|
变量标记
我们首先要考虑的 JSTL 定制标记是 <c:set>
操作。正如已经说明的,限制了作用域的变量在 JSTL 中起关键作用, <c:set>
操作提供基于标记的机制来创建和设置限制了作用域的变量。清单 9 中显示了该操作的语法,其中 var
属性指定了限制了作用域的变量的名称, scope
属性表明了该变量驻留在哪个作用域中, value
属性指定了分配给该变量的值。如果指定变量已经存在,则简单地将所指明的值赋给它。如果不存在,则创建新的限制了作用域的变量,并用该值初始化这个变量。
清单 9. <c:set> 操作的语法
<c:set var="
name" scope="
scope" value="
expression"/>
|
scope
属性是可选的,其缺省值是 page
。
清单 10 中显示了 <c:set>
的两个示例。在第一个示例中,将会话作用域变量设置成 String
值。在第二个示例中,用表达式来设置数值:将页面作用域内名为 square
的变量赋值为名为 x
的请求参数的值的平方。
清单 10. <c:set> 操作示例
<c:set var="timezone" scope="session" value="CST"/>
<c:set var="square" value="${param['x'] * param['x']}"/>
|
您还可以将限制了作用域的变量的值指定为 <c:set>
操作的主体内容,而不是使用属性。使用这种方法,您可以重新编写清单 10 中的第一个示例,如清单 11 所示。此外,正如我们马上可以看到的, <c:set>
标记的主体内容本身也可以使用定制标记。 <c:set>
主体内生成的所有内容都将作为一个 String
值赋给指定变量。
清单 11. 通过主体内容指定 <c:set> 操作的值
<c:set var="timezone" scope="session">CST</c:set>
|
JSTL core 库包含第二个用于管理限制了作用域的变量的标记 ― <c:remove>
。顾名思义, <c:remove>
操作是用来删除限制了作用域的变量的,它获取两个属性。 var
属性指定待删除变量的名称, scope
属性是可选的,它表示待删除变量来自哪个作用域,缺省为 page
,如清单 12 所示。
清单 12. <c:remove> 操作示例
<c:remove var="timezone" scope="session"/>
|
输出
尽管 <c:set>
操作允许将表达式结果赋给限制了作用域的变量,但开发人员通常会希望只显示表达式的值,而不存储它。JSTL <c:out>
定制标记承担这一任务,其语法如清单 13 所示。该标记对由其 value
属性指定的表达式进行求值,然后打印结果。如果指定了可选属性 default
,那么,在对 value
属性的表达式求值所得结果为 null
或空 String
的情况下, <c:out>
将打印其值。
清单 13. <c:out> 操作的语法
<c:out value="
expression" default="
expression" escapeXml="
boolean"/>
|
escapeXml
属性也是可选的。它控制当用 <c:out>
标记输出诸如“<”、“>”和“&”之类的字符(在 HTML 和 XML 中具有特殊意义)时是否应该进行转义。如果将 escapeXml
设置为 true,则会自动将这些字符转换成相应的 XML 实体(此处提到的字符分别转换成 <
、 >
和 &
)。
例如,假定有一个名为 user
的会话作用域变量,它是一个类的实例,该类为用户定义了两个特性: username
和 company
。每当用户访问站点时,这个对象被自动分配给会话,但直到用户实际登录后,才会设置这两个特性。假定是这种方案,请考虑清单 14 中的 JSP 片段。在用户登录之后,这个片段将显示单词“Hello”,其后是他/她的用户名和一个惊叹号。但是,在用户登录之前,由这个片段生成的内容则是短语“Hello Guest!”。在这种情况下,因为 username
特性还有待初始化,所以 <c:out>
标记将转而打印出 default
属性的值(即字符串“Guest”)。
清单 14. 带缺省内容的 <c:out> 操作示例
Hello <c:out value="${user.username}" default=="Guest"/>!
|
接下来,考虑清单 15,它使用了 <c:out>
标记的 escapeXml
属性。如果在这种情况下已经将 company
特性设置成 Java String
值 "Flynn & Sons"
,那么,实际上该操作生成的内容将是 Flynn & Sons
。如果这个操作是生成 HTML 或 XML 内容的 JSP 页面的一部分,那么,这个字符串中间的“&”符号最终可能被解释为 HTML 或 XML 控制字符,从而妨碍了对该内容的显示或解析。但是,如果将 escapeXml
属性值设置成 true
,则所生成的内容将是 Flynn & Sons
。浏览器或解析器不会因在解释时遇到这种内容而出问题。假定 HTML 和 XML 是 JSP 应用程序中最常见的内容类型,所以 escapeXml
属性的缺省值是 true
就不足为奇了。
清单 15. 禁用转义的 <c:out> 操作示例
<c:out value="${user.company}" escapeXml=="false"/>
|
用缺省值设置变量
除了简化动态数据的显示之外,当通过 <c:set>
设置变量值时, <c:out>
指定缺省值的能力也很有用。正如 清单 11 所示,用来赋给限制了作用域的变量的值可以指定为 <c:set>
标记的主体内容,也可以通过其值属性来指定。通过将 <c:out>
操作嵌套在 <c:set>
标记的主体内容中,变量赋值就可以利用其缺省值能力。
清单 16 中说明了这种方法。外部 <c:set>
标记的行为非常简单:它根据其主体内容设置会话作用域 timezone
变量的值。但是,在这种情况下,主体内容是通过 <c:out>
操作生成的。这个嵌套操作的值属性是表达式 ${cookie['tzPref'].value}
,它尝试通过 cookie
隐式对象返回名为 tzPref
的 cookie 值。( cookie
隐式对象将 cookie 名称映射到相应的 Cookie
实例,这意味着必须通过对象的 value
特性使用点运算符来检索储存在 cookie 中的实际数据。)
清单 16. 合并 <c:set> 和 <c:out> 以提供缺省变量值
<c:set var="timezone" scope=="session">
<c:out value="${cookie['tzPref'].value}" default=="CST"/>
</c:set>
|
但是,请考虑以下情况,用户是第一次尝试使用这段代码的 Web 应用程序。结果是,请求中没有提供名为 tzPref
的 cookie。这意味着使用隐式对象的查找将返回 null
,在这种情况下整个表达式将返回 null
。因为对 <c:out>
标记的 value
属性求值的结果是 null
,所以 <c:out>
标记会转而输出对其 default
属性求值的结果。在这里是字符串 CST
。因此,实际的结果是将 timezone
限制了作用域的变量设置成用户的 tzPref
cookie 中存储的时区,或者,如果没有,则使用缺省时区 CST
。
|
EL 和 JSP 2.0
目前,表达式语言仅可用于指定 JSTL 定制标记中的动态属性值。但 JSTL 1.0 表达式语言的一个扩展已经被提出,会把它包括到 JSP 2.0 中去,眼下正在进行最后评审。这个扩展将允许开发人员通过自己的定制标记来使用 EL。页面作者将可以在目前允许使用 JSP 表达式的任何地方使用 EL 表达式,譬如将动态值插入模板文本中: <p>Your preferred time zone is ${timezone}</p> 。
这个 JSP 2.0 功能(就象 JSTL 本身一样)将支持页面作者进一步减少对 JSP 编制脚本元素的依赖,从而改进 JSP 应用程序的可维护性。
|
|
结束语
EL(与四个 JSTL 定制标记库提供的操作结合起来)允许页面作者不使用脚本元素即可实现表示层逻辑。例如,对比本文开头 清单 1 中的 JSP 代码和清单 17 中显示的通过 JSTL 实现的同样功能。(JSTL core
库中其余的标记,包括 <c:choose>
及其子标记,将在本系列的下一篇文章中讨论。)尽管显然执行了条件逻辑,但是 JSTL 版本中没有 Java 语言源代码,并且标记之间的关系(尤其是关于嵌套需求)对于任何精通 HTML 语法的人都应该是熟悉的。
清单 17. 合并 <c:set> 和 <c:out> 以提供缺省变量值
<c:choose><c:when test="${user.role == 'member'}">
<p>Welcome, member!</p>
</c:when><c:otherwise>
<p>Welcome, guest!</p>
</c:otherwise></c:choose>
|
通过提供大多数 Web 应用程序常用功能的标准实现,JSTL 有助于加速开发周期。与 EL 结合起来,JSTL 可以不需要对表示层程序编写代码,这极大地简化了 JSP 应用程序的维护。
参考资料
此文原出于AJAX Patterns网站的一篇《Ajax Frameworks》的wiki文章,很早前我就注意到,后来在国内也有人翻译了,不过最近发现此wiki还是在不断添加维护中,截止此文发布前,作者又添加了好几个新诞生的AJAX开发工具,所以我决定重新翻译一遍,并且时常注意原文发布状态,一有新的内容立马也翻译过来,做到同步:)
此翻译稿很大一部分内容出自国内出现的那个先前版本,我只是对新加入的几项进行了翻译,并且对我熟悉的产品项着重介绍了一下,以后我会抽时间收集文中提到AJAX工具相关的文章,尽量将内容介绍和功能点评做到全面详细点。所以请关注和准备用AJAX做开发的朋友关注这篇文章,我会时常更新的。原文因为是由一个wiki系统维护,所以在所难免出现参差不齐,风格上也有不统一的情况,翻译时我也是参照原文原封不动的挪了过来,以后我会抽时间改良下。
翻译正文
基于浏览器的应用框架一般分为两种:
- Aplication frameworks:提供了浏览器功能,但其最著名的还是在于通过窗口生成组件建立桌面GUI。
- Infrastructural frameworks:提供基本的框架功能和轻便式浏览器端操作,让开发者去创建具体应用,主要功能包括:
- 基于XMLHttpRequest组件的浏览器交互功能
- XML解析和操作功能
- 根据XMLHttpRequest的返回信息进行相应的DOM操作
- 一些特殊情况下,和其他的浏览器端技术如Flash(或Java Applets)等集合到一起应用
基于服务器端的应用框架通常以下面两种方式工作(尽管它们根据不同的语言进行了分类)
- HTML/JS Generation(HTML/JS生成):通过服务器端生成HTML和JS代码在传递给浏览器端进行直接运行
- 远程交互:JavaScript调用服务器端函数(例如调用Java函数)并返回给JavaScript的回调句柄,或者请求服务器端数据信息,例如Session信息,数据库查询等。
目录
1.1 Bindows1.2 BackBase1.3 DOJO1.4 Open Rico1.5 qooxdoo1.6 Tibet1.7 AJFORM2.1 AjaxCaller2.2 Flash JavaScript Integration Kit 2.3 Google AJAXSLT2.4 HTMLHttpRequest2.5 Interactive Website Framework 2.6 LibXMLHttpRequest2.7 MAJAX2.8 RSLite2.9 Sack2.10 Sarissa2.11 XHConn3.1 Cross-Platform Asynchronous INterface Toolkit3.2 SAJAX3.3 Javascipt Object Notation (JSON) and JSON-RPC3.4 Javascript Remote Scripting (JSRS)3.5 Bitkraft for ASP.NET4.1 WebORB for Java4.2 Echo 24.3 Direct Web Remoting (DWR)4.4 SWATO4.5 AJAX JSP Tag Library4.6 AJAX Java Server Faces Framework5.1 CL-Ajax6.1 WebORB for .NET6.2 Ajax.NET6.3 ComfortASP.NET6.4 AjaxAspects7.1 AjaxAC7.2 JPSpan7.3 XAJAX8.1 Ruby On Rails
1. Pure Javascript: Application Frameworks
1.1 Bindows (成立于2003年)
Backbase是一个通过DHTML、JavaScript、CSS和HTML等技术强劲联合起来的一套完整的Windows桌面式的WEB应用程序解决方案。Bindows无需下载安装客户端支撑组件(如Java、ActiveX或Flash),仅需一个浏览器。纯OO的理念体现在Bindows任何地方,Bindows或许是笔者见过的最完整最强大的AJAX应用程序平台。
Bindows是商业程序的,使用了来自于MB的技术(总部位于GA USA,主要开发中心在瑞典,成立于2002年)。
Bindows框架提供的功能和特性有:
- 基于面相对象技术的类和API
- 一套完整的Windows桌面系统,支持各种特性窗口模式,包括菜单、表单、表格、滑动条、测量仪器窗口和其他一些Windows窗口特性支持。
- 是开发zero-footprint(零空间占用)SOA客户端应用程序首选工具包
- 本机的XML,SOAP和XML-RPC支持
- 单用户到企业级开发的支持
- 内建的完美的AJAX支持
Bindows开发环境:
- 支持企业级规模的项目开发
- 跨浏览器、跨OS平台的支持
- 不受服务器结构限制
- 良好的与新的、现有的资源互操作性
- 统一的开发接口
1.2 BackBase (成立于2003年)
BackBase是一个完整的浏览器端框架,提供了丰富的浏览器操作功能,以及对.NET和JAVA平台的集成。
商业化产品,来自于Backbase B.V(总部在Amsterdam,成立于2003年)。
1.3 DOJO (开发中,成立于2004年9月)
DOJO提供完整的轻量级窗口组件和浏览器-服务器消息映射支持
1.4 Open Rico (开发中;成立于2005年5月;基于早期的一个proprietary 框架)
Open Rico是一个支持Ajax架构和用户交互的多用途框架。
- 一个XMLHttpRequest response能被一个或多个的DOM对象,或者Javascript对象调用。
- 支持拖拽操作
- 支持基于AJAX的动画模式,如缩放和变换等
- 基于Behaviors的操作库
- 使用指南,由RussMirimar的Yonah提供
- 开源。源于Sabre航空公司解决方案,由Bill Scott,Darren James及另外一些人维护。
1.5 qooxdoo (开发中; 成立于2005年5月)
qooxdoo,是另一个发展迅猛的应用框架,提供广泛的UI支持,正在开发基础架构等特性。
- 基础结构特性:
- 能轻易的捕获和操纵DOM事件
- 支持调试
- 支持一个时间操作的Timer类
- Getter/Setter支持
- UI:
- 窗口组件库和框架
- 界面布局管理
- 图像缓存和透明PNG图片处理
- 开源(LGPL).
1.6 Tibet (开发中; 创建于2005年6月)
Tibet提供了大量的易移植和完整的JavaScript API,通过这些可以快速生成大量的客户端代码,Tibet自称是企业级AJAX。
- 远程脚本调用封装在XMLHttpRequest中
- URI支持
- 支持所有的HTTP事件,不再仅仅是GET和POST
- 低级的协议-File://和WebDav也可以当作HTTP正常使用
- Web Services调用支持,包括SOAP、XML-RPC等等
- 大型的Javascript对象库
- 多种多样的XML操作支持
- IDE和开发工具
- 开源协议(OSI)
1.7 AJFORM (创建于2005年6月)
AJFORM是一个极易上手的AJAX框架,被用来编写入门级的AJAX代码,提供有以下功能:
- 三步安装
- 自动支持任意HTML表单元素
- 几乎无需编码即可实现AJAX
2 Pure Javascript: Infrastructural Frameworks
2.1 AjaxCaller(创建于2005年5月,目前是Alpha版)
AjaxCaller是一个具有多线程安全访问的XMLHttpRequest组件,主要针对Ajax开发新手,目前仍处于alpha开发阶段,仅在AjaxPatterns的在线搜索范例中使用了这个程序。
- 用明文或者XML结构的数据实现和服务器的交互(GET/POST/PUT/DELETE)
- 支持XMLHttRequest对象的构析(销毁对象,C++支持内存对象的构析操作)
- 支持Response的高速缓存(尚在计划中)
- 简单的库文件代码易于新手学习使用,并且支持脚本调试
- 开源协议
2.2 Flash JavaScript Integration Kit
The Flash JavaScript Integration Kit可以使Flash和Javascript脚本实现相互集成。
- 可以实现在JavaScript中调用Flash ActionScript脚本,反之亦然。
- 几乎支持双方主要数据类型的在不同环境中的传递调用。
- 开源协议,有几个Flash开源爱好者维护。
2.3 Google AJAXSLT (2005年6月发行)
Google AJAXSLT,是一个Javascript框架,用来执行XSLT转换以及XPath查询。
- 目前在Google Map上就使用了这个。
- 开源协议(BSD)
2.4 HTMLHttpRequest(Beta版;创建于2005年)
HtmlHttpRequest最大的特点就是运用XMLHttpRequest对象和标准HTML标签IFrame来实现最大限度的跨浏览跨平台的AJAX支持,其原理是在支持XMLHttpRequest的浏览器上调用XMLHttp,如果不支持,就用IFrame来模拟实现异步交互。
- 目前支持的浏览器:IE6/Win, IE5.5/Win, IE5/Win, IE4/Win, Mozilla/Win, Opera7/Win, Safari/Mac, IE5/Mac
- 尚未测试的浏览器:IE4/Mac, Mozilla/Mac, Opera/Other, Konqueror/Linux。
- 开源协议(LGPL)
2.5 Interactive Website Framework (创建于2005年)
Interactive Website Framework定位在浏览器中支持各种各样的AJAX基础应用的开源项目。自称是通过JavaScript、CSS、XML和HTML实现高性能的交互式WEB框架,包括一个可定制易读的XML解析器。实际上,IWF是一个AJAX的基础框架,并且还包括一些通用脚本代码。
- 实现了线程安全的XMLHttpRequest
- 对XML Document进行封装,以便创建更具有可读性的代码:
var node = doc.groceries.frozen[0].pizza[0].size;
封装后的数据读取
var node = doc.documentElement.firstChild.firstChild.getAttribute("size");
原始的DOM操作读取
- 开源协议
2.6 LibXMLHttpRequest (2003年6月发布)
libXmlRequest是一个小型XMLHttpRequest封装包
- 用getXML()和postXML()两个事件简化XMLHttpReuqest调用
- 支持XMLHttpRequest对象池
- Response缓存处理
- 源码可以使用,但是有版权保护。
2.7 MAJAX
MAJAX是另一个非常小巧的HttpRequest封装包,为收发字符型信息提供简单接口,并为每步动作设置回调界面。
2.8 RSLite (x)
RSLite是一个XMLHttpRequest封装组件,作为Brent Ashley的JSRS(JavaScript Remote Scripting)其中的一部分功能单独发布。详情可以看JSRS的介绍
2.9 Sack(开发中,成立于2005年5月)
Sack也是一个很有名字的微型XMLHttpRequest封装包。调用者可以自定义回调函数或者是DOM对象。借助于回调DOM对象,可以把Response回来的数据直接以文本的方式嵌入DOM中。
2.10 Sarissa (发布于2003年2月)
Sarissa是一个JavaScript API,封装了在浏览器端独立调用XML的功能。
- 可移植的XMLHttpRequest对象创造
- 可移植的XPath查询
- 可移植的DOM操控
- 可移植的XSLT
- 可移植的XML序列化
- 开源协议(GPL2.0和LGPL2.1)
2.11 XHConn (2005年4月发布)
XHConn也是一个小型的XMLHttpRequest封装库。笔者也使用改良过的XHConn,其特点就是调用简单,代码也清晰易读。
- 例子:
new XHConn().connect("mypage.php","POST","foo=bar&baz=qux",fnWhenDone);
- 开源协议许可
3 Server-Side: Multi-Language
3.1 Cross-Platform Asynchronous INterface Toolkit (2005年5月)
CPAINT是一个真正的同时支持PHP和ASP/VBScript脚本的AJAX和JSRS工具包。CPAINT在后台提供你需求的AJAX和JSRS代码,并自动返回到浏览器端相应的Javascript脚本代码,这种方式易于实时反馈需求的WEB应用程序。
- 支持PHP和ASP
- 所有功能函数都在统一的JavaScript文件中
- 支持远程脚本和XML
- 支持本地和远程函数调用
- 可以创建单个或多个XMLHttp对象
- 返回给后台的数据即可以是文本也可以是XML/DOM文档对象
- 支持POST和GET
- 用服务端代理的方式实现远程函数和数据的访问操作
- 大部分浏览器中测试正常使用
- 在GNU、GPL、LGPL开源协议保护下发行
3.2 SAJAX (2005年3月)
SAJAX的实现方式很独特,例如:调用一个javascript方法x_calculateBudget(),将先把响应传到服务器并调用一个Java calculateBudget()方法,然后以javascript方式把值返回到x_calculateBudget_cb()中。SAJAX的名气不错,估计很多人都听过甚至用过,不过缺点就是它的这套映射理论感觉较繁锁,远不如一些轻量级的封装库好用,不过SAJAX最大的特点就是支持的平台丰富,几乎囊括了WEB下常用的编程语言和平台
- 很方便从JavaScript函数映射到服务端代理操作
- 支持多种平台(ASP/ColdFusion/Io/Lua/Perl/PHP/Python/Ruby)
- 开源协议
3.3 Javascipt Object Notation (JSON) and JSON-RPC
JSON是一个"face-free" XML,而JSON-RPC是一种远程交互协议,类似于XML-RPC,对JavaScript支持较强
3.4 JavaScript Remote Scripting(JSRS)(2000年)
JSRS,较经典的远程脚本访问组件,支持将客户端数据通过服务器做代理进行远程的数据/操作交互。
- 支持的浏览器:IE4+,NS4.x,NS6.x,Mozilla,Opera7和Galeon。
- 服务器端脚本语言支持:ASP,ColdFusion,PerlCGI,PHP,Python和JSP(servlet)。
- 开源协议。由Brent Ashley提供支持。
3.5 Bitkraft for ASP.NET
Bitkraft是个基于(.NET)Web框架的CLR(公共语言运行库),允许用独特的方式创建和操作分布式Web内容。用C#编写,运行在微软的.NET 1.1和Mono框架下,无缝式的客户端-服务器响应方式是它的最大特点。Bitkraft没有使用XML组织数据,而是用JSON代替。
- 支持的浏览器: IE5+, Firefox1+, NS6
- 服务器端要求:ASP.NET, Mono XSP, Cassini, Apache (modMono) .NET Framework 1.1+
- 事件驱动
- 支持同步和异步的远程代理
- 客户端支持所有的.NET类型或自定义类对象映射到JSON中
- 用JSON取代XML
- 免费,开源许可协议
4 Server-Side: Java
4.1 WebORB for Java (2005年8月)
WebORB for Java是一个开发AJAX和基于Flash的富客户端应用程序的开发平台。在线例子
- WebORB包括一个富客户端开发类库。提供简单的在线式API用来绑定或者调用任何Java对象、XML Web Services和EJB
- 支持异步或同步的事件驱动
- 不需要在服务端修改任何代码,不需要自定义方法或属性、变量等。不要求设计时指定代理等。
- 同步调用不需要回调,异步调用需要一个回调方法。
- 客户端可以向服务端请求指定的活动方式,不需要任何编程就可以把处理结果轻易的转变为状态。
- 提供一个特定API来处理数据库查询结果-服务器代码能返回DataSet或者DataTable,而客户端以一个类似于RecordSet的JavaScript对象来显示这个结果。该对象提供检索列名和行数据的方法。
- 支持数据分页技术。客户应用程序能检索页面中的数据。
- 支持以参数的方式返回所有服务期端数据类型,如primitives, strings, complex types, arrays, native .net collections, remote references
- 目前有两个版本:标准版(免费),专业版(商业许可)
4.2 Echo 2 (2005年3月)
Echo 2允许你用纯Java语言编写AJAX程序。 Demo.
- 自动生成HTML和Javascript代码
- 用XML在客户端-服务端传递消息
- 如果愿意支持自定义Javascript组件
- 开源协议(Mozilla Public License or GNU LGPL)
4.3 Direct Web Remoting (DWR) (2005)
Direct Web Remoting可以在Javascript代码中直接调用Java方法的应用框架
- 类似于SAJAX,可以把Javascript中的请求调用转递到Java方法中并将执行结果返回给Javascript
- 可以和任何Web框架一起使用,如Struts、Tapestry等等
- 开源(Apache),目前该产品被加入到WebWork中
4.4 SWATO (2005)
SWATO是一套可重用的和良好集成的Java/JavaScript库,它实现了一种更容易的方式来改变你的web应用程序的交互,通过AJAX方式实现。
- 服务端Java库可以非常容易的部署到所有Servlet2.3+兼容的容器中
- 客户端Javascript库可以在所有支持XMLHttpRequest的浏览器中使用
- 使用JSON技术在服务端组织POJO数据,这样你可以在任何Javascript环境中(HTML、XUL、SVG)访问这些远程数据,这种方式很容易通过硬编码或者某种成熟的Javascript库集成到当前应用中
- 提供一个简单接口使你能在Javascript中调用远程的POJO数据
- 使用<servlet>和<filter>灵活的在web.xml中进行配置,并且可以集成(不是必须)到你的Spring框架中
- 提供了几个可帮助你快速开发web应用程序的组件(如自动完成的文本框,在线表单,在线列表等等)
4.5 AJAX JSP Tag Library
The AJAX JSP Tag Library是一组JSP标签库,用来AJAX程序开发。可以在J2EE下无需Javascript就能轻松开发AJAX模式的Web Form。标签库为比较通用的AJAX功能提供了5个标签:
- autocomplete: 用户在文本框中输入字符,自动从指定的数据中匹配用户输入的字符,类似于Google Suggest
- callout:可以为A标签加入气泡式的消息提示框,不过是实时的服务端取出数据
- Select/dropdown:类似于联动菜单,比如地州市的联动下拉框
- toggle:开关闸按钮,比如在一个hidden表单域中存储true和falsh,同时显示相应的img图像
- update field:更新数据,也就是无刷新提交了。
4.6 AJAX Java Server Faces Framework
The AJAX-JSF用来把任意的JSF应用程序转变为AJAX应用程序
Server-Side: Lisp
5.1 CL-Ajax
CL-Ajax实现Javascript直接调用服务端Lisp
- 生成可带参数的函数
- 可以回调Javascript函数或者DOM对象
- 可以集成到SAJAX中
- 开源许可
6 Server-Side: .NET
6.1 WebORB for .NET (2005年8月)
WebORB for .NET是一个用.NET和XML Web Services方式开发AJAX和基于Flash的富客户端应用程序(在线例子)
- WebORB包括一个富客户端开发类库。提供简单的在线式API用来绑定或者调用任何.NET对象、XML Web Services
- 支持异步或同步的事件驱动
- 不需要在服务端修改任何代码,不需要自定义方法或属性、变量等。不要求设计时指定代理等。
- 同步调用不需要回调,异步调用需要一个回调方法。
- 客户端可以向服务端请求指定的活动方式,不需要任何编程就可以把处理结果轻易的转变为状态。
- 提供一个特定API来处理数据库查询结果-服务器代码能返回DataSet或者DataTable,而客户端以一个类似于RecordSet的JavaScript对象来显示这个结果。该对象提供检索列名和行数据的方法。
- 支持数据分页技术。客户应用程序能检索页面中的数据。
- 支持以参数的方式返回所有服务期端数据类型,如primitives, strings, complex types, arrays, native .net collections, remote references
- 目前有两个版本:标准版(免费),专业版(商业许可)
6.2 Ajax.NET (2005年3月)
Ajax.NET是首家支持各种方式通过Javascript访问服务端.net的免费库
- 类似于SAJAX,能把Javascript请求发送到.NET方法,服务端回传给Javascript,甚至包括串行化自定义类。
- 可以在Javascript中访问Session和Application数据
- 缓存查询结果
- 免费使用源代码
- 无需更改源代码,允许给Ajax.NET添加和修改方法和属性
- 所有类支持Javascript客户端返回数据,可以在JavaScript中使用DataSet:res.Tables[0].Rows
- 使用HtmlControls组件访问和返回数据
- 页面无需重载,用事件代理(数据访问层)
- 因为只提供一个调用接口方法,所以服务端CPU占用非常少
6.3 ComfortASP.NET (2005年8月)
ComfortASP.NET可以让开发者在纯.NET下开发类似AJAX(DHTML,JavaScript,XMLHttp)特性的应用程序。
- 快速应答
- 减少HTML传输
- 减少页面重载
- 无闪烁的浏览器内容更改
- AJAX用户体验,
6.4 AjaxAspects (2005年8月)
AjaxAspects是个可以用Javascript调用服务端WebService事件的引擎
- 用标准的SOAP和WSDL进行服务端-客户端通信
- 用简单的类型和XML对象支持带参数的返回值
- 缓存支持
- 动作队列
- 免费使用,开源协议
7 Server-Side: PHP
7.1 AjaxAC (2005年4月)
AjaxAC用一个单独类封装了完整的应用程序功能
- 所有的功能集成在自包含的类中(另外附带一些Javascript库)
- 调用PHP文件或者HTML页面非常简易,只需创建App类后把类引用传递给需要调用的Javascript对象或者HTML元素即可。
- 捕获Javascript事件
- 可以自定义配置数据,并且支持运行时参数更改
- 无需再Javascript代码中夹杂凌乱的Html代码,所有事件都是被动态附加上的
- 由于以上两个优点,所以支持良好的模版引擎
- 容易Hook到PHP类和MySql数据已返回给自己的request
- 能够容易的用Javascript建立窗口模式应用程序。
7.2 JPSpan
JPSPAN通过Javascript直接调用PHP中的函数。
7.3 XAJAX
XAjax通过Javascript直接调用PHP中的函数
- 支持用Javascript调用PHP脚本
- 开源许可协议
8 Server-Side: Ruby
8.1 Ruby On Rails
Ruby On Rails是一个支持AJAX的完整Web框架,使用Ruby语言编写,严格按照MVC结构开发。
- 当Ajax出现的时候Rails还处于其发展的早期,因此Ajax可能逐渐成为Rails框架的核心。
- 生成浏览器中大多数/全部的Window应用组件和动画的Javascript脚本。
- 支持服务器端调用。
- 队列支持
- 开源许可
|
|
.NET大局观( 第2版) |
David Chappell 译者:荣耀 / 2006年11月 / 电子工业出版社 / 39元 / |
学什么都要先来一个大局把握 |
|
|
|
Programming C#中文版 |
Jesse Libert 译者:刘基诚 / 2006年7月 / 电子工业出版社 / 65元 / 179*233 / |
O'Reilly的 |
|
|
|
C#入门经典(第3版) |
(美)Karli Watson Christian Nagel 等著 / 05 1 2006 12:00AM / 清华大学出版社 / 98元 / 185×260 / |
Wrox的 |
|
|
|
C#设计模式(影印版) |
(美)麦斯科(Metsker,S.J.)著 / 07 1 2006 12:00AM / 中国电力出版社 / 49元 / |
对翻译没信心,有影印版可选:) |
|
|
|
C#设计模式 |
(美)麦斯科 著,颜炯 译 / 07 1 2005 12:00AM / 中国电力出版社 / 42元 / 787*1092 1/16 / |
|
|
|
|
.NET精简框架程序设计:C#版 |
(美)姚(Yao,Y.),(美)杜朗(Durant,D.)著,刘新军,盛泉,李辛鹤 译 / 06 1 2006 12:00AM / 电子工业出版社 / 80元 / |
讲精简框架最好的书 |
|
|
|
C#高级编程(第3版) |
(美)罗宾逊,(美)内格尔 著,李敏波 翻译 / 06 1 2005 12:00AM / 清华大学出版社 / 128元 / 787*1092 1/16 / |
第三版有一些重点章节的连载 |
|
|
|
C#高级编程(第4版) |
Christian Nagel Bill Evjen Jay Glynn等著 李敏波翻译 / 2006年10月 / 清华大学出版社 / 128元 / |
新版本 |
|
|
|
C# Primer中文版 |
Stanley B.Lippman/著 侯捷 陈硕/译 / 09 1 2003 12:00AM / 华中科技大学出版社 / 45元 / 787*1092 1/16 / |
书经典,就是翻译有争议 |
|
|
|
C#精髓 |
刘基诚/译 / 2001年8月 / 中国电力出版社 / 29元 / 787*1092 1/16 / |
除了版本老外,几无瑕疵 |
|
|
|
Windows Forms程序设计 |
[美]Chris Sells 著,荣耀,蒋贤哲 译 / 09 1 2004 12:00AM / 人民邮出版社 / 65元 / 787*1092 1/16 / |
WinForms高端 |
|
|
|
C#程序设计 |
[美]佩佐尔特 著,杨涛等 译 / 04 1 2004 12:00AM / 机械工业出版社 / 30元 / 787*1092 1/16 / |
又一本C#入门好书 |
|
|
|
C#技术揭秘 |
(美)Tom Archer 等著;马朝晖 译 / 07 1 2003 12:00AM / 机械工业出版社 / 69元 / 787*1092 1/16 / |
C#入门好书,可惜就是版本老了 |
|
EJB用自己的悲剧人生警告Sun,不可对新技术的推广掉以轻心,但Sun还是再次犯下同样的错误。与Microsoft和Intel成功的商业推广策略截然不同的是,Sun 完全没有估量到,JSP作为一项成功技术的价值和影响力,在JSF的推广上,出现了令人痛心的失误。如果JSF以JSP3.0的名义推出,那么JSF的日子恐怕要比现在好过得多。
1. JSF没有站在JSP巨人的肩膀上
前文说过,EJB是Sun的伤心往事,它用自己的悲剧人生,警告Sun,不论技术也好,商务也好,凡事应该有一个全盘的规划,再也不能想到什么是什么了。一项好的技术,如果不加以适当的推广,最后可能逃脱不了被束之高阁的命运,大把的资金投入,自然也难免竹篮打水一场空。
当然,如何进行商业运作,Sun比我高明得多了,似乎轮不到我在这里说三道四,不过,Java已经不单单属于Sun了,Java已经成为全世界的Java,所以,所有的Java程序员,都有发表自己意见的权利。未必都是真知灼见,但Java世界就是因为有这些不同声音的存在,才显得无比的精彩。
其他的技术我不敢妄加评论,就JSF这项技术而言,Sun的商业策略实在是不敢恭维。在JSP已经深入人心的时候,为什么不继续沿用JavaServer Pages的这个如雷贯耳的名称,而要标新立异地推出一个JavaServer Faces的怪物呢?你看人家Microsoft,在ASP流行开来之后,推出ASP.NET,是多么的顺理成章。
暂且不论这两项技术的区别有多大,就冲着似曾相识的名称,Microsoft就让大批的ASP用户,自觉自愿地加入ASP.NET的阵营。没有任何抵抗,Microsoft兵不血刃,不费一枪一弹就完成了从ASP向ASP.NET的过渡。
同样的策略Intel也曾使用过。第一代“奔腾”芯片推出后,获得了巨大的成功,“奔腾”一词,一时间名噪天下。Intel看到了这一点,并且立刻明白了该怎么做,所以,当下一代芯片制造出来时,Intel完全没有在命名上费什么脑筋,直接冠以“奔腾II”的名字,马上令一大批“奔腾”的爱好者趋之若骛。此后,“奔腾III”“奔腾IV”,Intel将“奔腾”一词的所有油水都榨干了,才心满意足地构思下一个名字。
相比之下,Sun则完全没有估量到一项成功技术的价值和影响力。令多少对手眼红的JSP背后庞大的用户群,Sun却视若无物,不知道Sun是没有看到这一点呢,还是不屑利用这一优势。
不管怎样,当JSP如日中天时,不知借JSP之势点燃JSF的大火,反而暴殓天物,另起炉灶,Sun简直就是在自毁JSF的前程。也许Sun主观上并不存在这样的故意性,但客观上造成了这样一种局面,也是不可原谅的失误。
2. JSF唯有一切从头再来
如果JSF没有叫做JSF,而是叫做JSP 3.0,情形会是如何呢?
可以想见,首先,大批的JSP爱好者会蜂拥而至,庆贺JSP的新版本;然后,一批“牛人”们很快发现,JSP的新版本,引入了他们期待已久的组件模型和事件驱动模式,JSP终于有了和ASP.NET抗衡的资本;接下来,“牛人”们必定奋笔疾书,以超凡的热情四处撒播JSP 3.0的种子。
于是,网络上、论坛里,到处充斥着为JSP 3.0唱赞歌的文章,JSP 3.0成为炙手可热的名词,而Sun专家们借JSP 3.0的名义推销的JSF组件模型和事件驱动模式,说不定现在已经成为Java Web编程的新贵。
将JSF以JSP3.0的名义发布,绝非戏言,是完全可行的。从技术上来看,JSF是建立在Servlet/JSP基础之上的,和JSP有着天然的联系,将JSF作为JSP3.0的一个崭新的扩充部分,随JSP3.0一起发布,即符合从JSP到JSF的平滑过渡的要求,同时也能满足程序员对于JSP3.0新特征的期待。
实际上,JSF和JSP融合的趋势越来越明显,例如在JSF1.2版本之前,JSP和JSF各有一套独立的表达式语言(EL,Expression Language),而从JSF1.2开始,这两套不同的表达式语言已经统一为Unified EL,并且从JSF和JSP规范中分离出来,自成一体。所以,让JSF搭上JSP的快车,一起前进,其实是很自然的事。
可惜,这些只能发生在Sun的梦里了。JSP与JSF,一字之差,Sun将一项颇具潜力的Java Web框架技术,亲手打回到娘胎中,让其以一个初生婴儿的身份,光着身子降临到Java Web世界。这个本来可以衣着光鲜地与ASP.NET一起独步江湖的汉子,现在唯有恨恨地抛下一句“君子报仇,十年不晚”,然后黯然离去了。
现在,有很多C/C++程序员总是自命不凡,看不起其他开发人员。其实,或许别人更看不起他呢!
学生时代,我也曾醉心于C/C++,但时至今日,始终无法写出无懈可击的C++代码,所以我始终认为我不会C/C++。这些年,我一直在寻找编写C++代码的最佳模式。但是,老实说,我还没有见到过哪个称得上高手的C++程序员,也没有见到过写得Very good的C/C++代码。C/C++代码总是丑陋不堪,BUG丛生!
我用C语言编程已经超过20年了。我写过C语言的编译器、C语言的调试器、用C开发的其他语言、游戏、客户端程序和服务器程序,你说吧!还有什么是我没写过的。还有我的书架上充斥着折了角的K&R和Steele的书。我太了解C语言了,但是,我讨厌他。十分讨厌!
当我读到一篇博客,题目是“为什么每个程序员都应该学习C语言?”时,我真是鸡皮疙瘩满地。如果你真的是个专业的程序员的话,你肯定觉得这是个天大的笑话,尽管作者的本意也许不是这样的。这篇反驳的文章有点意思,但是还是没有抓住本质。所以我展开了说一下。有以下5个原因来说明,为什么那些会C语言,并且使用C语言的程序员,现在不但应该去用别的语言,而且应该忘记他们学习C语言过程中的那些烦人的东西。
1、内存分配
仅仅关于这一点我就能写整整一篇文章了,也许能写一本书,甚至还有可能写出能够塞满图书馆技术书籍那块,那么多的内容。内存分配和存储单元分配的存在确确实实是个大麻烦。你要不就是分配太少的内存不够用,要不就是分配了太多内存浪费掉。这里的问题就是:怎么把它初始化为零呢?还是干脆就不初始化它。但最挠头的步骤还是释放内存。所有已有的工具包都会帮助你确认,你是否已经释放了之前分配的每一位的内存,在释放完之后是否永远不使用它,并且会阻止你,永远不要释放它第两次。更严重的是,分配内存和释放内存在C语言中都是很慢的,非常慢。使用内存分配时,要考虑的各种特殊情况,我真是连想都不愿意去想,只要问题(对象)的大小合适,我更愿意使用栈空间或者事先分配的结构空间。如果这么做的话,我就有更值得烦恼的事了。话说回来,发明垃圾处理器那人真应该得诺贝尔奖。
2、多线程
我过去是喜欢C语言的,真的。直到我开始用C开发并维护多线程的服务器。在为连接相冲突的线程保护数据方面,C语言没有为程序员提供那怕一点点的帮助。你在使用单线程的日子里获得的每一个直觉、经验,用在多线程的时候都是错误的。至少JAVA有表示同步的关键字和备有证明文件(但是是个很奇怪的文件)的记忆体,但即使是这样,除非你使用新的javax.concurrent,否则也只能在那些巨大的平行摆放的机器们面前崩溃。回到C语言上:在模拟生产的环境下,坚持一个星期在数据中心调试一个死锁(这事真的发生过)。而JAVA却只需要Ctrl+Break!天哪!!!
3、指针
指针太难以控制了,太阴险了;我甚至没有委婉一点的方式去形容它。我生命中每年都有几个月被用来调试那些奇怪的指针问题。我过去常常努力获取所有的诀窍,比方说难以理解的构成符、联合体和偏移量,以及重用最后两位做标记,还有所有其他的诀窍。但我发现这么做根本不值得。其他语言的静态引用就可以解决了。
4、过早的优化
说到诀窍,你是否曾经浪费脑细胞去研究究竟*p++是不是比p[i]快?你是否曾经花时间去试着做点变化来代替乘法,或者去尝试使循环中的倒置运行更快的方法?还在为传递一个参数的速度和反对添加结构,并且传递它的速度一样而苦恼不已?停吧!算法是速度的关键,程序员的水平决定了他会使用那些算法。知道这一点能让你的程序更好,更快一点并且让你的脑袋少扭几个筋。好吧,有一些例子也许可以这样做的……不,你就别那么做就行了!
5、测试
你最喜欢的C的单元测试的工具是哪个?嗯…一个也想不到?单元测试一定是一点也不重要,是吧?或者是太麻烦了,很难跟上进度,浪费时间。你可以把这个时间用到更加有用的事情上,让它只占用工作时间的1%,那还比较合适。或者在数据中心,通过优化的没有标记的图形来调试这个仅仅由100个同时在线使用者引起的问题。
我本来应该继续再说一些原因的,但是5个现在就足够了;说完这些,现在感觉好点了。C以前是非常棒的…那是在1984年的时候。直到今天,那些用C写的新代码都让我感到惊喜…如果你让我比较的话,我觉得C++只是比C稍微好点。如果你想要学些老一点的语言,不妨尝试Forth,Lis,或者APL。这些老式的语言起码能教会你,用不同的而且优雅的方式去思考你的程序。
CVS 中文手册
CVS—协作版本系统 v1.12.12
本手册描述了如何使用和管理 cvs 版本 1.12.12.
CVS 实践 -----------------------
参考 -----------
displaytag的使用方法(用于数据表格的显示和功能控制)Displaytag1.1版本使用方法
一、 安装步骤
1. 下载displaytag-1.1-bin.zip后解压缩并将displaytag-examples-1.1.war中的WEB-INF/lib类包放入自己的web应用程序中的WEB-INF/lib目录下,并将WEB-INF/classes中的displaytag.properties放入到自己web应用程序中的WEB-INF/classes目录下。
2. 将displaytag-examples-1.1.war中的资源文件放置到与自己web应用程序同级的目录中,资源文件包括css,images,img三个文件夹下的所有内容。
二、 使用方法
1、 得到要显示的数据源
有四种范围
pageScope
requestScope (默认) <display:table name="test" >
sessionScope <display:table name="sessionScope.sessiontest" > 注意,这里要指定范围
applicationScope 同上
2、 全部数据显示
<% request.setAttribute( "test", new TestList(20, false) ); %>
<display:table name="test" ></display:table>
标签将遍历List里的每一个对象,并将对象里的所有属性显示出来。
name属性用来对应list对象的名称
3、 部分数据显示
<% request.setAttribute( "test", new TestList(20, false) ); %>
<display:table name="test" >
<display:column property="id" title="ID"/>
<display:column property="name" title="姓名" />
<display:column property="email" title="电子邮件"/>
<display:column property="url" title="网址"/>
<display:column property="money" title="Money"/>
</display:table>
property对应List里对象的属性(用getXXX()方法取得),title则对应表格表头里的列名。
4、 表格的样式定义
共有的表格样式为isis,its,mars,simple,report,mark五种,默认为isis
表格样式设定为mark后可以设定column的样式属性
<display:table name="test" class="isis" >
<display:column property="id" title="ID"/>
<display:column property="name" title="姓名" />
<display:column property="email" title="电子邮件" class="tableCellError"/>
<display:column property="url" title="网址"/>
<display:column property="money" title="Money"/>
</display:table>
通过class属性来指定所要应用的样式。
5、 数据的自动连接功能
如果显示的数据中包含emal和ur时,可以通过设定display:column里的autolink="true"来直接连接
<display:table name="test" >
<display:column property="id" title="ID"/>
<display:column property="name" title="姓名" />
<display:column property="email" title="电子邮件" autolink="true" />
<display:column property="url" title="网址" autolink="true"/>
<display:column property="money" title="Money"/>
</display:table>
6、 数据的排序
在需要排序的column里增加sortable="true"属性,headerClass="sortable"是指定显示的样式。
defaultsort="1" 默认第一个column排序
defaultorder="descending" 默认递减排序
<display:table name="test" defaultsort="1" defaultorder="descending">
<display:column property="id" title="ID" sortable="true" headerClass="sortable" />
<display:column property="name" sortable="true" headerClass="sortable"/>
<display:column property="email" />
<display:column property="status" sortable="true" headerClass="sortable"/>
</display:table>
7、 数据的动态连接
实现数据的动态连接有两种方法。第一种为使用标签库的属性值来设置连接地址,这种方法实现的动态连接比较简单,只能实现类似 xxx.jsp?id=1的连接样式。第二种方法为通过自定义一个Wrapper类继承TableDecorator来实现表格中动态连接的数据内容,这样就可以实现类似xxx.jsp?id=1&action=add的连接样式。
第一种动态连接使用方法:在<display:column/>里通过增加href、paramId、paramName、paramScope、paramProperty属性
href 基本的URL 地址
paramId 加在URL 地址后的参数名称
paramName 数据bean的名称,一般为null(即使用当前List里的对象)
paramScope 数据bean的范围,一般为null
paramProperty 数据bean的属性名称,用来填充URL 地址后的参数值
<display:table name="test">
<display:column property="id" title="ID" href="details.jsp" paramId="id" />
<display:column property="email" title="电子邮件"
href="details.jsp" paramId="action" />
<display:column property="url" title="网址"
href="details.jsp" paramId="id" paramProperty="email" />
</display:table>
第一列的连接地址为details.jsp?id=1
第二种动态连接使用方法:首先编写MyWrapper.java文件,代码如下
import org.displaytag.decorator.TableDecorator;
import com.module.DateModule; // DateModule为将来要在tag中进行显示的数据bean。
public class MyWrapper extends TableDecorator{
public MyWrapper ()
{
super();
}
public String getLink2()
{
DateModule myModule = (DateModule) getCurrentRowObject();
int id = DateModule.getId().intValue();
return "<a href=\"details.jsp?id=" //$NON-NLS-1$
+ id
+ "&action=view\">查看</a> | " //$NON-NLS-1$
+ "<a href=\"details.jsp?id=" //$NON-NLS-1$
+ id
+ "&action=edit\">编辑</a> | " //$NON-NLS-1$
+ "<a href=\"details.jsp?id=" //$NON-NLS-1$
+ id
+ "&action=delete\">删除</a>"; //$NON-NLS-1$
}
}
然后编写jsp页面,首先在页面中import一下自己定义的MyWrapper,在<display:table>中增加decorator=” MyWrapper”属性,在数据显示的列种添加
<display:column property="link2" title="Actions" />
三、 备注说明
此文档只列举了一些经常用到的表格显示例子,其他的功能暂没进行详细列举。
关于此标签的分页功能说明: 此标签还有的功能包括实现对list的数据分页,但是由于对海量数据支持的不完善性暂不介绍,在进行分页的时候我们仍然用hibernate的分页方法实现分页,传递数据时只传递当前页的List对象数据。
关于样例程序的说明:在displaytag-examples-1.1.war中的例子基本上包含了所有displaytag所有能做到的效果显示。其中所有例子都是基于JSP XML syntax这种格式的页面文件编写的。当用普通的jsp页面进行测试时应该在文件顶部加入标签库信息<%@ taglib uri="
http://displaytag.sf.net" prefix="display" %> 同时应当将标签库要用到的css样式导入到页面中
<style type="text/css" media="all">
@import url("css/maven-base.css");
@import url("css/maven-theme.css");
@import url("css/site.css");
@import url("css/screen.css");
</style>