技术开发 频道

用 J2EE 1.2 部署多个应用程序

  通过使用这一部署方法,我们将连接到 EmployeeManagement 会话 bean 所需的代码包括到 Benefits 应用程序的 WAR 文件中,而将应用程序分别放在它们自己的 EAR 文件中。在图 2 中说明了这个选项:

  图 2. 共享服务部署

        

  该方法将 EmployeeManagement bean 视为共享服务。将应用程序部署到不同的 EAR 文件中让我们将它们部署到不同的应用程序服务器 JVM 实例中,从而允许我们对每个应用程序分配多少硬件做出不同决定。另外,该方法似乎有助于维护问题 ― 现在我们可以关闭 Benefits 应用程序,而根本不会影响 Timesheet 应用程序。

  然而,我们并没有彻底解决该问题。现在,这两个应用程序之间具有依赖性。虽然我们可以关闭 Benefits 应用程序,但 Timesheet 应用程序现在必须具有与 Benefits 应用程序相同的可用性需求,所以可能会给管理带来麻烦。此外,我们现在必须处理一个 J2EE 1.2 规范未解决的问题:如何将 EJB 存根代码包括在 Benefits WAR 文件中。从理论上讲,我们可以从 Timesheet EJB-JAR 文件分离出客户机代码,但这看起来容易出错并且很可能会造成问题。稍后我们回头讨论这种可能性。

  另一种可能性是将客户机代码放在 EAR 文件之外的共享类路径上,但这种方法不仅违反了 J2EE 规范的精神,而且如果我们选择错误的类路径,那么它会对该应用程序和应用程序服务器本身造成破坏。简而言之,这个解决方案引起的问题比它解决的问题要多得多。

  与合并组件解决方案相比,共享服务部署会降低性能。如果我们选择通过将两个应用程序放在不同 JVM 中来分离它们,那么我们需要一个跨进程调用,而这样的调用本可以由两个应用程序都位于同一个 JVM 的解决方案中的容器进行优化。简而言之,在部署了 EJB 组件的 JVM 内部调用组件比从该 JVM 外部调用组件快好几倍。

  然而,该解决方案还会造成一个更隐蔽的问题,它也出现在上一个解决方案中: 版本漂移。设想一下,在 EmployeeManagement 会话 bean 的初始版本中,我们有一个具有以下特征符的方法:

1 EmployeeVO getEmployeeDetails(int employeeID)
2

  该方法特征符假设 employeeID 为整数,如果它们真的是整数,则工作正常。然而,让我们假设它们进一步受到整数大小的限制 — 一些其它后端数据库需求将雇员标识限制为 6 位数。假设这对于两个应用程序的初始版本运行正常,但是此后有一天我们用完了 6 位整数。作为变通方法,HR 部门对雇员标识规则进行重新定义,使之还可以包括字母字符,从而产生了下面经更改的特征符:

1 EmployeeVO getEmployeeDetails(String employeeID)

  因为 Timesheet 团队开发这个 EJB 组件,所以他们计划更新他们自己的应用程序,以使用新的雇员标识特征符。但是,Benefits 应用程序会怎样呢?假设就在福利签约周期开始之前 Benefits 应用程序一年只推出一个新版本(因为我们只可以在签约周期内更改福利,但我们可以在任何时候查看我们的福利)。如果 Benefits 团队未准备好推出其应用程序的新版本,那么这次对 Timesheet 应用程序的更改将破坏 Benefits 应用程序。

  那么,我们该如何避免 API 版本漂移问题呢?要找到解决方案,我们需要发散性地思考一下。虽然 J2EE 规范可能看上去使我们受困于一系列糟糕的解决方案,但实际上它隐含着很好的思想,使我们能够十分干脆利落地解决这一问题。解决问题的关键是断定逻辑项目块尽可能不要跨越 EAR 文件。让我们研究一下。

0
相关文章