抽象地讨论 Scala 是一件有趣的事情,但对于本专栏的大多数读者而言,需要通过实践才能理解理论和应用之间的区别。在本期文章中,Ted Neward 将使用 Scala 为客户构建基础框架,用于访问流行的微型博客系统 Twitter。
Twitter 迅速占领了 Internet 市场。您肯定知道这个出色的社交网络工具允许订阅者提供关于他们自身以及当前正在执行的任务的简要状态更新。追随者将接收到他们的 “Twitter 提要” 的更新,这与博客将更新生成到博客阅读者的提要中极为类似。
|
就其本身而言,Twitter 是对社交网络的有趣讨论,并且是用户之间的新一代 “高度互联”,它具备您能想到的所有优点和缺点。
由于 Twitter 很早就发布了其 API,因此大量 Twitter 客户机应用程序涌入到 Internet 上。由于该 API 主要建立在直观和易于理解的基础上,因此许多开发人员都发现有必要构建一个自己的 Twitter 客户机,这与学习 Web 技术的开发人员构建自己的博客服务器极为类似。
考虑到 Scala 的功能性(这看上去能很好地协同 Twitter 的 REST 式特性)以及非常出众的 XML 处理特性,因此尝试构建一个用于访问 Twitter 的 Scala 客户机库应该是一个非常不错的体验。
何为 Twitter?
在详细讨论之前,我们先来看看 Twitter API。
简单来说,Twitter 是一个 “微型博客” — 关于您自己的简短个性化提要,不超过 140 个字符,任何 “追随者” 都可以通过 Web 更新、RSS、文本消息等方式接收它们。(140 字符的限制完全来自文本消息,它是 Twitter 的主要来源渠道,并受到类似的限制)。
|
从实际的角度来说,Twitter 是一个最具 REST 特征 的 API,您可以使用一些种类的消息格式 — XML、ATOM、RSS 或 JSON — 来发送或从 Twitter 服务器接收消息。不同的 URL,与不同的消息和它们所需及可选的消息部分相结合,可以发起不同的 API 调用。例如,如果您希望接收 Twitter 上所有人的所有 “Tweets”(Twitter 更新)的完整列表(也称作 “公共时间轴”),您需要准备一个 XML、ATOM、RSS 或 JSON 消息,将它发送给合适的 URL,并采用与 Twitter 网站(apiwiki.twitter.com)上相同的格式来使用结果:
------------------------------------------------------------
public_timeline
返回设定了自定义用户图标的
非保护用户的 20 条最新状态。不需要身份验证。
注意,公共时间轴将缓存 60 秒钟
因此频繁请求它不再浪费资源。
URL: http://twitter.com/statuses/public_timeline.format
格式:xml、json、rss、atom
方法:GET
API 限制:不适用
返回:状态元素列表
------------------------------------------------------------
从编程的角度来说,这意味着我们给 Twitter 服务器发送一个简单的 GET HTTP 请求,并且我们将获取一组封装在 XML、RSS、ATOM 或 JSON 消息中的 “状态” 消息。Twitter 站点将 “状态” 消息定义为类似清单 1 所示的内容:
清单 1. 您好世界,您在哪里?
<feed xml:lang="en-US" xmlns="http://www.w3.org/2005/Atom"> <title>Twitter / tedneward</title> <id>tag:twitter.com,2007:Status</id> <link type="text/html" rel="alternate" href="http://twitter.com/tedneward"/> <updated>2009-03-07T13:48:31+00:00</updated> <subtitle>Twitter updates from Ted Neward / tedneward.</subtitle> <entry> <title>tedneward: @kdellison Happens to the best of us...</title> <content type="html">tedneward: @kdellison Happens to the best of us...</content> <id>tag:twitter.com,2007:http://twitter.com/tedneward/statuses/1292396349</id> <published>2009-03-07T11:07:18+00:00</published> <updated>2009-03-07T11:07:18+00:00</updated> <link type="text/html" rel="alternate" href="http://twitter.com/tedneward/statuses/1292396349"/> <link type="image/png" rel="image" href="http://s3.amazonaws.com/twitter_production/profile_images/ 55857457/javapolis_normal.png"/> <author> <name>Ted Neward</name> <uri>http://www.tedneward.com</uri> </author> </entry> </feed> |
状态消息中的大部分元素(如果不是全部的话)都很直观,因此不再赘述。
由于我们可以采用三种基于 XML 的格式使用 Twitter 消息,以及 Scala 具备一些非常强大的 XML 特性,包括 XML 字面值和类似 XPath 的查询语法 API,因此编写可以发送和接收 Twitter 消息的 Scala 库只需要一些基础的 Scala 编码工作。举例来说,通过 Scala 使用清单 1 消息来提取状态更新的标题或内容可以利用 Scala 的 XML 类型和 \ 及 \\ 方法,如清单 2 所示:
清单 2. 您好 Ted,您在哪里?
<![CDATA[ package com.tedneward.scitter.test { class ScitterTest { import org.junit._, Assert._ @Test def simpleAtomParse = { val atom = <feed xml:lang="en-US" xmlns="http://www.w3.org/2005/Atom"> <title>Twitter / tedneward</title> <id>tag:twitter.com,2007:Status</id> <link type="text/html" rel="alternate" href="http://twitter.com/tedneward"/> <updated>2009-03-07T13:48:31+00:00</updated> <subtitle>Twitter updates from Ted Neward / tedneward.</subtitle> <entry> <title>tedneward: @kdellison Happens to the best of us...</title> <content type="html">tedneward: @kdellison Happens to the best of us...</content> <id>tag:twitter.com,2007: http://twitter.com/tedneward/statuses/1292396349</id> <published>2009-03-07T11:07:18+00:00</published> <updated>2009-03-07T11:07:18+00:00</updated> <link type="text/html" rel="alternate" href="http://twitter.com/tedneward/statuses/1292396349"/> <link type="image/png" rel="image" href="http://s3.amazonaws.com/twitter_production/profile_images/ 55857457/javapolis_normal.png"/> <author> <name>Ted Neward</name> <uri>http://www.tedneward.com</uri> </author> </entry> </feed> assertEquals(atom \\ "entry" \ "title", "tedneward: @kdellison Happens to the best of us...") } } } ]]> |
有关 Scala 的 XML 支持的更多详细信息,请参阅 “Scala 和 XML”(参见 参考资料)。
实际上,使用原始 XML 本身并不是一个有趣的练习。如果 Scala 的宗旨是让我们的生活更加轻松,那么可以创建一个或一组专用于简化 Scala 消息发送和接收任务的类。作为其中一个目标,应该能够在 “普通” Java 程序中方便地使用库(这意味着可以方便地从任何可理解普通 Java 语义的环境中来访问它,比如说 Groovy 或 Clojure)。
API 设计
在深入了解 Scala/Twitter 库的 API 设计之前(根据同事 ThoughtWorker Neal Ford 的建议,我将它称作 “Scitter”),需要明确一些需求。
首先,Scitter 显然会对网络访问有一些依赖 — 并且可扩展到 Twitter 服务器 — 这会使测试变得非常困难。
其次,我们需要解析(和测试)Twitter 发回的各种格式。