跳转到主要内容

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

当您初次登录到 developerWorks 时,将会为您创建一份概要信息。您在 developerWorks 概要信息中选择公开的信息将公开显示给其他人,但您可以随时修改这些信息的显示状态。您的姓名(除非选择隐藏)和昵称将和您在 developerWorks 发布的内容一同显示。

所有提交的信息确保安全。

  • 关闭 [x]

当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

所有提交的信息确保安全。

  • 关闭 [x]

优化 Project Zero 和 WebSphere sMash 应用程序的数据库配置和依赖项

有关如何管理 Web 2.0 组件的数据库需求的实际建议

Dan Jemiolo, 顾问软件工程师, EMC
Dan Jemiolo 是 IBM 位于美国北卡罗来纳州 Research Triangle Park 的 Autonomic Computing 团队中的一名顾问软件工程师。他负责 Apache Muse 2.0 的设计和开发而且现在还在为此项目工作。Dan 还参与过 WS-RF TC,担任 WS-ResourceMetadataDescriptor 规范的编辑,他亦参与制订过 IBM 在更多地采用 Web 服务标准方面的策略。从 Rensselaer Polytechnic Institute 获得了理学硕士学位之后,他加入 IBM 刚刚两年。

简介: Project Zero 开发平台包括一个易用的数据访问库以让开发人员能够从其应用程序代码进行极少的配置即可执行 SQL 语句。实际上,设置数据库并连接到此数据库所需的只是一个四行的配置文件和一些基本的 SQL 知识,这二者都不会给 Web 开发人员增加太多负担。但即便数据库驱动的开发如此简单,围绕数据库驱动组件的包装还是存在很多问题,这些问题需要大量的关注:没有合适的设计,Zero 组件就有可能会拖累依赖项,而且会做出其他开发人员无法接受的假设。本文讨论了配置和包装数据库驱动组件的最佳实践,以使这些组件可以为其他 Zero 开发人员所用。

发布日期: 2007 年 9 月 24 日
级别: 中级
访问情况 : 1531 次浏览
评论: 


开始之前

本文假设您已经下载了 Project Zero并且或者完成了 “用 Project Zero 开发应用程序” 入门教程或者自己编写过简单的应用程序。您应该对 Zero 数据访问库(称为 zero.data)和 Apache Ant十分熟悉。您也应该使用如下数据库产品进行开发:

更多信息,请参阅 参考资料

简介

当包装 Zero 组件以便在产品系统中使用时,数据库配置就显得至关重要。没有合适的设计,Zero 组件就有可能会拖累依赖项,而且会做出其他开发人员无法接受的假设。如果 Zero 组件在不提取其内容和处理配置文件和脚本的情况下无法使用,那么它就不会被广泛重用。即便假设软件许可允许这么做,也很少有开发人员愿意担负起更改第三方代码的责任。本文如下的章节着重介绍了 Zero 组件的三个方面:配置文件、库依赖项和表创建,对 Zero 组件可进行优化以让它对数据库不可知、对用户友好。

优化配置文件

需要在 Zero 配置文件中指定组件的数据库连接的细节,包括驱动程序名称、数据库位置和身份验证信息。这可以在应用程序目录 /config/zero.config 下找到。清单 1 显示了一个可用于 blog 组件的示例 zero.config 文件,该组件使用了 Apache Derby 数据库:


清单 1. 带数据库配置的示例 zero.config 文件
				
 [/app/db/blog/config] 
 class=org.apache.derby.jdbc.ClientDataSource 
 serverName=localhost 
 portNumber=1527 
 databaseName=BlogDB 

这类组件的实现代码通过调用 zero.data 的 Manager.create()方法并将数据库配置的名称传递给它(例如 Manager.create("blog"))来访问数据库。

清单 1 中代码对于初始开发和测试而言很好,但现在的情况是我们已经将数据库名称和数据库产品硬编码了我们的实现当中。如果有人想要在应用程序中重用我们的组件,他 / 她就必须要创建新的数据库实例(“blog”),而不能重用现有的数据库。如果他 / 她还没有使用我们的数据库产品,那么他 / 她就必须要安装和部署此数据库产品。在大多数产品环境中,这两个需求都非入门者所能处理得了的。部署人员也不可能为每个 Zero 组件都提供其自身的数据库,他们也不能为了一个组件而安装和维护额外的产品。简言之,配置必须要充分灵活以便能够适应用户的数据库环境,否则您的代码将得不到使用。在本节,我们修改了 zero.config 文件以使其能更好地适应新的环境。

删除硬编码的数据库名称

通向灵活性的第一个也是最容易的步骤是从面向数据库的代码中删除硬编码的数据库名称。清单 2 所示的代码设置了 blog 组件的 dbKey属性值,该值可以在运行时利用 Zero 的 GlobalContextAPI 读取:


清单 2. 配置数据库名称
				
 [/app/blog] 
 dbKey=blog 

有了这个属性之后,我们就可以更改代码以使用 Manager.create(app.blog.dbKey)而非 Manager.create("blog")。具体化数据库名称会让用户更容易对之进行更改,而无需在整个代码中搜寻。

但我们还可以做得更好。dbKey属性的值既可以是数据库的名称,也可以是 defaultDB,后者是个特殊的值,它告知 zero.data 库去使用应用程序的数据库配置。而这正是我们所希望的!如果其他 Zero 开发人员将 blog 组件添加到其应用程序,他们可以在其应用程序的 zero.config 文件中重写我们的 dbKey值,只需将该值设成 defaultDB即可,如清单 3 所示:


清单 3. 重写数据库名称
				
 [/app/blog] 
 dbKey=defaultDB
			

现在我们获得了一个很好的平衡:在开发和测试期间,组件使用 blog数据库;在部署期间,我们的用户可以在其自己的 zero.config 文件中重写此名称以便它们可以匹配其数据库设置。

动态数据库配置

我们的数据库名称现在是动态的,不过 blog 组件在其 zero.config 文件中有专门特定于我们数据库设置的信息。清单 1包含了特定于 Apache Derby 的一些设置,但即便如此,我们的 blog 组件仍可以很好地工作于 IBM DB2 或 MySQL,那么我们为何还要限制自己呢?

让配置动态化的第一个步骤是将配置从我们的 zero.config 文件中拉出。我们可以将 清单 1中的文本放入另一个名为 data.config 的文件并将该文件包括到原始的 zero.config 文件,所使用的语法如清单 4 所示:


清单 4. 提取数据库配置
				
 [@include data.config] 

对于那些更小的、永远都不会作为单独应用程序使用的组件,我们完全可以到此为止。在将此组件包装以便重复分发之前,我们所需做的只是注释掉 @include行,但前提是用户应用程序会提供我们所需的数据库配置。大功告成!

然而,还有很多的组件类型都是复杂应用程序的有用构建块,而同时又可以用作更复杂的应用程序本身。我们的 blog 组件就是这样一个很好的例子。有许多网站只有博客功能(例如 blogger.com)。而另一些网站,博客功能只是其用户体验的一部分(例如 MySpace)。如果用户希望将这类组件用作独立的应用程序,那么这类组件就必须具有动态设置数据库配置的能力。最理想的情况是此组件可以作为其安装过程的一部分来配置其数据库需求,而安装过程是用户通过使用 Zero 命令行界面发起的。

由于我们的数据库信息存在于单独的文件中,所以添加动态数据库配置非常容易实现。每个 Zero 组件都有一个 Apache Ant 文件(build.xml),可用来调用 Zero 命令行界面,可使用它来添加动态构建和部署逻辑。我们下一步要做的是添加 Ant 目标,这些目标可以针对用户数据库生成合适的 data.config 文件。您可以将清单 5 所示的 Ant 目标添加到 blog 组件的 build.xml 文件:


清单 5. 用来生成 data.config 文件的 Ant 任务
				
 <property name="config-file" value="config/data.config"/> 
    
 <target name="create-derby"> 
  <echo file="${config-file}"> 
  [/app/db/blog/config] 
  class=org.apache.derby.jdbc.ClientDataSource 
  serverName=localhost 
  portNumber=1527 
  databaseName=BlogDB 
  </echo> 
 </target> 
	
 <target name="create-mysql"> 
  <echo file="${config-file}"> 
  [/app/db/blog/config] 
  class=com.mysql.jdbc.jdbc2.optional.MysqlDataSource 
  serverName=localhost 
  portNumber=3306 
  databaseName=BlogDB 
  </echo> 
 </target> 
	
 <target name="create-db2"> 
  <echo file="${config-file}"> 
  [/app/db/blog/config] 
  class=com.ibm.db2.jcc.DB2DataSource 
  serverName=localhost 
  portNumber=50000 
  databaseName=BlogDB 
  </echo> 
 </target> 
     

清单 5为我们想要提供支持的三个数据库中的每一个都添加了一个目标。而每个目标都会创建一个具有特定于供应商设置的 data.config 文件。已经下载了我们的 blog 组件的用户若想将该组件作为单独的、受 Apache Derby 支持的应用程序加以运行,就需要发出清单 6 所示的命令:


清单 6. 运行 Ant 任务以创建面向 Apache Derby 的 data.config
				
 $ zero resolve 
 $ zero create-derby 
 $ zero run 

DB2 和 MySQL 用户则会针对其各自的目标替代 create-derby

至此,我们已经尽可能灵活地完成了我们的数据库配置来满足我们潜在用户的需求。接下来让我们来看看不必要的依赖项所存在的问题。

优化依赖项列表

要构建和测试数据库驱动的代码,就需要向可提供必要的 JDBC 驱动程序的组件中添加库。比如,如果所支持的是 Apache Derby 数据库,就需要使用 derbyclient.jar 文件,此文件在每个 Derby 发布中都会包括(在本节中,我们将继续使用 Derby 作为我们的示例数据库,但给出的建议也同样适合于其他的数据库产品)。包含 JDBC 驱动程序的 JAR 文件可以放置于组件的 /lib 目录,也可以使用 Apache Ivy 在构建过程中加以 发现。在前一种情况,安装十分简单:将 JAR 文件复制到合适的目录即可;在第二种情况下,则需要向位于 /config/ivy.xml 的组件的 Ivy 文件添加一个条目。清单 7 给出了这样的一个条目:


清单 7. 面向 Apache Derby 的 JDBC 驱动程序的 Ivy 条目
				
 <dependency name="derbyclient" org="org.apache.derby" rev="10.2+"/> 
     

不管何种情况,都会向组件添加一个依赖项,而这会影响到用户。MySQL 用户将不会想让 Derby 驱动程序包括到其应用程序中,而反之亦然。未使用的依赖项可能不会对应用程序的准确性有任何影响,但它们的确会影响应用程序的大小和许可。任何人可能都不想使自己的组件看起来十分 “臃肿”,亦不想让其由于法律方面的原因而被禁止。为了避免这些问题,就需要将开发人员的需求和用户的需要分离开来。

将细节留给开发人员

当我们刚刚开始修改 zero.config 文件时,我们的目的是将尽量多的配置留给用户以不使自己陷入困境。我们在处理依赖项管理时仍然采用相同的办法:将必要的 JDBC 驱动程序包括到构建和测试环境中,但不让其出现在最终的发布中。

实现这个目标最简单的方法是添加必要的 JDBC 驱动程序,做法是使用 /lib 目录,然后再在创建发布工件的时候将其排除。Zero 命令行界面有一个 package目标,它会取出组件目录中的所有内容并将其添加到一个 ZIP 文件;有一点您可能不太知道的是 package目标具有可选的 excludes属性,可用来排除某些文件和目录。清单 8 中的 Ant 目标将 excludes设置成我们想要排除的 JAR 文件的列表,然后调用 Zero 的 package目标:


清单 8. 从组件包中去除驱动程序
				
 <target name="clean-package"> 
  <property name="excludes" value="lib/derbyclient.jar"/> 
  <package/> 
 </target> 
     

可以将此 Ant 目标添加到组件的 build.xml 文件,如同我们处理 清单 5中的目标一样。当我们准备好创建发布文件后,只需运行 zero clean-package,而非通常的 zero package。我们现在就具备了数据库驱动组件,该组件就其配置而言十分灵活且没有任何不需要的文件。

优化特定于供应商的表创建

不幸的是,并不是所有项目都会如此规整,也不会像我们在之前的两个章节中描述的那样简洁。有时,不管如何试图避免,逻辑或配置仍 必须要特定于供应商。有关如何编写独立于供应商的 SQL 语句的文章很多,在这里无需重复。相反,我们将重点分析一种无法避免特定于供应商的 SQL 的情况:创建数据库表。在这种情况下, 所具备的 SQL 脚本是您在安装过程中想要运行的,但您并不能提前知道用户将会使用哪个数据库。所幸的是,相应的解决方案并不遥不可及。

Ant 来帮忙(再次!)

清单 5中,我们创建了特定于供应商的 Ant 任务,这些任务都可以在安装时生成特定于供应商的配置文件。我们现在将要对这些任务进行添加,通过执行特定于供应商的 SQL 来创建数据库表。让我们假设我们已经组织好了以数据库产品命名的目录中的所有 SQL 脚本(比如,/sql/derby 和 /sql/mysql)。我们的目标可以利用这一约定通过 Ant 的 sql任务寻找和执行正确的 SQL 脚本。清单 9 给出了 create-derby目标是如何被修改以设置特定于 Derby 的属性的,sql任务会使用这些属性执行正确的脚本:


清单 9. 扩展 Ant 任务以执行 SQL 脚本
				
 <property name="config-file" value="config/data.config"/> 
    
 <target name="create-derby" depends="init-derby, create-tables"> 
  <echo file="${config-file}"> 
  [/app/db/blog/config] 
  class=org.apache.derby.jdbc.ClientDataSource 
  serverName=localhost 
  portNumber=1527 
  databaseName=BlogDB 
  </echo> 
 </target> 
	
 <target name="init-derby"> 
  <property name="db-name" value="derby"/> 	
  <property name="db-driver" value="org.apache.derby.jdbc.ClientDriver"/> 
  <property name="db-jar" value="lib/derbyclient.jar"/> 
  <property name="db-url" value="jdbc:derby://localhost:1527/db/BlogDB"/> 
 </target> 
	
 <target name="create-tables"> 
  <sql driver="${db-driver}" 
    classpath="${db-jar}" 
    url="${db-url}" 
    src="sql/${db-name}/create-blog-tables.sql"/> 
 </target> 
    
     

现在,当部署者运行 zero create-derby时,除了生成 zero.config 文件之外,它还会创建合适的数据库表。我们的 MySQL 和 DB2 目标都可以用相同的方式进行扩展,即通过添加同等的 init-目标。用户现在就可以确保组件的数据库是通过使用对应于其产品的正确语法创建的。惟一的一个缺陷是我们必须为所有的供应商都要发布 SQL 脚本。由于这类脚本通常都是相对较小的文本文件,而且没有许可方面的隐患,因此无需过分担心。

结束语

若要包装 Zero 组件以供其他开发人员重用,需要考虑的事情很多,而其中大多数问题都是由数据库访问引起的。在本文中,您了解了如何减轻开发人员在进行开发时不知不觉为用户制造的一些限制和问题。借助 Apache Ant 和 Zero 命令行工具,就能消除与发布数据库驱动组件相关的大多数常见问题。


参考资料

学习

获得产品和技术

讨论

  • Project Zero 社区站点包含了参加论坛讨论、blog 和 wiki 的邀请。今天就加入吧!

关于作者

Dan Jemiolo

Dan Jemiolo 是 IBM 位于美国北卡罗来纳州 Research Triangle Park 的 Autonomic Computing 团队中的一名顾问软件工程师。他负责 Apache Muse 2.0 的设计和开发而且现在还在为此项目工作。Dan 还参与过 WS-RF TC,担任 WS-ResourceMetadataDescriptor 规范的编辑,他亦参与制订过 IBM 在更多地采用 Web 服务标准方面的策略。从 Rensselaer Polytechnic Institute 获得了理学硕士学位之后,他加入 IBM 刚刚两年。

关于报告滥用的帮助

报告滥用

谢谢! 此内容已经标识给管理员注意。


关于报告滥用的帮助

报告滥用

报告滥用提交失败。 请稍后重试。


developerWorks:登录


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 使用条款

 


当您初次登录到 developerWorks 时,将会为您创建一份概要信息。您在 developerWorks 概要信息中选择公开的信息将公开显示给其他人,但您可以随时修改这些信息的显示状态。您的姓名(除非选择隐藏)和昵称将和您在 developerWorks 发布的内容一同显示。

请选择您的昵称:

当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

(长度在 3 至 31 个字符之间)


单击提交则表示您同意developerWorks 的条款和条件。 使用条款.

 


为本文评分

评论

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Web development, Information Management
ArticleID=257739
ArticleTitle=优化 Project Zero 和 WebSphere sMash 应用程序的数据库配置和依赖项
publish-date=09242007
author1-email=danjemiolo@us.ibm.com
author1-email-cc=weitzelm@us.ibm.com

标签

Help
使用 搜索 文本框在 My developerWorks 中查找包含该标签的所有内容。

使用 滑动条 调节标签的数量。

热门标签 显示了特定专区最受欢迎的标签(例如 Java technology,Linux,WebSphere)。

我的标签 显示了特定专区您标记的标签(例如 Java technology,Linux,WebSphere)。

使用搜索文本框在 My developerWorks 中查找包含该标签的所有内容。热门标签 显示了特定专区最受欢迎的标签(例如 Java technology,Linux,WebSphere)。我的标签 显示了特定专区您标记的标签(例如 Java technology,Linux,WebSphere)。