Java开拓2.0 – 通过CouchDB和Groovy的RESTClient实现REST
当前位置:以往代写 > JAVA 教程 >Java开拓2.0 – 通过CouchDB和Groovy的RESTClient实现REST
2019-06-14

Java开拓2.0 – 通过CouchDB和Groovy的RESTClient实现REST

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

#p#副标题#e#

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"

#p#副标题#e#

清单 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 接口

Java开辟2.0 - 通过CouchDB和Groovy的RESTClient实现REST

#p#副标题#e#

假如选择 parking_tickets 数据库,则随后可以在最右侧看到一个下拉列表 (Select view:)。通过选择 Custom query…来界说一个自界说视图,如图所 示:

图 2. Futon 的视图选择接口

Java开辟2.0 - 通过CouchDB和Groovy的RESTClient实现REST

此刻,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 函数

Java开辟2.0 - 通过CouchDB和Groovy的RESTClient实现REST

接下来,您需要指定文档名称(输入 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"}}]}

#p#副标题#e#

从返回的原始 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#

#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 。

本文配套源码

    关键字:

在线提交作业