UML软件工程组织

把您从麻烦中解脱的JNDI在J2EE中的角色 (2)
作者:Kirk Pepperdine Joseph Ottinger
部署人员(Deployer)

这个角色负责部署,这意味着将 EAR 安装到 J2EE 容器(应用服务器)中,然后配置资源(例如数据库连接池),把应用程序需要的资源绑定到应用服务器中的特定资源上,并启动应用程序。

系统管理员(System Administrator)

这个角色负责保证容器需要的资源可用于容器。

角色实战

假设有一个企业应用程序,该应用程序包含一个 Web 应用程序,还有一个负责业务逻辑和持久性的 EJB 组件。开发这个应用程序的组件供应商可能有许多,但是在许多情况下,可以由一个人来承担全部职责。组件可以包含数据传输对象(一个 JAR 文件)、EJB 接口(另一个 JAR 文件)、EJB 实现本身(另一个 JAR 文件),以及用户界面组件 —— servlet、JSP、HTML 页面和其他静态 Web 内容。用户界面组件被进一步打包成 Web 应用程序,其中包含 servlet 类、JSP 文件、静态内容,以及其他必需组件的 JAR(包括 EJB 接口)。

这听起来好像用到的组件太多了,几乎超出了人的想像范围,尤其是在考虑构建一个典型的 Web 应用程序需要使用多少个 JAR 文件的时候。但是,重要的是认识到在这里必须小心地管理依赖性。接口和传输对象是 Web 应用程序和 EJB 实现可以依赖的对象,但是依赖性的方向应该是相同的;还要避免产生循环依赖。J2EE 组件(例如 WAR 文件和 EJB JAR 文件)必须在它们的部署单元之外声明它们在资源上的依赖性。

应用程序组装者负责把 Web 应用程序中的依赖内容包含进来,并把它们整体打包成单个企业应用程序。工具在这里帮助很大。IDE 可以协助创建反映模块和 JAR 依赖性的项目结构,还允许您随意指定包含或排除的模块。

部署人员负责确保部署环境中存在组件所需的资源,并将组件绑定到平台的可用资源上。例如,Web 应用程序中的外部 EJB 引用(部署描述符中的 ejb-ref)就是在此时被绑定到实际部署的 EJB 组件 —— 而且是立即绑定。

外部资源的后绑定

任何不平凡(nontrivial)的 J2EE 应用程序都需要访问描述它期望使用环境的信息。这意味着开发和测试组件时,为了临时测试代码,开发人员要承担一些部署方面的职责。重要的是要理解:这么做的时候,您就走出了开发人员的领域。否则,可以试着依靠 JDBC 驱动程序,或 URL、JMS 队列名称,或者其他具有无意识的、偶尔可能是灾难性暗示的机器资源。

JNDI 前来援助

Dolly 的问题的解决方案是从她的应用程序中清除所有对数据存储的直接引用。没有对 JDBC 驱动程序的引用,没有服务器名称,没有用户名称或口令 —— 甚至没有数据库池或连接管理。Dolly 需要编写代码来忽略将要访问的特定外部资源,只需要知道其他人会提供使用这些外部资源所需的链接即可。这允许部署人员(任何处在这个角色的人)把数据库连接分配给 Dolly 的应用程序。Dolly 没有必要参与其中。(从数据库安全性到遵守 Sarbanes-Oxley 法案,她都没有参与进来,她这样做也有充足的业务理由。)

许多开发人员知道:代码和外部资源之间的紧密耦合是潜在的问题,但是在实践中却经常忘记角色的划分。在小型开发工作中(指的是团队规模或部署规模),即使忽视角色划分也能获得成功。(毕竟,如果应用程序只是个人的应用程序,而且您不准备依靠它,那么把应用程序锁定在特定的 PostgreSQL 实例上也挺好的。)

J2EE 规范要求所有 J2EE 容器都要提供 JNDI 规范的实现。JNDI 在 J2EE 中的角色就是“交换机” —— J2EE 组件在运行时间接地查找其他组件、资源或服务的通用机制。在多数情况下,提供 JNDI 供应者的容器可以充当有限的数据存储,这样管理员就可以设置应用程序的执行属性,并让其他应用程序引用这些属性(Java 管理扩展(Java Management Extensions,JMX)也可以用作这个目的)。

JNDI 在 J2EE 应用程序中的主要角色就是提供间接层,这样组件就可以发现所需要的资源,而不用了解这些间接性。

Dolly 的情况更糟了

现在我们重新来看一下 Dolly 的情况。在其简单的 Web 应用程序中,她直接从应用程序代码中使用了一个 JDBC 连接。参见清单 1,我们可以看出,Dolly 显式地把 JDBC 驱动程序、数据库 URL 以及她的用户名和口令编码到了 servlet 中:

清单 1. 典型(但是不好)的 JDBC 用法:


Connection conn=null;
try {
  Class.forName("com.mysql.jdbc.Driver",
                true, Thread.currentThread().getContextClassLoader());
  conn=DriverManager.getConnection("jdbc:mysql://dbserver?user=dolly&password=dagger");
  /* use the connection here */
  c.close();
} 
catch(Exception e) {
  e.printStackTrace();
} 
finally {
  if(conn!=null) {
    try {
      conn.close();
    } catch(SQLException e) {}
  }
}



如果不用这种方式指定配置信息,Dolly(以及她的同伴们)使用 JNDI 来查找 JDBC DataSource 会更好一些,如清单 2 所示:

清单 2. 使用 JNDI 得到数据源:


Connection conn=null;
try {
  Context ctx=new InitialContext();
  Object datasourceRef=ctx.lookup("java:comp/env/jdbc/mydatasource");
  DataSource ds=(Datasource)datasourceRef;
  Connection c=ds.getConnection();
  /* use the connection */
  c.close();
} 
catch(Exception e) {
  e.printStackTrace();
} 
finally {
  if(conn!=null) {
    try {
      conn.close();
    } catch(SQLException e) { }
  }
}



为了能够得到 JDBC 连接,首先要执行一些小的部署配置,这样我们才可以在本地组件的 JNDI 下文中查找 DataSource。这可能有点烦琐,但是很容易学。不幸的是,这意味着即使是为了测试组件,开发人员也必须涉足部署人员的领地,并且还要准备配置应用服务器。


<<上一页 1 2 3 下一页>>

 


版权所有:UML软件工程组织