使用 DB2 pureXML 和 DB2OnRails 构建敏捷的 WEB2.0 应用
2009-11-12 00:00:00 来源:WEB开发网引言
Web2.0 这个词汇在当下这个时候算是足够流行的了,对于很多人来讲,它可能就像一座金矿,因为有不少的风险投资人正在虎视眈眈地看着互联网上又出现了哪些新奇有趣的应用值得去烧钱。在这篇文章里,我不想谈论如何吸引风险投资人的注意,但是我讲的东西确实可以提高你圈到那些钱的概率 --- 以最敏捷的方式实现你脑中的想法。
当然,这些想法的实现最终还是要靠代码一行行地堆出来。但是随着新技术的不断出现,程序员手头上已经有越来越多可以利用的东西可以大大节省这个时间,并且一些以往通常被认为实现起来比较困难的需求也可以使用一些工具轻易实现。
当我们可以站在巨人的肩膀上时,何苦还要闭门再造那些已经被大量制造且性能优良的轮子呢 ?
你可以在本文的题目中找到“敏捷”二字,对于本文而言,这个词有着多重含义。首先在技术上,本文所提到的技术组合需要更少的代码,对变化和需求的扩展具有更方便快捷的响应能力。对于成本来说,本文提到的技术都可以免费获得和使用,它保证了你在选择使用该技术之前不需要经过漫长的考虑 --- 不管是个人的思想斗争还是公司冗长的决策过程 ---,通常在这个充斥着各种新奇的想法的互联网时代,先发制人就已经大大提高了你的圈钱概率。
对于本文想向您推荐的技术组合,您已经在题目中看到了,他们是 DB2 PureXML 和 Ruby On Rails. 在第二节中有对这两个技术大体情况的简单介绍。
为了向你证明这种技术组合的真正“敏捷”,我会本文中向你展示一个真正有趣的网络应用的开发过程。基于该应用的一些特点,我想它够格被称为是一个 WEB 2.0 应用。在第三节,你可以看到对这个应用需求的详细描述。第四节用来说明真正开发前的准备工作,即如何搭建开发环境。而最后的第五节,我将详细描述如何一步步搭建这个应用。你会发现,这是一个轻松且有趣的过程。
一些相关知识
IBM DB2 Express-C
IBM 的 DB2 Express-C 最新版本为 9.5,它与用于大型应用的企业版本 (Enterprises Edition) 具有相同的公共代码库,是 IBM 专门为其合作伙伴和开发社区设计的。DB2 Express-C 具有企业版本所具有的大多数功能,例如对 PureXML 的支持等,其具有的纯正 DB2 核心和对部署平台的极低限制(没有数据库大小限制,没有自动管理或工具限制,没有内存模型限制等等)使其成为开发人员、中小型应用部署的首选,当然,最重要的是 --- 它是免费的。
而正因为其与 DB2 的同根性,当需要时,部署在其上的应用可以被非常方便地移植到企业版本 DB2 上来。这种很强的扩展性同时可以保证当业务大量扩展后的需要。关于 IBM DB2 各个版本之间的对比,可以参考列于参考资料中的《哪一个分布式 DB2 9.5 版本适合您?》。另外,你还可以在参考资料中找到它的下载页面。如果你在下载、安装或试用过程中遇到了问题,亦或你想获得关于这个版本 DB2 的最新消息,它的社区就是最好的地方了。通常开发人员经常出没于上面并积极解答用户提出来的问题。如果你正在试用 Ubuntu,你可以访问参考资料中列出的 Ubuntu Linux 的 DB2 页面,Canonical 已经和 IBM 合作制作了专门用于 Ubuntu 上面的安装包,如果你愿意付费,还可以获得到一个更为强大的 IBM DB2 Express-C 和来自 Canonical 和 IBM 方面的官方服务支持。
DB2 PureXML
DB2 从 Viper 版本开始提供了对 XML 数据类型的支持,用户可以使用 DB2 来储存和查询纯 XML 数据。最重要的是,这种支持是内建于 DB2 的,它与以往的解决方案相比具有更好的性能和更强大的功能。这就是 DB2 的 PureXML 技术。
XML 数据现在已经充斥于互联网之上。它的应用大大加强了应用的扩展性并且得益于其得到广泛支持的标准化和相关技术的应用,应用之间的互通互联也成为可能。基于这些优势,已经有越来越多的 WEB2.0 应用用它来存储相关的数据或作为数据通讯的协议。
更多的关于 PureXML 的资料,可参考本文的参考资料。
Ruby On Rails
现在 ROR(Ruby On Rails) 已经不仅仅在那些技术偏执狂和懒人中流行。随着 37signals 公司的成功和网上“使用 ROR15 分钟开发一个 BLOG 系统”视频的惊现 ,,已经有越来越多的人 --- 包括开发人员跟那些头脑中总是有些新鲜主意的家伙 --- 开始注意到它,它为 WEB 开发带来了革命性的变革。
抛开那些浮躁的喧嚣,ROR 在其自身架构的设计和提高开发效率上确实很有过人之处。且随着 Rails 2.0 的发布和越来越多成功案例的公布,Ruby On Rails 已经开始成为构建企业应用和大用户量互联网应用的备选方案之一。
IBM_DB
IBM_DB Adapter 是一个由 IBM 官方开发并维护的用于 Ruby 的 DB2 驱动。实际上,它的开发人员就是 DB2 的开发人员。因此,在性能和对 DB2 的兼容性上,与社区开发的驱动相比,它具有先天的优势。也因此,它总能与 DB2 同步更新以支持 DB2 中的那些令人艳羡的新功能,比如在当前的版本中,它很好地支持了 DB2 Viper 中的 PureXML 功能。实际上,通过 IBM_DB 项目的活跃,也可以看出来,IBM 对 ROR 社区的重视。并且 IBM_DB 本身现在也是 rubyforge 中的一个开源项目,它为使用 ROR 和 DB2 的开发人员和那些想为其他数据库提供驱动程序的开发人员提供了良好的参考。
如果你想获得 IBM_DB 项目的最新现状,可以访问其位于 RubyForge 上的项目主页。并且,在其项目论坛中,开发人员会很及时地回答用户提出的问题。对于 IBM_DB 的一些关于安装和应用的基本问题,它的开发人员创建了一个单独的网站用来发布一些技术文章,你可以访问参考资料中列出的 DB2OnRails 网站得到帮助。
初始需求的提出
Q 是我的一个同事,他可是我们组里每一次活动的组织者。当组里只有 10 来个人的时候,在每次活动前,他都会把大家召集在一起,经过一个大概半小时的头脑风暴,大家还可以得到一个关于活动计划的共识。但是当人数增加到 20 多人的时候,我发现这个会议的时间通常会在一个多小时。而现在 --- 当人数达到 50 多人的时候,这个决策过程通常都会以邮件外加一个人一个人走访的形式完成了,因为 Q 发现在一个 50 多人的会场上,这个决策过程通常都会演变为一场不可控制的争论。
“众口难调”说的就是这种事情。在一个有多人参与的活动中,如何以最小的成本统一大多数人的思想,最终得出一个符合大多数人利益要求的结论,这便是本系统最初的需求来源。基于 Q 为我们大家所做的贡献和他的行为是这个系统的灵感来源,我们把这个小应用命名为:robotQ.。
robotQ 会在得到最初的活动计划信息后不断获取每一个参与者的意见信息,最终得到一份符合大多数人利益要求的详细活动计划。总之一句话,robotQ 需要人的观点作为输入并输出最终形成的活动计划 -- 当然,这个过程需要人的交互。
使用这个应用,活动的发起人只需要在一开始发出活动的初始计划和邀请人,剩下的事情就可以交给 robotQ 去做了,它会不厌其烦地与众位进行“沟通”,直到最后到达计划结束的时间。在最后,它会给出一份考虑了“大多数人”意愿的最优化活动方案。
其实,我们的“调解机器人”很类似于 Ikordo---- 一个已经相当成熟的商务会议规划工具。通过 robotQ,你会发现开发一个类似的 WEB2.0 应用其实是如此轻松,轻松到你完全可以再去考虑如何能够将它做的更“好玩”。
而如何才能够确定这个计划已经得到了最终的结论呢?我想大家应该都有这样的经验 :如果任由各位争吵下去,恐怕永远也不会完结。所以在 robotQ 的世界里,我们要设置一个时间作为 deadline 来进行控制,如果达到了预定的时间,这个计划的讨论就算完结了,就应该有一个最终方案出来。
考虑到用户使用的方便性,我们的 robotQ 会以邮件的形式将发生的事件和最后结果通知给各位应邀者。并且,任何人都可订阅某个选定“计划”的当前状态。
下面我们简单地罗列一下这个应用的功能点,当然,这些就是我们将要去实现的功能:
发起活动
任何人都可以发起活动,发起活动时发起者需要填写活动的时间、地点、其他说明。同时可以多给出几个时间和地点作为选项,供用户投票决定。
无所谓,我都能去
活动参与者接到活动邮件后可选择 " 无所谓,我都能去 "。
无论如何我都不去
活动参与者接到活动邮件后可选择 " 我怎么都不去 "。
选择给出的选项
活动参与者根据给出的选项(如果有)进行选择并提交。
我有更好的选择
活动参与者可以在时间,地点和项目上给出自己的选项并发邮件给所有人进行选择。
改变之前的选择,重新操作
当其他活动参与者添加了自己的选项后,一封新的邮件会发送给其他活动参与者,其他活动参与者可以选择重新选择。
保持原来的选择
当其他活动参与者添加了自己的选项后,活动参与者可以选择保持原来的选择不变。
时间到,统计选择
在指定的统计结束时间到的时候,系统会自动统计每个选项的用户选择率并且将结果发送邮件给所有人。
搭建开发环境
对于一个刚发展起来想要从 WEB 2.0 中分得一杯羹的新公司,实施的成本当然是一个非常重要的部分。免费的东西人人喜欢,在本文中,我将介绍一个完全免费的开发和部署环境 --- 它绝不是只可以用来玩玩而已的玩具。借助于 Linux 平台的稳定和 DB2 的强大,构建于这个平台上的应用完全可以满足于大用户量的访问和将来对扩展的需要。
下表中我列举了 robotQ 的开发和部署中需要的主要软件:
表 1. 开发和部署中需要的主要软件
名称 | 版本 | 主页 | 备注 |
Ubuntu Linux | 7.10 | http://www.ubuntu.com/ | 最流行的桌面 Linux 发行版之一 |
DB2 Express-C | 9.5 | http://www.ibm.com/software/data/db2/express/ | IBM DB2 的免费发行版 |
Ruby | 1.8.6 | www.ruby-lang.org | Ruby 语言当前最新的稳定版本 |
Rails | 2.0 | http://www.rubyonrails.org/ | Rails 框架最新的稳定版本 |
IBM_DB Adapter | 0.9.2 | http://rubyforge.org/projects/rubyibm/ | IBM 以开源形式发布的用于 Ruby 的 DB2 驱动 |
NetBeans IDE for Ruby | 6.0.1 | http://www.netbeans.org/index.html | 由 Sun 公司发布的开源集成开发环境,其对 Ruby 开发的支持非常受 Ruby 程序员的欢迎 |
在这一节中,我会介绍除 Ubuntu Linux 之外那些软件的安装过程并给出一些参考材料。对于 Ubuntu Linux 操作系统的安装,网上已经有足够多用各种语言写就的安装和调优教程了。不管您在安装过程中遇到什么样的问题,都可以在网上得到答案。唯一需要说明的是,在安装完 Ubuntu Linux 操作系统之后,一定要加入一些“源”的地址,否则在使用 "apt-get" 命令安装下面的那些软件时,就会得到错误信息而不能进行下去。关于如何加入“源”以及应该加入哪些“源”和其他一些关于 Ubuntu Linux 的配置方法,可以参考 Ubuntu Linux 的快速设置指南。
安装 Ruby 和 Rails
Linux 上面没有类似 Windows 下的 one-click installer, ,但是实际上通过几条命令进行的安装,速度也并不一定比 Windows 上慢。
首先,当然是安装 Ruby,您可以打开 Ruby 官方网站的下载页面,那里介绍了在各种平台下安装 Ruby 的方法。当然,也包括了 Ubuntu 下的安装命令:
% sudo apt-get install ruby ruby1.8-dev irb rdoc build-essential
这条指令会安装 Ruby 的最新稳定版本 1.8.6 以及交互式 Ruby--IRB 和 Ruby 的 API 文档。Rdoc.ruby1.8-dev 和 build-essential 包中的一些类在之后安装 IBM_DB adapter 时会用到。同时,程序会自动安装必须的其他程序包。需要说明的是,在执行这条语句之前,一定要保证在 Ubuntu 中添加了“源”的地址,否则就不会成功。
安装 gem,gem 是 Ruby 下一个非常方便的程序包管理组件,使用 gem 可以非常方便地安装 ruby 下绝大多数的常用软件包 ( 类似 Ubuntu 下的 apt 命令了 )。使用下面的命令安装 gem:
% sudo apt-get install rubygems
如果 gem 安装成功,就可以使用 gem 安装其他的 Ruby 程序包了。首先,我们使用 gem 来将 Ruby 中所有的程序包更新到最新版本并删除不会使用的旧版本:
% sudo gem update --system
在这一步的时候,很多人都会碰到一个下面的错误:
“(Gem::GemNotFoundException) Could not find rubygems-update”
其实这个错误并不那么高深,可能是网络问题吧,你只要多执行几次该命令,就会成功了。
接下来,是安装 Rails 了,虽然 Ruby 语言本身借着 Rails 的光芒大放异彩,但毕竟 Rails 还是 Ruby 语言之下的一个 WEB 开发包。
% sudo gem install rails –include-dependencies
我们用上面的命令来安装 rails 及其必须的依赖包。如果你上面几步都严格按照本教程来做,那么恭喜你,你在这个时刻会得到另外一个错误:
/usr/bin/gem:23: uninitialized constant Gem::GemRunner(NameError)
如果你是用 apt 命令来安装的 gem,通常情况下都会遇到这个错误,幸运的是,修正它并不复杂,只需要编辑 /usr/bin/gem 文件,并在 require ‘rubygems’之后加一行:
require ‘rubygems/gem_runner’
然后再从新执行然后再重新执行 rails 的安装命令,就可以成功了。如果你想了解更多关于这个错误的故事,可以参考列在参考资料中的“官方论坛上的讨论”。
安装 DB2
DB2 Express-C 的最新版本是 9.5,在安装之前,首先要安装两个 DB2 依赖的程序包,可以通过以下命令进行安装:
$ sudo apt-get install libstdc++5
$ sudo apt-get install libaio-dev
然后就可以下载 DB2 Express-C 9.5. ,如果你在下载中遇到问题,可以访问参考资料中给出的 DB2 Express-C 官方论坛,大多数的问题都可以在那里找到答案。将下载到的安装包解压缩后,运行命令进行安装:
$ sudo ./db2setup
接下来就可以按照 DB2 的安装向导一步步进行下去,大多数的选项选择默认值就可以,这里要特别说明一个需要注意的地方,在 Install Type 窗口中,要注意选择为 custom 类型,然后在接下来的 Features 窗口中,要把“Application Development Tools”下的“Base application development tools”选中。如下图所示:
图 1. DB2 Installation type 窗口
图片看不清楚?请点击这里查看原图(大图)。
图 2. DB2 Features 窗口
图片看不清楚?请点击这里查看原图(大图)。
做了这一步,才能保证下面的 IBM_DB Adapter 能够成安装。
至于 DB2 安装的其他部分,都可以接受默认值进行。在 DB2 安装过程中的其他选项,可参考资料中的“安装文档”。
安装 IBM_DB adapter
假设在上面的一步中安装的 DB2 创建了一个名为 db2inst1 的实例,且其 home 目录位于 /home/db2inst1,,那么需要执行以下的命令来进行 IBM_DB 的安装:
清单 1. 安装 IBM_DB adapter
$ . /home/db2inst1/sqllib/db2profile
$ export IBM_DB_DIR=/home/db2inst1/sqllib
$ export IBM_DB_LIB=/home/db2inst1/sqllib/lib
$ sudo gem update
$ sudo gem install ibm_db --include-dependencies
不出意外的话,到此为止,DB2_DB 的 0.9.2 版本及其相应的 rdoc 文档和 ri 文档都已经正确安装上了。
在安装过程中遇到的问题,可访问参考资料中的 db2onrails 网站获得更加详细的安装和配置资料,或是访问 IBM_DB 官方论坛直接获取开发人员的帮助。
安装开发工具 ---NetBeans IDE
NetBeans IDE 是 Sun 公司支持开发的集成软件开发工具,其对 Ruby 和 Ruby On Rails 的支持已经获得了越来越多 ROR 开发者的肯定。首先在其下载站点下载其专门的 Ruby 版本。当然,如果你还希望用其进行其他语言的开发,如 C++ 或 Java,还可以下载其相应的版本。不过据笔者个人使用经验来看,其提供的功能和基于其上的插件资源还与 Eclipse 具有一定的差距。
下载后 ,,Linux 的文件是一个 .sh 的文件,将其权限改为可执行,然后执行这个文件,按照向导提示一步步安装 netbean。安装过程中,如果没有特殊的需要,接受默认值就可以了。安装完成后,进入安装目录下的 bin 目录,执行 netbean 命令打开 netbean 编辑器。
创建工程
在使用 netbean 创建和维护 ROR 工程时,因为有可能会访问 Ruby Gem, ,所以这些操作需要具有故管理员权限的用户执行。为了避免麻烦,我们就用具有管理员权限的用户来运行netbean 开发工具 ( 如无特殊说明,本文中命令执行位置均为命令文件所在的位置 ):
sudo ./netbean
在打开的 netbean IDE 中,选择文件--新建项目,然后通过一个向导设置新工程的参数并创建新功能。这个创建新工程的向导如下:
图 3. 选择项目
图片看不清楚?请点击这里查看原图(大图)。
图 4. 设置名称和位置
图 5. 安装 Rails
在第一步和第二步中,可根据实际情况对项目进行设置。需要说明的是,在第二步设置数据库时,因为在选择框中并没有 DB2 这一选项,所以我们在这一步中选择 MySql 数据库,在项目建立好后再修改相应的配置文件将使用的数据库指定为 DB2。在第三步中,我们当前的 Rails 已经是最新版本,所以不用再更新 Rails 了。完成这个向导后,点击 " 完成 " 按钮。之后便可以看到 IDE 下部出现的一系列创建操作。实际上,走过这个向导,就相当于在命令行中执行了如下的 Rails 命令:
rails robotQ
接下来创建整个应用的数据库表。这是一个非常简单的小应用,它简单到甚至只需要一个表就可以满足所有的需求 --- 当然,这还要得益于使用 XML 存储了大量的信息:
表 2. Plan 表结构说明
字段名 | 类型 | 说明 |
Id | Integer | 该表主键 |
Name | Varchar(200) | 该活动计划的名称 |
description | Varchar(2255) | 该活动计划的简短描述 |
endDate | Datetime | 该活动计划截止时间 |
content | Xml | 该活动计划的具体内容,包括了活动的时间、地点、人物信息。 |
接下来,我们创建 ROR 中的 Migration 脚本,Controller 和 Model. 。而这一切,我们可以通过一个 scaffold((以前被称为 scaffold_resource)生成器一次性搞定。而且,通过这个生成器生成的代码还是 REST 风格的(又一个当前炙手可热的新技术)。在 Netbean 中,我们可以右击项目名,选择“生成”,然后通过如下的生成器向导来生成我们所需要的一切:
图 6. Netbean 中的 Rails 生成器
点击确定后,可以在 IDE 下方的输出窗口中看到如下的文件改动。
清单 2. 查看Rails 生成的文件 exists app/models/
exists app/controllers/
exists app/helpers/
create app/views/plans
exists app/views/layouts/
exists test/functional/
exists test/unit/
create app/views/plans/index.html.erb
create app/views/plans/show.html.erb
create app/views/plans/new.html.erb
create app/views/plans/edit.html.erb
create app/views/layouts/plans.html.erb
create public/stylesheets/scaffold.css
dependency model
exists app/models/
exists test/unit/
exists test/fixtures/
create app/models/plan.rb
create test/unit/plan_test.rb
create test/fixtures/plans.yml
create db/migrate
create db/migrate/001_create_plans.rb
create app/controllers/plans_controller.rb
create test/functional/plans_controller_test.rb
create app/helpers/plans_helper.rb
route map.resources :plans
在窗口上的这一系列点击操作等同于在命令行下输入如下的 Rails 命令:
./script/generate scaffold plan
可见,这个生成器已经为我们创建好了从最后面的数据库 Migration 脚本到最前端的 View 页面在内的所有文件,我们接下来的工作,就是在这些已经生成的文件中填空了。
接着修改刚刚自动生成的 db/001_create_plans.rb 加入创建 plan 表的语句。
清单 3. 加入创建 plan 表的语句class CreatePlans < ActiveRecord::Migration
def self.up
create_table :plans do |t|
t.column :name, :string, :null=>false, :limit=>200
t.column :description, :string, :null=>false
t.column :endTime, :datetime, :null=>false
t.column :content, :xml, :null=>false
end
end
def self.down
drop_table :plans
end
end
现在是时候修改项目的数据库配置文件以让我们刚刚创建的项目能够通过 IBM_DB adapter 连接 DB2 数据库了。
在刚才通过 netbean IDE 建立项目的时候,由于列表中并没有 DB2 的选项,我们只能选择了生成 MySql 类型的数据库配置文件。下面我们编辑位于项目根目录下的 config 目录中的 database.yml 文件,将其内容修改为如下内容。
清单 4. 修改 database.yml 文件内容development:
adapter: ibm_db
database: robotQ
username: db2inst1
password: passw0rd
host: localshost
port: 50000
schema: robotQ
test:
adapter: ibm_db
database: robotQ
username: db2inst1
password: passw0rd
host: localshost
port: 50000
schema: robotQ
production:
adapter: ibm_db
database: robotQ
username: db2inst1
password: passw0rd
host: localshost
port: 50000
schema: robotQ
为了简便起见,在这个例子中,我们将开发数据库、测试数据库和产品数据库设置为同样的数据库。可以看到,在上面的数据库配置文件中,我们指名了使用 ibm_db 为数据库适配器,并且指定了数据库的名字为 robotQ, ,连接数据库的用户名 ( 也就是安装数据库时建立的实例 ) 为 db2inst1。其他诸如密码、端口等等,都需要根据自己的实际开发环境进行配置。
Migration 脚本可以自动创建需要的数据表,但是数据库本身还是要我们自己来创建的:
$ su - db2inst1
$ db2 create db robotQ using codeset utf-8 territory us
DB20000I The CREATE DATABASE command completed successfully.
接下来,执行 rake 操作,将 migration 脚本中指定的数据库结构写入数据库中。通过 netbean,,可以在项目名称上点击右键,然后选择“运行 rake 任务-db-migrate”. 。如果执行有问题的话,还可以在命令行下执行“rake db:migrate””, ,ROR 会自动调用这个 migration 脚本创建相应的数据库对象。
下面是命令执行后的输出结果:
清单 5. 命令执行后的输出结果== CreatePlans: migrating =======================================
-- create_table(:plans)
-> 0.4220s
== CreatePlans: migrated (0.4220s) ===============================
至此为止,你已经拥有了结构定义完备的数据库表,用于数据库维护的 migration 脚本,直接对应于 plans 表的 model 代码以及具有 REST 风格的 controller。
在后续的文章中,我们将进行实际的开发工作,来实现在本文开始处定义的 8 条需求。并且,你将看到,结合 DB2 PureXML 和 ROR 强大的 WEB 开发能力和 XML 处理能力,构建一个强壮的 WEB2.0 应用将是如此敏捷。
更多精彩
赞助商链接