最重要的 Java EE 最佳实践 |
级别: 初级 Keys Botzum, 高级技术人员 , IBM 2007 年 3 月 27 日 2004 年 IBM® WebSphere® 开发者技术期刊中曾发表过一篇名称类似的文章,本文是其更新版本。这个修正版中考虑了一些不断变化的技术趋势,更重要的是推荐了一些作者认为应当广泛遵循、但尚未广泛遵循的实践。<!--START RESERVED FOR FUTURE USE INCLUDE FILES--><!-- include java script once we verify teams wants to use this and it will work on dbcs and cyrillic characters --> <!--END RESERVED FOR FUTURE USE INCLUDE FILES--> 在 过去的几乎整整十年中,人们编写了很多有关 Java™ Platform, Enterprise Edition (Java EE) 最佳实践的内容。现在有十多本书籍和数以百计(可能更多)的文章,提供了关于应该如何编写 Java EE 应用程序的见解。事实上,这方面的参考资料如此之多,并且这些参考资料之间往往还存在着一些矛盾的建议,以至于在这些混杂的内容中进行学习本身也成为了采 用 Java EE 的障碍。因此,为了给刚进入这个领域的客户提供一些简单的指导,我们汇编了这个最重要的最佳实践列表,其中包括我们认为最重要和最有效的 Java EE 最佳实践。遗憾的是,我们无法仅在 10 大最佳实践中描述所有需要介绍的内容。因此,为了避免遗漏关键的最佳实践和尊重 Java EE 的发展,我们的列表中包含了“19 大”关键的 Java EE 最佳实践。
将业务逻辑(Java Bean 和 EJB 组件)从控制器逻辑(Servlet/Struts 操作)和表示逻辑(JSP、XML/XSLT)中清晰地分离出来。良好的分层可以带来许多好处。
对于 Java EE,有许多关于这个主题的优秀评论,我们特别推荐感兴趣的读者可以参考 [Fowler] 或者 [Brown](请参见参考资料部分)的评论,以便全面和深入地了解相关内容。 如 果不遵循基本的 MVC 体系结构,在开发过程中就会出现许多的问题。最常见的问题是,将过多的任务放到该体系结构的视图部分中。可能存在使用 JSP 标记来执行数据库访问,或者在 JSP 中进行应用程序的流程控制,这在小规模的应用程序中是比较常见的,但是,随着后期的开发,这样做将会带来问题,因为 JSP 逐步变得越来越难以维护和调试。 类似地,我们也经常看到将视图层构建到业务逻辑的情况。例如,一个常见的问题就是将在构建视图时使用的 XML 解析技术直接应用到业务层。业务层应该对业务对象进行操作,而不是对与视图相关的特定数据表示进行操作。 然 而,仅仅使用适当的组件无法实现应用程序的正确分层。我们常常见到一些应用程序包含 Servlet、JSP 和 EJB 组件所有这三项,然而,其主要的业务逻辑却是在 Servlet 层实现的,或者应用程序导航是在 JSP 中处理的。您必须对代码进行严格的检查和重构,以确保仅在模型层中处理业务逻辑,在控制器层中进行应用程序导航,而视图应该只关心如何将模型对象呈现为合 适的 HTML 和 Javascript™。 本文中这项建议的涵义应该比原始版本中的更加清楚。用户接口技术 不断地发生着变化,将业务逻辑关联于用户接口,会使得对接口的更改影响到现有的系统。几年之前,Web 应用程序用户接口开发人员可能从 Servlet 和 JSP、Struts 和 XML/XSL 转换中进行选择。在那以后,Tiles 和 Faces 非常流行,而现在,AJAX 大行其道。如果每当首选的用户接口技术发生了更改就要重新开发应用程序的核心业务逻辑,那么就糟透了。
使用常见的、经过证实的框架,如 Apache Struts、JavaServer Faces 和 Eclipse RCP。使用经过证实的模式。 随着开放源码的框架(如 Apache Struts)的出现 [Brown],我们相信,可以自动地和快速地转换到这些新的框架。我们认为,使用开放源码社区支持的框架非常适合于开发人员,并且这些框架很快得到了广泛认可,不仅可用于新的开发,还可以修改现有的应用程序。 但 令人感到奇怪的是,事实并非如此。我们仍可以看到许多公司在维护或甚至开发新的用户接口框架,而这些框架的功能与 Struts 或者 JSF 是完全相同的。之所以会出现这种情况,有许多原因:机构惰性,“非我发明”症,不了解更改现有代码的好处、或者甚至傲慢地认为能够比开放源码开发人员的特 定框架做得更好。 然而,这些原因都已经过时了,不能够成为不采用标准框架的借口。Struts 和 JSF 不仅在 Java 社区中得到了广泛认可,而且还受到 WebSphere 运行时和 Rational® 工具套件的全面支持。同样地,在富客户端领域中,Eclipse RCP(富客户端平台,Rich Client Platform)获得了广泛的认可,可用于构建独立的富客户端。尽管不是 Java EE 标准中的一部分,但这些框架现在已成为 Java EE 社区的一部分,并且理应如此。 对于那些因为傲慢而不愿使用现成的 UI 框架的人,应该阅读 [Alur] 和 [Fowler] 中介绍的内容。这两本书详细地描述了企业 Java 应用程序中最常用的可重用模式。从类似于会话 Facade 这样简单的模式(将在后面的建议中讨论)到类似于 Fowler 持久性模式(许多开放源码的持久性框架对其进行了实现)这样比较复杂的模式,其中的内容体现了 Java 前辈们所积累的智慧。那些不能吸取教训的人必定会重蹈覆辙(如果他们非常幸运,能够在第一次失败之后获得重来一次的机会),他们不得不向哲学家 Santayana 说抱歉。
不要只是测试您的图形用户界面(GUI)。分层的测试使得调试和维护工作变得极其简单。 MVC 体系结构(以及 Java EE 中的 MVC 实现)的一个优点就是元素的组件化能够(实际上,相当的简单)对您的应用程序进行单元测试。因此,您可以方便地对实体 Bean、会话 Bean 以及 JSP 独立编写测试用例,而不必考虑其他代码。现在有许多用于 Java EE 测试的框架和工具,这些框架及工具使得这一过程更加简单。例如,JUnit(是一种由 junit.org 开发的开放源代码工具)和 Cactus(由 Apache 协会开发的开放源代码工具)对于测试 Java EE 组件都非常有用。[Hightower] 详细探讨了如何在 Java EE 中使用这些工具。 尽 管所有这些详述了怎样彻底地测试您的应用程序,但是我们仍然看到一些人认为只要他们测试了 GUI(可能是基于 Web 的 GUI,或者是独立的 Java 应用程序),则他们就全面地测试了整个应用程序。仅进行 GUI 测试是不够的。GUI 测试很难达到全面的测试,有以下几种原因。
另 外,我们必须强调,使用 EJB 和 Web 服务进行分布式的、基于组件的开发使得测试单个组件变得非常必要。如果没有“GUI”需要测试,您就必须进行低级(lower-level)测试。最好以 这种方式开始测试,省得当您将分布式的组件或 Web 服务作为您的应用程序的一部分时,您不得不花费心思重新进行测试。 总之,通过使用自动的单元测试,能够很快地发现系统的缺陷,并且也易于发现这些缺陷,使得测试工作变得更加系统化,因此整体的质量也得以提高。
要将规范熟记于心,如果要背离规范,需经过慎密的考虑后才可以这样做。这是因为当您背离规则的时候,您所做的事情往往并不是您应该做的事情。 现 在有好几个地方如果不直接使用 Java EE 提供的方法肯定会产生问题。一个常见的例子就是开发人员通过使用 JAAS 模块来替代 Java EE 安全性,而不是使用内置的遵循规范的应用服务器机制来进行验证和授权。要注意不要脱离 Java EE 规范提供的验证机制。如果脱离了此规范,这将是系统存在安全漏洞以及厂商兼容性问题的主要原因。类似地,要使用 Servlet 和 EJB 规范提供的授权机制,并且如果您要偏离这些规范的话,要确保使用规范定义的 API(例如 getCallerPrincipal())作为实现的基础。通过这种方式,您将能够利用厂商提供的强安全性基础设施,其中,业务要求需要支持复杂的授权 规则。(有关授权的更详细内容,请参见 [Ilechko]。) 其 他常见的问题包括使用不遵循 Java EE 规范的持久性机制(这使得事务管理变得困难)、在Java EE程序中使用不适当的 J2SE 方法(例如线程或 singleton),以及使用您自己的方法解决程序到程序(program-to-program)的通信,而不是使用 Java EE 内在支持的机制(例如 JCA、JMS 或 Web 服务)。当您将一个遵循 Java EE 的服务器移植到其他的服务器上,或者移植到相同服务器的新版本上,上述的设计选择将会造成无数的问题。使用 Java EE 之外的元素,通常会导致一些细微的可移植性问题。唯一要背离规范的情况是,当一个问题在规范的范围内无法解决的时候。例如,安排执行定时的业务逻辑在 EJB2.1 出现之前是一个问题。在类似这样的情况下,我们建议当有厂商提供的解决方案时就使用厂商提供的解决方案(例如 WebSphere Application Server Enterprise 中的 Scheduler 工具),而在没有厂商提供的解决方案时就使用第三方提供的工具。当然,现在的 EJB 规范提供了基于时间的函数,所以我们鼓励使用这些标准接口。如果使用厂商提供的解决方案,应用程序的维护以及将其移植到新的规范版本将是厂商的问题,而不 是您的问题。 最后,要注意不要太早地采用新技术。太过于热衷采用还没有集成到 Java EE 规范的其他部分或者还没有集成到厂商的产品中的技术常会带来灾难性的后果。支持是关键的——如果您的厂商不直接支持某种特定的技术,那么您在采用此技术时 就应该非常谨慎。有些人(尤其是开发人员)过分关注于简化开发过程,忽略了依赖大量本组织之外开发的代码的长期后果,而供应商并不支持这些代码。我们发 现,许多项目团队沉迷于新技术(例如最新的开放源代码框架),并很快地依赖于它,却没有考虑它对业务带来的实际代价。坦白地说,对于使用您的供应商所提供 的产品之外的任何技术的决策,都应该由企业组织结构中的各个部门、业务团队和法律团队(或您的环境中的等同机构)仔细地进行评审,这与正常的产品购买决策 完全相同。毕竟,我们中的大多数人是在解决业务问题,而不是推进技术的发展。
启用 WebSphere 安全性。这使您的 EJB 和 URL 至少可以让所有授权用户访问。不要问为什么——照着做就是了。 不使用 Java EE 安全性是件危险的事情。假设您的应用程序需要安全性(几乎所有的应用程序都需要),敢打赌您的开发人员能够构建出自己的安全性基础设施,其比您从 Java EE 厂商那里买来的更好。这可不是个好的游戏。为分布式的应用程序提供安全性是异常困难的。例如,您需要使用网络安全加密令牌控制对 EJB 的访问。以我们的经验看来,大多数自己构建的安全性基础设施是不安全的,并且有重大的缺陷,这使产品系统极其脆弱。(有关更详细的信息,请参考 [Barcia] 的第 18 章。) 一 些不使用 Java EE 安全性的理由包括:担心性能的下降,相信其他的安全性(例如 IBM Tivoli® Access Manager 和 Netegrity SiteMinder)可以取代 Java EE 安全性,或者是不知道 WebSphere Application Server 安全特性及功能。不要陷入这些陷阱之中。尤其是,尽管像 Tivoli Access Manager 这样的产品能够提供优秀的安全特性,但是仅仅其自身不可能保护整个 Java EE 应用程序。这些产品必须与 Java EE 应用服务器联合起来才可能全面地保护您的系统。 其他一种常见的不使用 Java EE 安全性的原因是,基于角色的模型没有提供足够的粒度访问控制以满足复杂的业务规则。尽管事实是这样的,但这也不应该成为不使用 Java EE 安全性的理由。相反地,应该将 Java EE 验证及 Java EE 角色与特定的扩展规则结合起来。如果复杂的业务规则需要做出安全性决策,那就编写相应的代码,其安全性决策要基于可以直接使用的以及可靠的 Java EE 验证信息(用户 ID 和角色)。(有关授权的更详细的信息,请参见 [Ilechko]。)
反复的开发工作将使您能够逐渐地掌握所有的 Java EE 模块。要从创建小而简单的模块开始而不是从一开始就马上涉及到所有的模块。 这 种方法可以通过在您的应用程序中创建小而简单的模块来得到最好的实现。如果一个开发团队通过创建一个简单的域模型以及后端的持久性机制(也许使用的是 JDBC),并且对其进行了完整的测试,这会增强他们的自信心,于是他们会使用该域模型去掌握使用 Servlet 和 JSP 的前端开发。如果一个开发团队发现有必要使用 EJB,他们也会类似地开始在容器管理的持久性 EJB 组件之上使用简单的会话 Facade,或者使用基于 JDBC 的数据访问对象(JDBC-based Data Access Objects,DAO),而不是跳过这些去使用更加复杂的构造(例如消息驱动的 Bean 和 JMS)。 这 种方法并不是什么新方法,但是很少有开发团队以这种方式来培养他们的技能。相反地,多数开发团队由于尝试马上就构建所有的模块,同时涉及 MVC 中的视图层、模型层和控制器层,这样做的结果是他们往往会陷入进度的压力之中。他们应该考虑一些敏捷(Agile)开发方法,例如极限编程(XP),这种 开发方法采用一种增量学习及开发方法。在 XP 中有一种称为 ModelFirst [Wiki] 的过程,这个过程涉及到首先构建域模型作为一种机制来组织和实现用户场景。基本说来,您要构建域模型作为您要实现的用户场景的首要部分,然后在域模型之上 构建一个用户界面(UI)作为用户场景实现的结果。这种方法非常适合让一个开发团队一次只学到一种技术,而不是让他们同时面对很多种情况(或者让他们读很 多书),这会令他们崩溃的。 还有,对每个应用程序层重复的开发可能会包含一些适当的模式及最佳实践。如果您从应用程序的底层开始应用一些模式(如数据访问对象和会话 Facade),您就不应该在您的JSP和其他视图对象中使用域逻辑。 最后,当您开发一些简单的模块时,在开始的初期就可以对您的应用程序进行性能测试。如果直到应用程序开发的后期才进行性能测试的话,这往往会出现灾难性的后果,正如 [Joines] 所述。
EJB 本地接口(从 EJB 2.0 规范开始使用)为共存的 EJB 提供了性能优化方法。本地接口必须被您的应用程序显式地进行访问,这需要代码的改变和防止以后配置 EJB 时需要应用程序的改变。如果您确定 EJB 调用始终是本地的,那么可以充分利用本地 EJB 的优化。然而,会话 Facade 本身的实现(典型例子如无状态会话 Bean)应该设计为远程接口。通过这种方式,其他的客户端可以远程地使用 EJB 本身,而不会破坏现有的业务逻辑。因为 EJB 可以同时具有本地和远程接口,所以这是完全可以实现的。 为了性能的优化,可以将一个本地接口添加到会话 Facade。这样做利用了这样一个事实,在大多数情况下(至少在 Web 应用程序中),您的 EJB 客户端和 EJB 会共同存在于同一个 Java 虚拟机(JVM)中。另外一种情况是,如果会话 Facade 在本地被调用,可以使用 Java EE 应用服务器配置优化(configuration optimizations),例如 WebSphere 中的“No Local Copies”。然而,您必须注意到这些可供选择的方案会将交互方法从按值传递(pass-by-value)改变为按引用传递(pass-by- reference)。这可能会在您的代码中产生很微妙的错误。最好使用本地 EJB,因为对于每个 Bean 而言,其行为是可以控制的,而不会影响到整个应用服务器。 如果在您的会话 Facade 中使用远程接口(而不是本地接口),您也可以将同样的会话 Facade 在 Java EE 1.4 中以兼容的方式作为 Web 服务来配置。(这是因为 JSR 109,Java EE 1.4 中的 Web 服务部署部分,要求使用无状态会话 Bean 的远程接口作为 EJB Web 服务和 EJB 实现的接口。)这样做是值得的,因为这样做可以为您的业务逻辑增加客户端类型的数量。
8. 使用无状态会话 Bean,而不是有状态会话 Bean。 这样做可以使您的系统更经得起故障转移。使用 HttpSession 存储和用户相关的状态。 Java EE 应用服务器为有状态会话 Bean 提供的故障转移能够解决一些问题,但是有状态的解决方案没有无状态的解决方案易于扩展。例如,在 WebSphere Application Server 中,对无状态会话 Bean 的请求,是通过对部署无状态会话的成员集群进行平衡加载来实现。相反地,Java EE 应用服务器不能对有状态 Bean 的请求进行平衡加载。这意味着您的集群中的服务器的加载过程会是不均衡的。此外,使用有状态会话 Bean 将会再添加一些状态到您的应用服务器上,这也是不好的做法。有状态会话 Bean 增加了系统的复杂性,并且在出现故障的情况下使问题变得复杂化。创建健壮的分布式系统的一个关键原则是尽量使用无状态行为。 因 此,我们建议对大多数应用程序使用无状态会话 Bean 方法。任何在处理时需要使用的与用户相关的状态应该以参数的形式传送到 EJB 的方法中(并且通过使用一种机制如 HttpSession 来存储它)或者从持久性的后端存储(例如通过使用实体 Bean)作为 EJB 事务的一部分来进行检索。在合适的情况下,这个信息可以缓存到内存中,但是要注意在分布式的环境中保存这种缓存所潜在的挑战性。缓存非常适合于只读数据。 总 之,您要确保从一开始就要考虑到可扩展性。检查设计中的所有设想,并且考虑到当您的应用程序要在多个服务器上运行时,是否也可以正常运行。检查设计中所有 的假设,判断如果您的应用程序运行于多个服务器之上,它们是否依然成立。这个规则不但适合上述情况的应用程序代码,也适用于如 MBean 和其他管理接口的情况。 避免使用有状态性不只是对 IBM/WebSphere 的建议,这是一个基本的 Java EE 设计原则。请参见 [Jewell] 的 Tyler Jewell 对有状态 Bean 的批评,其观点和上述的观点是相同的。
学习一下 Java EE 中的两阶段提交事务,并且使用这种方式,而不是开发您自己的事务管理。容器在事务优化方面几乎总是比较好的。 如 果您的应用程序代码显式地使用了开始和结束事务(也许使用 javax.jts.UserTransaction 或者甚至是本地资源事务),而将来的要求需要组合模块(也许会是代码重构的一部分),这种情况下往往需要改变事务代码。例如,如果模块 A 开始了一个数据库事务,更新数据库,随后提交事务,并且有模块 B 做出同样的处理,请考虑一下当您在模块 C 中尝试使用上述两个模块,会出现什么情况呢?现在,模块 C 正在执行一个逻辑动作,而这个动作实际上将调用两个独立的事务。如果模块 B 在执行中失败了,而模块 A 的事务仍然能被提交。这是我们所不希望出现的行为。如果,相反地,模块 A 和模块 B 都使用 CMT 的话,模块 C 也可以开始一个 CMT(通常通过配置描述符),并且在模块 A 和模块 B 中的事务将是同一个事务的隐含部分,这样就不再需要重写复杂的代码了。 如 果您的应用程序在同一个操作中需要访问多种资源,您就要使用两阶段提交事务。例如,如果从 JMS 队列中删除一个消息,并且随后更新基于这条消息的纪录,这时,要保证这两个操作都会执行或都不会执行就变得尤为重要。如果一条消息已经从队列中被删除,而 系统没有更新与此消息相关的数据库中的记录,那么这种系统是不一致的。一些严重的客户及商业纠纷源自不一致的状态。 我 们时常看到一些客户应用程序试图实现他们自己的解决方案。也许会通过应用程序的代码在数据库更新失败的时候“撤销”对队列的操作。我们不提倡这样做。这种 实现要比您最初的想象复杂得多,并且还有许多其他的情况(想象一下如果应用程序在执行此操作的过程中突然崩溃的情况)。作为替代的方式,应该使用两阶段提 交事务。如果您使用 CMT,并且在单一的 CMT 中访问两阶段提交的资源(例如 JMS 和大多数数据库),WebSphere 将会处理所有的复杂工作。它将确保整个事务被执行或者都不被执行,包括系统崩溃、数据库崩溃或其他的情况。其实现在事务日志中保存着事务状态。当应用程序 访问多种资源的时候,我们怎么强调使用 CMT 事务的必要性都不为过。如果您所访问的资源不支持两阶段提交,那么您当然就没有别的选择了,只能使用一种比较复杂的方法,但是您应该尽量避免这种情况。
只有在需要多种表示输出类型,并且输出类型被单一的控制器及后端支持时才使用 XML/XSLT。 问 题是既然给予了这种灵活性,开发人员就会利用这种灵活性。尽管每个人都认同 JSP 使开发人员容易在视图中加入“类似模型”的行为,而实际上,在 XSL 中也有可能做出一些同样的事情。尽管从 XSL 中进行访问数据库这样的事情会非常困难,但是我们曾经见到过一些异常复杂的 XSLT 样式表执行复杂的转换,这实际上是模型代码。 然而,应该选择 JSP 作为首选的表示技术的最基本的原因是,JSP 是现在支持最广泛的、也是最被广泛理解的 Java EE 视图技术。而随着自定义标记库、JSTL 和 JSP2.0 的新特性的引入,创建 JSP 变得更加容易,并且不需要任何 Java 代码,以及可以将模型和视图清晰地分离开。在一些开发环境中(如 IBM Rational Application Developer)加入了对 JSP(包括对调试的支持)的强大支持,并且许多开发人员发现使用 JSP 进行开发要比使用 XSL 更加简单,主要是因为 JSP 是基于例程的,而不是基于规则的。尽管 Rational Application Developer 支持 XSL 的开发,但一些支持 JSP 的图形设计工具及其他特征(尤其在 JSF 这样的框架下)使得开发人员可以以所见即所得的方式进行 JSP 的开发,而使用 XSL 有时不容易做到。 然而,这并不表示您绝不 应该使用 XSL。在一些情况下,XSL 能够表示一组固定的数据,并且可以基于不同的样式表(请参见 [Fowler])来以不同的方式显示这些数据的能力是显示视图的最佳解决方案。然而,这只是一种特殊的情况,而不是通用的规则。如果您只是生成 HTML 来表达每一个页面,那么在大多数情况下,XSL 是一种不必要的技术,并且,它给您的开发人员所带来的问题远比它所能解决的问题多。
11. 当使用 HttpSession 时,尽量只将当前事务所需要的状态保存在其中,其他内容不要保存在 HttpSession 中。 一个常见的问题是使用 HttpSession 缓存一些很容易再创建的信息,如果有必要的话。由于会话是持久性的,进行不必要的序列化以及写入数据是一种很奢侈的决定。相反地,应该使用内存中的哈希表 来缓存数据,并且在会话中保存一个对此数据进行引用的键。这样,如果不能成功登录到另外的应用服务器的话,就可以重新创建数据。(有关更详细的信息,请参 见 [Brown2]。) 当 谈及会话持久性时,不要忘记要启用这项功能。如果您没有启用会话持久性,或者服务器因为某种原因停止了(服务器故障或正常的维护),则所有此应用服务器的 当前用户的会话将会丢失。这是件令人非常扫兴的事情。用户不得不重新登录,并且重新做一些他们曾经已经做过的事情。相反地,如果启用了会话持久 性,WebSphere 会自动将用户(以及他们的会话)移到另外一个应用服务器上去。用户甚至不知道发生了这样的事情。我们曾经见到过一些产品系统,因为本地代码中存在令人难以 忍受的错误(不是 IBM 的代码!)而经常崩溃,在这种情况下,上述功能仍然可以运行良好。
使用某些特性(如 WebSphere Application Server 缓存和 Prepared Statement 缓存)可以极大地提高性能,并且使得开销最小。 作为这个最佳实践的一个示例,在 WebSphere Application Server 中,您应该开启动态缓存,并且使用 Servlet 缓存。系统性能可以得到很大的提高,而开销是最小的,并且不影响编程模型。通过缓存来提高性能的好处是众所周知的事情。遗憾的是,当前的 Java EE 规范没有包括一种用于 Servlet/JSP 缓存的机制。然而,WebSphere 提供了对页面以及片断缓存的支持,这种支持是通过其动态缓存功能来实现的,并且不需要对应用程序作出任何改变。其缓存的策略是声明性的,而且其配置是通过 XML 配置描述符来实现的。因此,您的应用程序不会受到影响,并保持与 Java EE 规范的兼容性和移植性,同时还从 WebSphere 的 Servlet 及 JSP 的缓存机制中得到性能的优化。 从 Servet 及 JSP 的动态缓存机制得到的性能的提高是显而易见的,这取决于应用程序的特性。Cox 和 Martin [Cox] 指出,对一个现有的 RDF(资源描述格式)站点摘要 (RSS) Servlet 使用动态缓存时,其性能可以提高 10%。请注意这个实验只涉及到一个简单的 Servlet,这个性能的增长量可能并不能反映一个复杂的应用程序。 为 了更多地提高性能,将 WebSphere Servlet/JSP 结果缓存与 WebSphere 插件 ESI Fragment 处理器、IBM HTTP Server Fast Response Cache Accelerator (FRCA) 和 Edge Server 缓存功能集成在一起。对于繁重的基于读取的工作负荷,通过使用这些功能可以得到许多额外的好处。(请参见参考资料的 [Willenborg] 和 [Bakalova] 中描述的性能的提高。) 作 为该原则的另一个示例(我们常常发现客户不使用它,仅仅是因为他们根本不知道它的存在),在编写 JDBC 代码时可以利用 WebSphere Prepared Statement Cache。在缺省情况下,当您在 WebSphere Application Server 中使用 JDBC PreparedStatement 时,它将对该语句进行一次编译,然后将其放到缓存中以便再次使用,不仅可以在创建 PreparedStatement 的同一方法中重用,还可以跨程序重用,只要其中使用了相同的 SQL 代码或者另一个 PreparedStatement。省去重新编译的步骤可以极大降低调用 JDBC 驱动程序的次数,并且提高应用程序的性能。要利用这个特性,您只需编写相应的 JDBC 代码以使用 PreparedStatements,而不需要进行任何其他工作。在编写代码时,使用 PreparedStatement 代替常规的 JDBC Statement 类(它使用了纯的动态 SQL),您就可以实现性能的增强,而不会损失任何可移植性。
提供一个 Java EE EAR 和可配置的安装脚本,而不是黑盒二进制安装程序。
设计可使用 WebSphere Application Server Network Deployment 集群的应用程序。 与集群紧密相关的是支持 WebSphere Application Server Network Deployment。如果您正在构建一个应用程序并打算将它卖给其他人,请确保您的应用程序可以运行于 WebSphere Application Server Network Deployment,而不仅仅是单个服务器版本。
致力于构建真正利用 Java EE 功能的 Java EE 应用程序。
更改是在所难免的。安排新的发行版和修复程序更新,以便您的客户能够获得最新的版本。 首先考虑修复程序。IBM 定期发布建议更新, 以修复产品中已发现的错误。尽管不太可能始终运行于最新的级别,但请注意,不要隔得太久。那么究竟“隔多久”是可以接受的呢?对于这个问题没有什么正确的 答案,但是您应该安排好对几个月内的发行版进行修复级别更新。是的,这表示一年要更新好几次。内部开发人员可以忽略某些修复级别,一次仅支持一个修复级 别,以降低测试成本。应用程序供应商则没有这么幸运。如果您是应用程序供应商,那么您同时需要支持多种修复级别,以便您的客户能够将您的软件与其他软件一 同运行。如果您仅支持一种修复级别,那么很可能无法找到同时兼容于多种产品的修复级别。实际上对于供应商而言,最好的方法是使用支持“向上兼容修复程序” 的模型。IBM 使用了这种方法来支持所集成的来自其他供应商的产品(如 Oracle®、Solaris™ 等等)。有关更详细的信息,请参考我们的支持策略。 下 面再考虑一下主要版本更新。IBM 定期地发布新的主要发行版,其中对我们的产品进行了主要的功能更新。我们暂时继续支持旧的主要发行版,但不会太久。这意味着您必须安排从一个主要发行版转 到另一个主要发行版。这是不可避免的,并且应该在您的成本模型中加以考虑。如果您是供应商,这意味着您必须经常地对您的产品进行更新,以支持新的 WebSphere Application Server 版本,否则您的客户将停滞于不受支持的 IBM 产品,我们曾多次碰到过这种情况!如果您正从供应商处购买产品,我们鼓励您要留心您的供应商,以确保他们承诺支持 IBM 产品新的版本。停滞于不受支持的软件是一种非常危险的情况。
17. 在代码中所有关键的地方,使用标准的日志框架记录程序的状态。 这包括异常处理程序。使用像 JDK 1.4 Logging 或 Log4J 这样的日志框架。 在决定了进行日志记录之后,需要选择一种合适的框架。实际上有许多选择,但是我们偏爱 JDK 1.4 Trace API,因为它们已全面地集成到了 WebSphere Application Server 跟踪子系统中,并且是基于标准的。
总之,对于大多数团队而言,只要团队成员能够很好地理解、严格地执行、 并根据特定的技术本质和使用该方法的团队进行适当的调整,那么几乎任何一种方法都是有效的。对于那些尚未采用任何方法、或者那些不能够完全地利用所选方法 的团队,我们建议他们参考一些优秀的著作,如 [Jacobson]、[Beck1] 或 [Cockburn]。另一个有价值的信息来源是最近公布的用于 Eclipse Process Framework [Eclipse] 的 OpenUP 插件。对于这个已经介绍过的主题,我们不想做过多的重复,建议读者参考 [Hambrick] 和 [Beaton2](请参见参考资料)。
在这个简短的摘要中,我们已经向您介绍了 Java EE 中的核心模式和最佳实践,它们使得 Java EE 开发成为一种可管理的过程。尽管我们并没有给出所有在实践中使用这些模式的必要细节,但是我们希望能够给您足够的指点和指导,以帮助您决定下一步要做什么。
感谢所有最初提出这些模式和最佳实践的人(以及下面提到的人),此外还要感谢 John Martinek、Paul Ilechko、Bill Hines、Dave Artus 和 Roland Barcia 对本文的审阅。
|
转自:IBM开发者社区