转载

JSP技术优缺点深入分析(1)

作为一名资深的 Java 技术专家和 Enhydra 支持者,本文作者强烈建议开发人员在选择 Web 应用程序编程语言时,使用其他可以替代 JavaServer Pages (JSP) servlets 的技术。JSP 技术是Sun 的J2EE 平台和编程模型的一部分,用于解决将单调的内容转换为外观优美的表示层时遇到的困难。事实上,并非所有的Web开发人员都对JSP 技术很满意。由于 Sun 技术出现了很多不同的版本,您可以从众多表示技术中选择一种替代技术。本文将深入查看JSP代码并介绍一些有吸引力的替代选择。

表示技术专门用于将单调粗糙的Web 内容转换成带有漂亮的表示层的内容。JavaServer Pages (JSP) 技术是 Sun 的表示模型,并且是 J2EE 平台的一部分,它获得了极大的关注。使用 JSP 技术有优点也有缺点。Web 开发人员应该了解这些优缺点,并且知道还有其他代替技术。实际上,现在有很多可供选择的表示技术。本文先介绍表示技术要解决哪些问题,然后考察 JSP 模型特有的优缺点。最后,将介绍一些其他表示技术,它们可以代替 Sun 表示技术。

历史背景

在深入介绍表示技术之前,有必要了解一下该技术产生的时代背景。就在10 年前,瘦客户机还是个新鲜事物。我们仍然处于桌面应用程序的时代,使用功能有限的 286 微处理器和现在看来不屑一顾的 14 寸显示器。时代变了!现在我的台式机只需要运行一个 Web 浏览器,服务器由 Sun、IBM、HP、Compaq 提供,计算、业务逻辑和内容则又由其他公司提供。那么显示器呢?现在我们使用的是 21 寸到 25 寸不等、等离子宽屏显示器。这样我们就可以看到复杂的 HTML 表示,它们充当这些强大的应用程序的前端。以前的单调界面已经无法满足需要;我们现在需要使用华丽的图形、可以移动的图像、色彩协调的表示,并且要求它能够加快呈现速度。

前提条件

如今,在羽毛渐丰的 Windows 应用程序经过十年的发展之后,我们还处在表示模式的巨大转型之中。Visual Basic 和 C 程序员发现他们仍然在使用后端系统或单调的 Windows 应用程序,或是在工具箱中加入了一种具有 Web 能力的语言,例如 Java 语言。如果一个应用程序无法支持至少 3 到 4 种 ML 式语言(例如 HTML、XML 和 WML),即使不是彻底失败,也会被认为是很糟糕的。当然,这就表示我们非常重视能轻松开发 Web 表示层的能力。

事实证明,使用新的 Internet 以及所有可用的语言(Java、C、Perl、Pascal 和 Ada 等)并不像我们希望的那样简单。在后端系统使用编程语言并利用它们生成适合客户机的标记语言时,出现了大量问题。随着浏览器端的选择越来越多(例如 DHTML 和 JavaScript 编码),Web 领域迫切需要图形设计知识,以及可以使用标准 HTML 创建复杂界面的工具。但开发应用程序前端的能力无法跟上这些需求的步伐。此时,表示技术 应运而生。

表示技术的专门任务是:将内容(即没有包含表示细节的数据)转换为表示,也就是您在手机、PalmPilot 或 Web 浏览器看到的各种用户界面。这些表示技术要解决哪些问题?让我们来了解一下。

分离和集成

表示技术的主要目的是允许分离内容和表示。换而言之,业务逻辑单元(假设 C 或 Java 等编程语言)不需要使用特定于表示的方式生成数据。数据或内容,按照原始格式返回,没有进行格式化。表示技术随后对内容应用格式化或进行表示。最终的结果是各种数据被图形、格式、色彩和徽标所包围。

查看清单 1 和清单 2 中的示例,了解一下原始内容和应用了表示技术的内容之间的差异。

清单1:展示了原始的内容,全部都是数据,可以按照任何方式使用。

Russell Crowe Tom Hanks Meg Ryan Mary Stuart Masterson Alec Baldwin Ashley Judd Keanu Reeves 

清单2:要比清单 1 更加复杂,使用表示技术对相同的数据进行了装饰,并可以立即表示在支持 HTML 的浏览器中。

HTML HEAD TITLESearch Results: Actors/TITLE /HEAD BODY H2 ALIGN="center"Search Results: Actors/H2 CENTER HR width="85%" TABLE width="50%" CELLPADDING="3" CELLSPACING="3" border="1"          BGCOLOR="#FFFFCC"     TR BGCOLOR="#FFCCCC"       TH width="50%" ALIGN="center"Last Name/TH       TH width="50%" ALIGN="center"First Name/TH     /TR     TR       TD width="50%"Baldwin/TD       TD width="50%"Alec/TD     /TR     TR       TD width="50%"Crowe/TD       TD width="50%"Russell/TD     /TR     TR       TD width="50%"Hanks/TD       TD width="50%"Tom/TD     /TR     TR       TD width="50%"Judd/TD       TD width="50%"Ashley/TD     /TR     TR       TD width="50%"Masterson/TD       TD width="50%"Mary Stuart/TD     /TR     TR       TD width="50%"Reeves/TD       TD width="50%"Keanu/TD     /TR     TR       TD width="50%"Ryan/TD       TD width="50%"Meg/TD     /TR /TABLE /CENTER /BODY /HTML  

可以看到,清单 1 中的内容更清晰,非专业人员更加容易使用和理解,而清单 2 中的内容特定于浏览器表示。很难从中提取数据或将数据用作其他用途。

内容导航
 第 1 页:分离和集成  第 2 页:工作和重复工作
 第 3 页:可移植性和语言锁定

这个基本的区别,即分离表示和内容而不是集成它们(至少在用户需要使用信息时),是任何表示技术前提,包括 JSP 技术。此外,任何无法实现这个基本目标的表示技术都不能真正体现创建的初衷。

工作和重复工作

除了分离表示和内容外,另一个衡量表示技术的可用性的指标是:能够消除多少重复的工作。表示和内容的分离也促使内容开发人员之间的角色分离。程序员可以关注上例所示的原始内容,而图形设计师或网络管理员则关注表示。然而,在获得图形设计师设计的表示(或标记)并将它应用到程序员代码提供的内容中时,角色之间仍然有一定重复。

在最简单的情况下,设计师提供标记,而开发人员提供代码并把标记插入到表示技术中。应用程序被 “启动”,内容魔术般地变成了用户界面。当然,我们都知道,开发远远没有结束。接下来要重新修订版本、修改界面,还必须添加新的业务规则。这能真正考验表示技术的灵活性。虽然很容易更新插入到表示层的原始内容,但是图形设计师很少能够轻松地编辑他们的初始工作。经常要修改表示层(我们常常按照销售部门的 “指使” 进行修改)。因此,问题产生了:设计师要修改哪些内容来调整他们的工作?是他们提供给开发人员的原始标记语言页面吗?也许不是,因为这个页面很可能插入了自定义标记或代码(JSP 页面、模板引擎),被转换为一个 Java servlet,或修改为完全无法识别的内容。

设计师通常需要重新设计页面并重新将其提交给开发人员。然后再由开发人员将页面重新转换为特定的格式,以供表示技术使用。或者,设计师必须学习一种脚本编制语言,或至少知道开发人员提供的页面源代码中哪部分是违规的。当然,这种方法容易出错,并且使用起来不安全。当您了解到某种表示技术允许清晰地分离内容和表示后,您应该确保将修改表示层所需的重复工作减至最小。

JSP 技术的承诺

现在,让我们具体看一下 JSP 编码。JSP 技术承诺为设计师和开发人员提供他们所需的惟一表示技术。JSP 技术是 J2EE 平台的一部分,这充分展示了 Sun 为其 Java 产品提供的强大支持。为了使您了解这个解决方案的流行程度,请尝试在 amazon.com 中搜索一下 ‘JSP’;您将发现大量与 JSP 技术有关的书籍,它会远远超过任何单独一种 Java API.在详细探讨 JSP 技术引发的具体问题之前,您应该清楚地了解这种技术的承诺。

内容和表示

首先,JSP 技术与内容和表示的分离有关,是 Sun 发布的有关 JSP 页面的最主要目标。实际上,一些代码开发人员抱怨将 out.println("HTMLHEADTITLE" + pageInfo.getTitle() + "/TITLE/HEAD"); 键入到 servlet,这直接导致了 JSP 的设计。在硬编码内容中混入运行时变量加重了 servlet 开发人员的负担,并且使开发人员更加难对表示层进行修改,即使非常小的修改也是如此。

JSP 技术解决了这个问题,它允许在运行时将普通的 HTML 页面(后来还包括 WHM 或其他标记语言)编译到 Java servlet 中,实际上效仿了 out.println() 范例,而不需要开发人员编写代码。它允许您将变量插入到在运行时才进行解释的页面。

在一个 JSP 页面中,清单 2 所示的 HTML 片段应该类似清单 3 中的示例。

%@ page import="com.ibm.display.PageUtils" % %@ page import="com.ibm.display.PageInfo" % % PageInfo pageInfo = (PageInfo)session.getAttribute("PAGE_DATA") % HTML HEAD TITLE %=pageInfo.getTitle()% /TITLE /HEAD BODY !-- Other HTML content -- /BODY /HTML 

根据最初的原则判断,JSP 技术(至少在其说明的设计中)可以满足表示技术的基本原则,正如上面概况的一样:内容与表示分离。

代码和标记

JSP 技术特性列表上的第二项可能会出现一些问题。JSP 代码可以让您将 Java 代码直接插入到标记页面。在开发 JSP 规范时,Microsoft Active Server Pages (ASP) 大获成功,因此 Sun 与 Microsoft 之间的竞争空前激烈。这导致了这个决策的产生。JavaServer Pages 的名称与 Active Server Pages 类似并非偶然。并且对众多 API 特性的模仿也是蓄意而为。因此 JSP 创建者需要能够将 Java 代码添加到他们的标记中。

为了演示将 Java 代码加入到标记中,清单 4 中的 JSP 代码片段根据需要动态地添加行,以表示 actors 的 Vector 中的每一项。

%@ page import="com.ibm.display.PageUtils" % %@ page import="com.ibm.display.PageInfo" % %@ page import="com.ibm.people.Actor" % %@ page import="java.util.Iterator" % %@ page import="java.util.Vector" % % PageInfo pageInfo = (PageInfo)session.getAttribute("PAGE_DATA") Vector actors = pageInfo.getActors() % HTML HEAD TITLE %=pageInfo.getTitle()% /TITLE /HEAD BODY H2 ALIGN="center"Search Results: Actors/H2 CENTER HR width="85%" TABLE width="50%" CELLPADDING="3" CELLSPACING="3" border="1"          bgcolor="#FFFFCC" % for (Iterator i = actors.iterator(); i.hasNext()) { Actor actor = (Actor)i.next(); %     TR BGCOLOR="#FFCCCC"       TH width="50%" ALIGN="center"        %=actor.getLastName()%       /TH       TH width="50%" ALIGN="center"        %=actor.getFirstName()%       /TH     /TR % } % /TABLE /CENTER /BODY /HTML 

注意,目前为止,我仅仅介绍了 JSP 技术的最初设计目标;在下一节介绍 JSP 技术存在的问题之后,我将对这个目标作出自己的论断。不过,您可能已经开始有点好奇,因为将代码嵌入到 JSP 页面中似乎与 JSP 技术的首要目标(分离内容和表示)有所冲突。实际上,我还没有就此展开论述。

设计师和开发人员

JSP 技术的最终(也是值得称赞)的目标是,它尝试在应用程序开发过程中形成清晰定义的角色。通过在表面上分离内容和表示,JSP 技术能够更加清晰地区分设计师和开发人员角色。设计师使用标准的 HTML、WML 或其他合适的语言创建标记,而开发人员编写代码。当然,如今很多设计师学习了 JavaScript 语言,因此,这些设计师开始学习 JSP 编码也不是什么令人吃惊的事情。通常,设计师并不会单纯地创建纯标记,他们会编写一个完整的 JSP 页面并将其交给开发人员。然后经过频繁的修改,开发人员再将 JSP 页面作为完整应用程序的前端使用。但是,这里的关键问题是仍然有很多设计师没有 学习 JSP 编码,他们也必须能够在这种环境下工作。

出现的问题

我刚刚介绍了一种良好的表示技术应该提供的功能,以及 JSP 技术尝试解决的具体问题。现在,我将转入正题:JSP 技术虽然建立在良好理念的基础之上,但是却出现了一些问题。在选择 JSP 编写您的应用程序之前(您可能仍然会这样做),至少应该注意一些容易出现的问题。

您还需要注意经常被忽略的 J2EE 编程平台:仅仅因为平台附带了 API 并不意味着一定要使用它。和这种想法同样可笑的是,很多开发人员在使用 JSP、EJB 或 JMS API 时,都在想如果不使用这些 API 的话,他们的应用程序就不是真正的 “J2EE 应用程序” 了。实际上,平台提供的 API 远远超过大多数应用程序的需要。如果您不能使用或对 JSP 技术还持有怀疑态度,那么可以不使用它!在选择 JSP 编写应用程序之前,仔细研究它的优点和 缺点。让我们看看其中一些缺点。

内容导航
 第 1 页:分离和集成  第 2 页:工作和重复工作
 第 3 页:可移植性和语言锁定

可移植性和语言锁定

JSP 技术将您锁定到某种特定的语言。这一点不应该给予太多的关注。至少在我看来,Java 技术是企业应用程序的惟一 选择。在这个领域,根本不存在可以独立于语言的解决方案。当然,在这个时候,我没有把 Microsoft .NET 平台牵涉进来。只有时间可以告诉我们这个平台是否可以真正独立于语言(我很怀疑这一点)。

然而,选择 JSP 技术将强制您使用 Java 语言,至少对于内容和表示是这样的。尽管 CORBA 可以用于业务逻辑,JSP 编码要求必须熟悉 servlet 和核心 Java 语言。因为很多开发人员通过 J2EE 平台接触 JSP 编码,因此这通常算不成问题。

混合和独立

在本篇文章中,我始终围绕分离内容和表示这一概念。您可能对此已经感到不耐烦,那么现在让我们看看 JSP 究竟能不能实现这个目标。正如我们之前讨论的一样,JSP 宣称 一直致力于实现内容和表示分离,那么我们可以因此认为它实现了目标,是吗?未必如此。

内容和表示之间的界限变得模糊

JSP 允许将 Java 代码插入到标记语言页面中,这个非常危险的特性允许将内容混合到表示中。更糟糕的是,业务逻辑通常会进入到 JSP 页面中,如清单 5 所示。

%@ page import="com.ibm.display.PageUtils" % %@ page import="com.ibm.display.PageInfo" % %@ page import="com.ibm.logic.AdminUtils" % %@ page import="com.ibm.people.Actor" % %@ page import="java.util.Iterator" % %@ page import="java.util.Vector" % % PageInfo pageInfo = (PageInfo)session.getAttribute("PAGE_DATA") % HTML HEAD TITLE %=pageInfo.getTitle()% /TITLE /HEAD BODY H2 ALIGN="center"Search Results: Actors/H2 CENTER HR width="85%" TABLE width="50%" CELLPADDING="3" CELLSPACING="3" border="1"          BGCOLOR="#FFFFCC" % // Based on user's permissions, perform search differently (business logic!) Vector actors = pageInfo.getActors() if (pageInfo.getUserInfo().hasPermission("ADMINISTRATOR")) {    actors = AdminUtils.getActors(pageInfo.getSearchCriteria()); } else {    actors = pageInfo.getActors(); } for (Iterator i = actors.iterator(); i.hasNext()) { Actor actor = (Actor)i.next(); %     TR BGCOLOR="#FFCCCC"       TH width="50%" ALIGN="center"        %=actor.getLastName()%       /TH       TH width="50%" ALIGN="center"        %=actor.getFirstName()%       /TH     /TR % } % /TABLE /CENTER /BODY /HTML 

JSP 的拥护者会很快告诉您 JSP 标记库 可以帮助您避免这个问题。标记库允许将自定义标记(例如 AUTHORS /)添加到 JSP 页面,然后在运行时在标记库内将其解析为代码片段。

使用自定义标记和相关的标记库允许把以上示例转换为清单 6 所示的内容。

CENTER TABLE width="50%" CELLPADDING="3" CELLSPACING="3" border="1"          BGCOLOR="#FFFFCC"    ACTORS / /TABLE /CENTER 

在运行时,将执行标记的代码并把正确的结果插入到页面中。但是这并没有解决问题。反对 JSP 技术的理由并不在于能否 分离内容和表示,而是在于是否必须 分离。只要 JSP 编码允许内联编码,那么就可以很方便地对内联代码进行最后的修改(特别是逼近最后期限时),而不是将代码转换为一个标记库。如果这不是真的,那么 Java 语言为何会马上比 C 和 C++ 更流行:Java 禁用了 C 中大量有问题的特性,例如指针相加。虽然您可以总是强调您不需要 在 C 中执行指针相加,或者优秀的程序员将插入代码 scriptlet,我们都知道实际会发生什么。Java 语言是一种更好的选择,因为它严禁 使用这些不好的习惯。但是 JSP 在这方面更类似于 C,允许实现一些非常糟糕的实践。

检验 JSP 技术是否成功达到其所述目标的另一种方法是看它能否在实践中实现这个目标;显然,如果认为 JSP 无法实际实现目标,这是不公平的。大多数模板引擎,比如 FreeMarker 和 WebMacro,都提供了相同的内联编码功能,通常附带了一种类似 Perl 的语言。然而,诸如 Enhydra 的 XMLC 这样的技术不 允许进行这种类型的编码。相反,这些技术将一个纯标记语言页面作为输入,然后生成 Java 方法。这实际上改变了编程流程;应用程序并不像 JSP 技术那样使用页面从应用程序调用逻辑,而是使用方法影响页面的值(Enhydra)。以 Enhydra 为例,使用 XMLC 将页面转换为一个 DOM 树,然后使用 DOM 的 HTML 绑定更新页面中的 “字段”(有关 Enhydra XMLC 的更多信息,请查阅 参考资料)。

这里的重点是,JSP 技术实现目标的能力远远超过 XMLC,例如,仅仅是允许标记库这一项就比 XMLC 强很多。但是 Sun 规范总体趋向于始终维护向后兼容性,或至少在相当长的一段时间内维护向后兼容性。JSP 规范的当前版本为 1.1,它允许使用 scriptlets,因此在未来几年内 JSP 页面内都会支持这个特性。在深入探究 JSP 编码之前,请注意,在其强调的完全分离内容和表示的理念和实际实现之间存在一个很大的缺口,它充其量只是假装分离了用户界面和驱动应用程序的代码。

单处理和多任务处理

如前所述,理想状态下,设计师应该能够执行单独处理,只关注图形设计,而开发人员应该能够将注意力集中在编程上。因此,设计师可以在将页面转换为适合应用程序的格式后,再对其进行处理。对于 JSP 页面来说,将页面转换为适合应用程序的格式就是指向页面导入 JavaBeans、插入内联编码并添加自定义标记库。问题是有些设计师使用的是 HTML 编辑器,比如 HoTMetaL、Macromedia Dreamweaver 或 FrontPage,这些编辑器无法识别代码 scriptlets 或标记库,这意味着设计师实际上只收到了页面的一部分。想象一下,标记库或代码片段只生成了表的若干行,或是页面中其他格式化的细节,这是多么麻烦的事情。设计师使用了不兼容的 HTML 编辑器,无法看到这些元素的外观。在开发人员完成编码后,设计师不能轻松地对页面进行修改,这时,不仅没有清晰地划分角色,JSP 编码实际上将这两种角色合二为一:开发人员必须执行多个任务,必须担当开发人员、设计师以及其他角色。

如果您仍然对此表示怀疑,那么请下载 J2EE Reference Implementation 并将其中一个附带的 JSP 页面加载到一个 WYSIWYG HTML 编辑器,例如 Dreamweaver.页面立即被一些黄色区域填充,告诉您页面中包含的所有 “错误” 标记。当然,黄色内容来自于 JSP 标记和代码,而不是页面出现了什么真正的错误。

迄今为止,尚未出现支持 JSP 功能的 WYSIWYG 编辑器,我也没有听说过任何与此相关的项目。尽管模板引擎也具有相同的问题,但是很多基于 Java 的解决方案,例如我最喜欢的 Enhydra,都允许您将标记页面作为输入提供给表示技术。在这种情况下,设计师可以根据需要频繁地进行修改,并重新提供标记页面。运行表示技术的引擎或编译程序将标记页面转换为适当的格式,并且不需要修改任何代码(典型情况下)。最终获得了理想的结果:设计师和开发人员各司其职。

因此,要注意 JSP 技术作出的承诺和它实际交付的实现。在实际中,要在一个 JSP 技术驱动的环境下发挥功效,必须让开发人员处理大部分标记,或至少让设计师学习一些 JSP 编码。

HTML 和 XML

JSP 技术最严重的缺陷之一(也是经常被忽视的一个缺陷)就是它与 XML 不兼容。更确切地说,并且特别针对 HTML 领域,JSP 页面不要求具备 XHTML 兼容性。XHTML 是一个 World Wide Web Consortium (W3C) 规范,目前正在取代 HTML 4.0.XHTML 在实现格式良好的 XML 文档方面定义了 HTML 标记集。例如,
标记必须被转换为
才能确保 XML 兼容性(如果这个例子没有解释清楚的话,可以查阅 参考资料 列出的 XML 规范,以及关于 XHTML 的 developerWorks 文章)。同样的规则适用于图像标记,并且在 XHTML 1.1(即将到来)中,大部分字体属性和其他样式被移入到 CSS 样式表中。另外,大多数标准 HTML 文档可以轻松地转换为 XHTML 1.0,这意味着可以使用任何与 XML 兼容的解析器读取,例如 Apache Xerces,并且可以作为 XML 进行处理。

您会问 “这有什么关系呢?”。答案是关系重大。因为 XML 正在快速成为一个在应用程序之间和应用程序内部进行通信的全球标准。使用 XML 格式传递书籍,可以让任何使用基本 XML 数据绑定功能的应用程序轻松地使用您的应用程序的数据。想象一下,通过将您的数据迁移到 XML 格式,您就可以与信用卡公司进行网上交易!多数情况下,您的数据表示还需要与其他公司进行交互。最常见的情况是门户应用程序,它接受来自各种提供者的内容(例如,天气信息、股票报价和新闻),通常附带有提供者的标记。然而,由于 JSP 页面将代码和自定义标记库相混合,因此无法在这种环境下良好地工作。

JSP 页面很少具有格式良好的 XML 文档,并且不重视是否符合 XHTML,而 XHTML 这种标记语言并不允许使用各种 JSP 自定义标记库。然而,更重要的是,插入到 JSP 页面的代码片段并不属于任何标记形式,因此当另一个应用程序处理它们时,将产生解析器加载错误。

在您提出质疑之前,让我们先了解一下整个情况。如果应用程序允许 JSP 页面由初始客户机处理,结果将产生纯 HTML(或 WML、VoXML 等)。然而,大多数请求这个数据的应用程序使用了一定程度的缓存,因为网络往返开销很昂贵。在这些情况下,缓存过的页面将返回过时的数据。因此,您可能更愿意返回与 XML 兼容的结果,最好使用静态的形式。而 JSP 技术在这些情况下无能为力;JSP 页面必须始终 在运行时进行处理,以去掉 JSP 代码 scriptlets 和标记库。

看看最关键的考验:其他一些表示技术能做到这一点吗?答案是可以。这个领域最权威的领导者是 Apache Cocoon 项目,它完全建立在 XML 和一个 XSLT 样式表应用程序(可以在运行时或静态状态下应用)的基础之上。由于 XML Server Pages(在 Cocoon 框架中称为 XSP)实际上是 XML 文档,因此始终与 XML 兼容。像 Tea 和 Enhydra XMLC 等允许输入纯标记语言页面的技术也可以做到这点,虽然它们的目的并不在此。在这些情况下,用户可以使用 XHTML 或标准的 HTML.此外,这比 JSP 技术要好,因为 JSP 不能 静态地实现格式良好的 XML.

结束语

希望我的努力能够让您进一步了解JSP 技术的优缺点,并且您可以将JSP 技术看作是众多其他表示技术的替代品。现在,您可能对整个J2EE编程模型也产生了一点怀疑。如果您希望进一步研究平台选择,那么可以在 Apache Cocoon、Enhydra 和各种模板引擎中寻找 JSP 技术的替代选择。

最后,请记住,本文并不是建议您使用JSP或避免使用它,尽管表面上像是这样。我的目的是鼓励您对任何技术进行详细的分析,确保它是正确的选择。就像编程模型一样,有时它们是合适的,然而有些时候它们并不适合。多进行一些比较,找到最适合自己的技术并作出明智的决定,而不是仓促地决定。

正文到此结束
Loading...