Java开拓2.0 – 通过CouchDB和Groovy的RESTClient实现REST
副标题#e#
今朝为止,本专栏 系列 已经探究了 Google 和 Amazon 平台中的云计较。 固然它们在实现和布局上存在差异,但两种平台都支持快速和可扩展的陈设方法 。它们可以快速经济地组装、测试、运行和维护 Java 应用措施,这无疑是前所 未有的。可是,云并不是影响如今 Java 开拓速度的独一因素。开源办理方案还 可以辅佐您迅速组装软件应用措施,因为您不再需要编写大量代码。手动编写对 象干系映射(ORM)、日志或测试框架的时代已经一去不复返。这些问题已经随 时间逐渐获得了办理,然后又再次呈此刻了开源规模中 — 再次面对这些问题 — 但这些办理方案险些始终要比您本身的好。
关于本系列
从 Java 技能首次表态以来,Java 开拓的名堂已经产生了庞大的变革。得益 于成熟的开源框架和靠得住的租用式陈设基本设施,此刻已经可以迅速经济地装配 、测试、运行和维护 Java 应用措施了。在本系列中,Andrew Glover 将摸索使 这种全新开拓典型成为大概的各类技能和东西。
在 Java 开拓的整个进程中,开源创新简化了应用措施的装配进程。全新的 开源数据库 Apache CouchDB(停止撰写本文时的刊行版为 0.10.0) 也不破例 。搭建好 CouchDB 情况之后可以轻松地利用它。您只需要操纵它的 HTTP 毗连 即可;既不需要 JDBC 驱动措施,也不需要第三方节制打点平台。在本文中,我 将向您先容 CouchDB 并展示如何利用它晋升开拓速度。思量到安装的轻便性, 您将利用 Amazon 的 EC2 平台。而且,您将通过一个利便易用的 Groovy 模块 来与它通信。
面临文档的数据库
干系数据库根基上主导了数据库市场。但其他雷同的数据库 — 包罗 面向对 象 和 面向文档 数据库,两者在面向干系的世界中极为差异 — 也不时发挥着 举足轻重的浸染。CouchDB 是一种面向文档的数据库。它是无模式的,而且答允 您以 JavaScript Object Notation (JSON) 字符串的形式来存储文档。
JSON
JSON 是一种轻量级的数据互换名目,同时也是 Web 应用措施的替代名目。 它雷同于 XML,但远没有它那么具体。得益于其轻量级特性,它正成为 Web 的 通用语。
试想一个违规停车罚单。该罚单将涵盖以下项目:
违规的日期
时间
位置
车辆的描写
牌照信息
违规环境
罚单上收集的名目和数据因统领权而异。纵然对付单一统领权限内的尺度停 车罚单来说,它们的内容也很有大概存在差异。举例来说,警官在开罚单时可以 不填写时间,可能可以省略车型,而只填写牌照的具体信息。所在可以是两条街 道的组合(好比 Fourth 和 Lexington 的交汇处),可能是某个牢靠地点(比 如说 19993 Main Street)。但所收罗信息的语义简陋相似。
罚单的数据点可以在干系数据库中建模,但具体信息却有点贫苦。举例来说 ,如何有效在干系数据库中捕捉某个交汇点呢?而且在没有街道交汇的环境下, 数据库是否会利用空字段来暗示第二个地点呢(假定建模方法为在各列中捕捉不 同的街道名)?
在这些环境下,干系数据库的抽象化水平大概 会稍高一些。所需的信息已经 回收了文档(罚单)的形式。为什么不将数据建模为文档呢?这样可以不消死守 严格的干系模式,而只需要大抵遵循高级模式的语义。这正是 CouchDB 的用武 之地。它答允您以机动的方法来对这些域范例举办建模 — 成就是一个完备的文 档,它没有模式,而是利用与其他文档大抵相似的蓝图。
MapReduce
Google 独创的 MapReduce 是一个用于处理惩罚海量数据集的观念框架。它是一 种高度优化的应用大量计较机的漫衍式问题办理机制。MapReduce 包括两个函数 :map 和 reduce。map 函数用于接管大量输入,并将它们支解为较小的部门( 同时将这些数据通报给其他历程)。reduce 函数的浸染是未来自 map 的所有单 独输出整合为一个最终的输出。
借助 CouchDB,您可以搜索文档、文档属性甚至在干系世界中关联文档。您 的实现方法是利用视图,而不是 SQL。从本质上说,视图是您回收 MapReduce 样式(在 JavaScript 中)编写的函数;也就是说,您最终只需要编写一个 map 函数和一个 reduce 函数。这些函数将配合过滤或提取文档数据,可能有效操作 它们之间的干系。事实上,CouchDB 具备足够的机动性,只要底层文档没有产生 发化,它就只需要运行这些函数一次,从而加速视图处理惩罚进程。
CouchDB 最有意思的处所是它的设计方法。CouchDB 浮现了 Web 自己的根基 (也是极为乐成的)观念。它果真了一组全面的 REST 式 API,答允建设、查询 、更新和删除文档、视图和数据库。这使得 CouchDB 的利用变得很是简朴。您 不需要借助其他驱动措施或平台来开始开拓:一个欣赏器便能完成所有事情。也 就是说,富厚的库使 CouchDB 的利用变得很是简朴 — 但从内部来看,它们仅 仅是通过 HTTP 来操作 REST 式观念。
#p#分页标题#e#
与 Web 的本质特性相雷同,CouchDB 在设计时融入了大量可扩展因素。它是 利用并发编程语言 Erlang 编写的,它支持绑定漫衍式、容错、不中断应用措施 。该语言(现已开源可用)是由 Ericsson 开拓的,并在电信情况中获得了遍及 应用。
#p#副标题#e#
安装 CouchDB,云气势气魄
CouchDB 的安装要领因操纵系统而异。假如使 用的是 Windows®,则需要安装 Microsoft C 编译器 Cygwin,以及其他一 些依赖项。假如利用的是 Mac,则需要利用 Macports。可是,假如利用的是 Linux® 平台,好比说 Ubuntu,则安装要领就不是那么简朴了。但并非所有 人都安装了 Ubuntu 实例吧。您是这样吗?
虽然,您可以利便的获取一个 Ubuntu 实例!Amazon 的 EC2 是一种相对较 为经济的、随需应变地 利用 Ubuntu 的一种要领。因此,只需要施展少许 EC2 邪术,您就可以迅速搭建好 CouchDB 情况;完成后,您可以封锁它(可以这样 说)。
首先,您需要找到一个充当根基实例的 EC2 AMI。我最终抉择使 用 AMI ami-ccf615a5(一个 Ubuntu 9.04 实例),它是停止撰写本文时的最新 版本。(当您阅读本文时,很有大概已经呈现了 9.10 版本的 AMI)。利用 Eclipse 可能 AWS Management Console 启动一个 ami-ccf615a5 实例。确保设 置了答允通过 SSH 会见的安详计策。(固然 CouchDB 利用 HTTP,但思量到简 单性,您将通过一个 SSH 通道来与它通信)。您还需要利用一个值对。(假如 需要指导,请拜见本系列的前两篇文章 “您也可以租用 EC2” 和 “利用利便的 EC2”。)
启动了 Ubuntu 9.04 的 EC2 实例 之后,您需要为它配置 ssh。(记着,该实例约莫要 1 分钟时间才气完全启动 ,因此请耐性期待。)举例来说,我可以打开一个终端并利用 ssh 配置新建设 的实例,如下所示:
aglover#> ssh -i .ec2/agkey.pem [email protected] 167.compute-1.amazonaws.com
我的 AMI 的 DNS 名称是 ec2-174-129-157-167.compute-1.amazonaws.com ,而且我引用的值对的名称是 agkey。您的 DNS 名称和值对必定会纷歧样。
在云 Ubuntu 实例的呼吁提示中,输入:
apt-get update
然后输入:
aptitude install couchdb
这些呼吁会自动安装 CouchDB。可是,留意它们不会安装最新版本。假如需 要最新版本,则需要通过源代码来安装 CouchDB。
呼吁执行竣事后,您可以通过发出 ps -eaf 呼吁来查抄 CouchDB 是否已经 正常运行。通过将 ps 输出通报给 egrep,查察在路径中利用 couchdb 的历程 。您应该能看到如清单 1 所示的输出:
清单 1. CouchDB 正在运行中(各行颠末度段以适应页面宽度)
couchdb 1820 1 0 00:54 ? 00:00:00 /bin/sh -e /usr/bin/couchdb
-c /etc/couchdb/couch.ini -b -r 5 -p /var/run/couchdb.pid -o /
couchdb 1827 1820 0 00:54 ? 00:00:00 /bin/sh -e /usr/bin/couchdb
-c /etc/couchdb/couch.ini -b -r 5 -p /var/run/couchdb.pid -o /
couchdb 1828 1827 0 00:54 ? 00:00:00 /usr/lib/erlang/erts-5.6.5/bin/beam
-Bd -- -root /usr/lib/erlang -progname erl -- -home /v
couchdb 1836 1828 0 00:54 ? 00:00:00 heart -pid 1828 -ht 11
接下来,回到当地呆板,配置一个 SSH 通道来答允会见在云上运行的 CouchDB 实例,就像是在本身的呆板上一样。为此,在当地呆板上打开一个新的 终端会话,然后输入:
ssh -i your key -L 5498:localhost:5984 [email protected] AMI DNS
最后,在当地呆板上打开一个欣赏器。在地点栏中,输入 http://127.0.0.1:5498/。您应该可以看到一个大度的 JSON 接待动静,如下所 示:
{"couchdb":"Welcome","version":"0.8.0-incubating"}
此刻,看上去一切运转正常,接下来可以开始应用 CouchDB 了。
回收 REST 气势气魄利用 Groovy 的 RESTClient
REST
在暗示状态传输(REST)设计气势气魄中,松散耦合的 Web 应用措施将依赖于指 定资源 — 好比回收统一资源定位符(URL)、统一资源标识符(URI)和统一资 源名称(URN)的形式 — 而不是动静。REST 明智地回收了 Web 中颠末验证并 得到了乐成的基本设施 — HTTP。也就是说,REST 将操作 HTTP 协议的各个方 面,好比 GET 和 POST 请求。这些请求将很好地满意业务应用需求,好比建设 、读取、更新和删除(CRUD)。
#p#分页标题#e#
由于 CouchDB 通过以上 REST 式 HTTP 接口来果真数据,因此利用 CouchDB (您已经在欣赏器中见地一二)是相当简朴的。险些所有事情都可以通过 HTTP 来完成。
您可以选择各类东西来与 HTTP 举办交互。在利用 REST 式接口时,我较量 偏幸 Groovy HTTPBuilder 的 RESTClient 扩展。 HTTPBuilder — 针对 Apache Commons Project 的 HTTPClient 的包装器 — 在 HTTP POST、GET、 PUT 和 DELETE 的语法中添加了一些 Groovy 因素。由于 HTTPBuilder 是利用 Groovy 建设的,因此编写操作 REST 式观念的剧本(好比与 CouchDB 通信)都 简朴得不能再简朴了。
Grape 的进一步简化
为了与 Java 开拓 2.0 的一般主题保持一致 — 快速、轻便和免费(或自制 ) — Groovy 的便捷的 Grape(Groovy Advanced Packaging Engine 或 Groovy Adaptable Packaging Engine)特性对付与 HTTPBuilder 这样的交互非 常有用。Grape 是一种依赖项打点器,它答允 Groovy 剧本和类在运行时 自动 设置本身的特定依赖项。这简化了各类开源库的利用,因为您不需要下载各类 JAR 文件便可开始编写代码。举例来说,借助 Grape,您可以编写一个 Groovy 脚原来利用 HTTPBuilder,而不需要 HTTPBuilder 的 JAR。借助 Grape,可以 在运行时或编译时下载它们(通过 Apache)。
您将通过注释和要领挪用来操作 Grape。举例来说,您可以利用 @Grab 注释 来修饰某个要领或类声明。在该注释中,您将主依赖项指定一些相关的元数据( 借助 Ivy 的魔力,所有中间依赖项都可以悉数确定)。在运行时或编译时(无 论孰前孰后),Grape 将下载这些依赖项并确保它们在您的类路径下。假如已经 下载了依赖项(好比说从之前的运行中),则 Grape 仍然会确保类路径下包括 适当的 JAR 文件。
通过 Groovy 简化 CouchDB 的 REST 气势气魄
在可以在 CouchDB 中建设任意文档之前,您必需首先建设一个数据库。要创 建一个停车罚单数据库,可以通过 HTTPBuilder 的域相关语言(DSL)利用其 RESTClient 来发出一个 HTTP PUT,如清单 2 所示。(本文示例中的所有 Groovy 代码都可以从 下载 小节得到。)
清单 2. 建设一个 CouchDB 数据库
import static groovyx.net.http.ContentType.JSON
import groovyx.net.http.RESTClient
@Grab(group='org.codehaus.groovy.modules.http-builder', module='http-builder',
version='0.5.0-RC2')
def getRESTClient(){
return new RESTClient("http://localhost:5498/")
}
def client = getRESTClient()
def response = client.put(path: "parking_tickets",
requestContentType: JSON, contentType: JSON)
assert response.data.ok == true : "response from server wasn't ok"
CouchCB 应该会返回应答 {"ok":true}。如清单 2 所示,在 HTTPBuilder 中可以轻松地理会 JSON 并确保 ok 元素的值确实为 true。
接下来,我们需要建设一些文档,以便与停车罚单的主题保持一致。要成立 一个停车罚单模子,需要记着一些与罚单相关的方面。别的需要记着,由于它们 是警官将填写的实际表单,因此一些字段可以不填可能回收预界说的模式 — 考 虑交汇点与精确所在。
利用 HTTPBuilder,您可以通过 HTTP PUT 在 CouchDB 中建设一个文档(就 像在清单 2 中建设数据库一样)。由于 CouchDB 将处理惩罚 JSON 文档,因此您必 须遵循 JSON 的名称值名目。为此,在 Groovy 中建设一种雷同于映射的数据结 构(HTTPBuilder 会将其转换为有效的 JSON)。如清单 3 所示:
清单 3. 通过 RESTClient建设一个 CouchDB 文档
response = client.put(path: "parking_tickets/1234334325", contentType: JSON,
requestContentType: JSON,
body: [officer: "Kristen Ree",
location: "199 Baldwin Dr",
vehicle_plate: "Maryland 77777",
offense: "Parked in no parking zone",
date: "2009/01/31"])
assert response.data.ok == true : "response from server wasn't ok"
assert response.data.id == "1234334325" : "the returned ID didn't match"
清单 3 完成了多项任务。首先,在为 CouchDB 文档发出 PUT 时,您必需分 配一个 UUID。CouchDB 可觉得您分派这些值,可能您也可以自已打点它们。在 清单 3 中,我设定了一个值(1234334325);随后,该 UUID 将附加到 URL。 假如该 UUID 可用,则 CouchDB 会为它分派执行了 PUT 操纵的文档。在 put 挪用的 body 部门,留意为各名称指定相关值的方法,险些与普通的映射无异。 举例来说,指定警官的名称为 Kristen Ree,而罚单的所在是 199 Baldwin Dr 。
清单 4 回收沟通的能力在 CouhDB 中建设了别的一个罚单:
清单 4. 另一个停车罚单
#p#分页标题#e#
def id = new Date().time
response = client.put(path: "parking_tickets/${id}", contentType: JSON,
requestContentType: JSON,
body: [officer: "Anthony Richards",
location: "Walmart Parking lot",
vehicle_plate: "Delaware 4433-OP",
offense: "Parked in non-parking space",
date: "2009/02/01"])
assert response.data.ok == true : "response from server wasn't ok"
assert response.data.id == "${id}" : "the returned ID didn't match"
每次通过 RESTClient 发出 PUT 时,我都断言 JSON 应答的 ok 值为 TURE ,而且验证是否存在 id 值。留意在清单 4 中,我没有建设 UUID,而是利用了 当前的时间 — 并不长短常简朴的能力,但我已经不再满意于利用简朴的交汇点 。
在 CouchDB 中乐成建设了新文档之后,它会返回一个包括 UUID 和修订 ID 的 JSON。举例来说,该应答暗示我在清单 4 中验证的 JSON:
{"ok":true,"id":"12339892938945","rev":"12351463"}
您的 id 和 rev 值必定纷歧样。留意,我可以通过发出 response.data.id 这样的挪用来捕捉 id 值。
在 CouchDB 中,它将通过修订来跟踪文档,因此您可以返回之前的文档版本 (通过修订 ID),这与 CVS 或 Subversion 中的要领极为雷同。
CouchDB 中的视图
此刻,我已经建设了一些停车罚单(可能,用 CouchDB 的术语来说是一些文 档),接下来可以在 CouchDB 中建设一些视图了。记着,视图就是实际的 MapReduce 函数;因此,您必需界说它们。在很多环境下,您都不需要 reduce 函数;map 函数可以辅佐您完成大大都任务。正如其名,它是任务的映射。举例 来说,您可以映射但愿过滤或查找的任何 “事物” 或方面。
我已经界说了两个罚单:一个由 Officer Ree 开示,而另一个是由 Officer Richards 发出的。举例来说,要查找 Officer Ree 开出的所有罚单,您可以编 写一个 map 函数来过滤相应的 officer 属性。然后,您可以将功效通报给 CouchDB 的 emit 函数。
利用 CouchDB 的打点接口:Futon
您可以通过 CouchDB 的 REST 式 API 或通过 CouchDB 的打点接口 Futon 来界说视图。Futon 仅仅是一个 Web 应用措施,可以从 http://localhost:5498/_utils/ 下载它。当即会见该位置(假定您已经跟从我 建设了数据库和一些文档),您应该能看到一个针对 parking_tickets 的简朴 接口,如图 1 所示:
图 1. Futon 接口
假如选择 parking_tickets 数据库,则随后可以在最右侧看到一个下拉列表 (Select view:)。通过选择 Custom query…来界说一个自界说视图,如图所 示:
图 2. Futon 的视图选择接口
此刻,Futon 接口可答允您界说 map 函数和 reduce 函数。(您大概需要单 击 查察代码 链接)。在 Map 文本框中,界说如清单 5 所示的简朴映射:
清单 5. CouchDB 中的简朴的 map 函数
function(doc) {
if(doc.officer == "Kristen Ree"){
emit(null, doc);
}
}
如您所见,清单 5 中的 map 函数是利用 JavaScript 界说的。它的浸染是 通过文档的 officer 属性来过滤 CouchDB 数据库中的文档。出格需要说明的是 ,仅当警官的名称为 Kristen Ree 时,该函数才会通报一个文档给 emit。图 3 显示了在 Futon 中界说此函数的位置:
图 3. 建设一个 MapReduce 函数
接下来,您需要指定文档名称(输入 by_name)和视图名称(输入 officer_ree)。这些名称将作为成立 URL 以便稍后挪用此视图的途径(该 URL 也就是 http://localhost:5498/parking_tickets/_view/by_name/officer_ree )。
此刻,您可以通过 HTTPBuilder 来利用该视图:
清单 6. 挪用您的新视图
#p#分页标题#e#
response = client.get(path: "parking_tickets/_view/by_name/officer_ree",
contentType: JSON, requestContentType: JSON)
assert response.data.total_rows == 1
response.data.rows.each{
assert it.value.officer == "Kristen Ree"
}
该视图将返回一个 JSON 应答,个中只包括一个文档:Officer Ree 于 1 月 31 日开出的罚单。通过理会相应的 JSON,清单 6 中的 response 工具将埋没 原始 HTTP 应答。您可以通过对 response 的 data 属性挪用 toString 要领来 查察原始 JSON 应答。原始应答将如清单 7 所示:
清单 7. 视图的原始功效
{"total_rows":1,"offset":0,"rows": [
{"id":"1234334325","key":null,
"value":{"_id":"1234334325","_rev":"4205717256","officer":"Kristen Ree",
"location":"199 Baldwin Dr","vehicle_plate":"Maryland 77777",
"offense":"Parked in no parking zone","date":"2009/01/31"}}]}
从返回的原始 JSON 文档中可以看出,HTTPBuilder 可以很是轻松地理会 JSON,因为它支持通过雷同于工具图的机制来预计各类属性及其相应的值。
为便于演示,我将向数据库再添加一些文档。为了跟从示例,您应该利用 代 码下载 完成沟通的任务。
CouchDB 的 emit 函数将充当各类形式的组织器。假如未在 map 函数中添加 限制(像我在 清单 5 中做的那样),则 emit 的根基浸染是对传入文档举办排 序。举例来说,假如您但愿按日期获取所有罚单(此处可看作 SQL 的 ORDER BY 语句),则可以按文档的 date 来执行 emit,如清单 8 所示:
清单 8. 一个较量简朴的 map 函数
function(doc) {
emit(doc.date, doc);
}
清单 9 向此视图发出了一个 HTTP GET(我已经指定 dates 作为设计文档名 ,by_date 作为视图名。)。
清单 9. 挪用的另一个视图
response = client.get(path: "parking_tickets/_view/dates/by_date", contentType: JSON,
requestContentType: JSON)
assert response.data.total_rows == 4
清单中的查询将按日期顺序返回 parking_tickets 数据库中的所有文档。 assert 语句仅验证 total_rows 属性是否便是 4。这是一个要害点。视图将返 回一些功效以及少许元数据(好比说返回文档的数量);因此,它将辅佐在开始 理会之前查察原始应答。清单 10 显示的原始功效:
清单 10. 按日期排序的原始 JSON 文档
{"total_rows":4,"offset":0,"rows":[
{"id":"85d4dbf45747e45406e5695b4b5796fe","key":"2009/01/30",
"value":
{"_id":"85d4dbf45747e45406e5695b4b5796fe","_rev":"1318766781",
"officer":"Anthony Richards",
"location":"54th and Main","vehicle_plate":"Virginia FCD-4444",
"offense":"Parked in no parking zone","date":"2009/01/30"}},
{"id":"1234334325","key":"2009/01/31",
"value":
{"_id":"1234334325","_rev":"4205717256",
"officer":"Kristen Ree",
"location":"199 Baldwin Dr","vehicle_plate":"Maryland 77777",
"offense":"Parked in no parking zone",
"date":"2009/01/31"}},
{"id":"12345","key":"2009/01/31",
"value":
{"_id":"12345","_rev":"1479261876",
"officer":"Anthony Richards","location":"1893 Main St",
"vehicle_plate":"Maryland 4433-OP",
"offense":"Parked in no parking zone","date":"2009/01/31"}},
{"id":"12339892938945","key":"2009/02/01",
"value":
{"_id":"12339892938945","_rev":"12351463","officer":"Anthony Richards",
"location":"Walmart Parking lot","vehicle_plate":"Maine 4433- OP",
"offense":"Parked in non-parking space",
"date":"2009/02/01"}}]}
#p#分页标题#e#
在界说这样的视图时,您可以随后向它通报一个值 — 也就是 emit 函数的 初始值。举例来说,清单 8 中界说的视图主要用于按日期排序。假如但愿按具 体的 日期,则将该日期通报给视图查询。举例来说,可以在欣赏器的地点栏中 输入以下 URL:
http://localhost:5498/parking_tickets/_view/dates/by_date? key="2009/01/31"
然后,这个视图只会返回 1 月 31 日发出的罚单。您应该可以在欣赏器窗口 中看到一些 JSON 样式的文本,它们与清单 11 中的内容相似。留意,利用欣赏 器作为查询东西是查察 HTTP 请求的原始 JSON 应答的一种极其简朴的方法。
清单 11. 1 月 31 日仅开出了两张罚单
{"total_rows":4,"offset":1,"rows":[
{"id":"1234334325","key":"2009/01/31",
"value":
{"_id":"1234334325","_rev":"4205717256","officer":"Kristen Ree",
"location":"199 Baldwin Dr","vehicle_plate":"Maryland 77777",
"offense":"Parked in no parking zone",
"date":"2009/01/31"}},
{"id":"12345","key":"2009/01/31",
"value":
{"_id":"12345","_rev":"1479261876","officer":"Anthony Richards",
"location":"1893 Main St","vehicle_plate":"Maryland 4433-OP",
"offense":"Parked in handicap zone without permit",
"date":"2009/01/31"}}]}
您可以按照需要来定制视图的成果。举例来说,只需要少量 JavaScript 字 符串操纵,我就可以编写一个查找 Main Street 上开出的罚单的视图,如清单 12 所示:
清单 12. 另一个添加了字符串魔力的视图
function(doc) {
if(doc.location.toLowerCase().indexOf('main') > 0){
emit(doc.location, doc);
}
}
可以从清单 12 中看出,假如任何文档的 location 元素包括 main,则该文 档将被通报给 emit 函数。记着,这种搜索相当遍及。假如某文档的 location 包括一个 Germaine Street 这样的字符串,则会返回它。对付我所界说的少量 罚单,视图将返回如清单 13 所示的功效:
清单 13. 按 Main Street 过滤的功效
{"total_rows":2,"offset":0,"rows":[
{"id":"123433432asdefasdf4325","key":"4th and Main",
"value":
{"_id":"123433432asdefasdf4325","_rev":"498239926",
"officer":"Chris Smith","location":"4th and Main",
"vehicle_plate":"VA FGA-JD33",
"offense":"Parked in no parking zone","date":"2009/02/01"}},
{"id":"123433432223e432325","key":"54 and Main",
"value":
{"_id":"123433432223e432325","_rev":"841089995",
"officer":"Kristen Ree","location":"54 and Main Street",
"vehicle_plate":"Maryland 77777",
"offense":"Parked in no parking zone","date":"2009/02/02"}}]}
留意,JSON 应答包括一个 key 元素,用于描写为何要生成特定的文档。这 一方面的信息相当有用。还需留意,我所界说的各类罚单中的数据在一致性方面 做的不是很好:一些所在是精确的,但也有一些是不准确的。固然该数据可以存 储在干系数据库中,但也同样可以利用面向文档的模子。别的,借助 Groovy 和 HTTPBuilder 的高效理会 JSON 的强大本领,可以很是轻松地获取数据(比原始 JDBC 简朴许多)。
CouchDB 作为 Web 数据库
CouchDB 的迷人之处在于它的利用很是简朴。干系数据库也很简朴,但该数据库的优势在于您只需要熟悉 Web 欣赏器就可以把握其 API。另外,由于 CouchDB 提供了 REST 式 API,您可以通过一些炫酷的框架来与其通信,好比说 HTTPBuilder 的 RESTClient。您也不会受制于 HTTPBuilder;各类 Java 库都 在实验简化 CouchDB 的利用。个中很是有潜力的一个就是 jcouchdb,它可以帮 助您制止 REST 化和 JSON 化,同时答允您以编程方法利用 Java 语言操纵文档 和视图。
#p#分页标题#e#
敬请等候下个月的专栏文章,我将回过甚来接头 Google App Engine。在开 放创新精力的大旗下,各类新框架不绝涌现,旨在促进 Google App Engine 的 开拓和陈设。您将相识它们如何可以或许简化 Google 云平台上的 Java 开拓 2.0 。
本文配套源码