Twitter是什么

這篇文章主要講解了“Twitter是什么”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“Twitter是什么”吧!

創(chuàng)新互聯(lián)專注于扶綏企業(yè)網(wǎng)站建設(shè),成都響應(yīng)式網(wǎng)站建設(shè),商城網(wǎng)站建設(shè)。扶綏網(wǎng)站建設(shè)公司,為扶綏等地區(qū)提供建站服務(wù)。全流程按需規(guī)劃網(wǎng)站,專業(yè)設(shè)計,全程項目跟蹤,創(chuàng)新互聯(lián)專業(yè)和態(tài)度為您提供的服務(wù)

Twitter 迅速占領(lǐng)了 Internet 市場。您肯定知道這個出色的社交網(wǎng)絡(luò)工具允許訂閱者提供關(guān)于他們自身以及當(dāng)前正在執(zhí)行的任務(wù)的簡要狀態(tài)更新。追隨者 將接收到他們的 “Twitter 提要” 的更新,這與博客將更新生成到博客閱讀者的提要中極為類似。

就其本身而言,Twitter 是對社交網(wǎng)絡(luò)的有趣討論,并且是用戶之間的新一代 “高度互聯(lián)”,它具備您能想到的所有優(yōu)點和缺點。

由于 Twitter 很早就發(fā)布了其 API,因此大量 Twitter 客戶機(jī)應(yīng)用程序涌入到 Internet 上。由于該 API 主要建立在直觀和易于理解的基礎(chǔ)上,因此許多開發(fā)人員都發(fā)現(xiàn)有必要構(gòu)建一個自己的 Twitter 客戶機(jī),這與學(xué)習(xí) Web 技術(shù)的開發(fā)人員構(gòu)建自己的博客服務(wù)器極為類似。

考慮到 Scala 的功能性(這看上去能很好地協(xié)同 Twitter 的 REST 式特性)以及非常出眾的 XML 處理特性,因此嘗試構(gòu)建一個用于訪問 Twitter 的 Scala 客戶機(jī)庫應(yīng)該是一個非常不錯的體驗。

何為 Twitter?

在詳細(xì)討論之前,我們先來看看 Twitter API。

簡單來說,Twitter 是一個 “微型博客” — 關(guān)于您自己的簡短個性化提要,不超過 140 個字符,任何 “追隨者” 都可以通過 Web 更新、RSS、文本消息等方式接收它們。(140 字符的限制完全來自文本消息,它是 Twitter 的主要來源渠道,并受到類似的限制)。

最具 REST 特征 是什么意思?

一些讀者會對我所使用的最具 REST 特征 短語感到好奇;這需要一些說明?!癟witter API 試圖符合 Representational State Transfer (REST) 的設(shè)計原則”。并且在很大程度上說它做到了。該思想的創(chuàng)造者 Roy Fielding 可能不同意 Twitter 使用這個術(shù)語,但實現(xiàn)來說,Twitter 的方法將適合大多數(shù)人的 REST 定義。我只希望避免關(guān)于 REST 定義的激烈爭論。因此,我使用了限定詞 “最”。

從實際的角度來說,Twitter 是一個最具 REST 特征 的 API,您可以使用一些種類的消息格式 — XML、ATOM、RSS 或 JSON — 來發(fā)送或從 Twitter 服務(wù)器接收消息。不同的 URL,與不同的消息和它們所需及可選的消息部分相結(jié)合,可以發(fā)起不同的 API 調(diào)用。例如,如果您希望接收 Twitter 上所有人的所有 “Tweets”(Twitter 更新)的完整列表(也稱作 “公共時間軸”),您需要準(zhǔn)備一個 XML、ATOM、RSS 或 JSON 消息,將它發(fā)送給合適的 URL,并采用與 Twitter 網(wǎng)站(apiwiki.twitter.com)上相同的格式來使用結(jié)果:

------------------------------------------------------------

public_timeline

返回設(shè)定了自定義用戶圖標(biāo)的

非保護(hù)用戶的 20 條最新狀態(tài)。不需要身份驗證。

注意,公共時間軸將緩存 60 秒鐘

因此頻繁請求它不再浪費(fèi)資源。

URL: http://twitter.com/statuses/public_timeline.format

格式:xml、json、rss、atom

方法:GET

API 限制:不適用

返回:狀態(tài)元素列表

------------------------------------------------------------

從編程的角度來說,這意味著我們給 Twitter 服務(wù)器發(fā)送一個簡單的 GET HTTP 請求,并且我們將獲取一組封裝在 XML、RSS、ATOM 或 JSON 消息中的 “狀態(tài)” 消息。Twitter 站點將 “狀態(tài)” 消息定義為類似清單 1 所示的內(nèi)容:

清單 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>

狀態(tài)消息中的大部分元素(如果不是全部的話)都很直觀,因此不再贅述。

由于我們可以采用三種基于 XML 的格式使用 Twitter 消息,以及 Scala 具備一些非常強(qiáng)大的 XML 特性,包括 XML 字面值和類似 XPath 的查詢語法 API,因此編寫可以發(fā)送和接收 Twitter 消息的 Scala 庫只需要一些基礎(chǔ)的 Scala 編碼工作。舉例來說,通過 Scala 使用清單 1 消息來提取狀態(tài)更新的標(biāo)題或內(nèi)容可以利用 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...")      }    }  }  ]]>

有關(guān) Scala 的 XML 支持的更多詳細(xì)信息,請參閱 “Scala 和 XML”。

實際上,使用原始 XML 本身并不是一個有趣的練習(xí)。如果 Scala 的宗旨是讓我們的生活更加輕松,那么可以創(chuàng)建一個或一組專用于簡化 Scala 消息發(fā)送和接收任務(wù)的類。作為其中一個目標(biāo),應(yīng)該能夠在 “普通” Java 程序中方便地使用庫(這意味著可以方便地從任何可理解普通 Java 語義的環(huán)境中來訪問它,比如說 Groovy 或 Clojure)。

API 設(shè)計

在深入了解 Scala/Twitter 庫的 API 設(shè)計之前(根據(jù)同事 ThoughtWorker Neal Ford 的建議,我將它稱作 “Scitter”),需要明確一些需求。

首先,Scitter 顯然會對網(wǎng)絡(luò)訪問有一些依賴 — 并且可擴(kuò)展到 Twitter 服務(wù)器 — 這會使測試變得非常困難。

其次,我們需要解析(和測試)Twitter 發(fā)回的各種格式。

第三,我們希望隱藏 API 內(nèi)部各種格式之間的差異,以便客戶機(jī)不需要擔(dān)心已記錄的 Twitter 消息格式,但是可以僅使用標(biāo)準(zhǔn)類。

最后,由于 Twitter 依賴 “通過身份驗證的用戶” 才能使用大量 API,因此 Scitter 庫需要適應(yīng) “驗證” 和 “未驗證” API 之間的差異,而不會讓事情變得過于復(fù)雜。

網(wǎng)絡(luò)訪問需要一些形式的 HTTP 通信,以便聯(lián)系 Twitter 服務(wù)器。雖然我們可以使用 Java 庫本身(特別是 URL 類及其同胞),但由于 Twitter API 需要大量請求和響應(yīng)主體連接,因此可以更加輕松地使用不同的 HTTP API,特別是 Apache Commons HttpClient 庫。為了更便于測試客戶機(jī) API,實際通信將隱藏在一些 API 內(nèi)部的 Scitter 庫中,以便能夠更加輕松地切換到另一個 HTTP 庫(其必要性不太容易想到),并能模擬實際網(wǎng)絡(luò)通信以簡化測試(其作用很容易想到)。

結(jié)果,第一個測試是 Scala 化 HttpClient 調(diào)用,以確保基本通信模式就位;注意,由于 HttpClient 依賴另外兩個 Apache 庫(Commons Logging 和 Commons Codec),因此還需要在運(yùn)行時提供這些庫;對于那些希望開發(fā)相似種類代碼的讀者,確保類路徑中包括所有三個庫。

由于最易于使用的 Twitter API 是測試 API

因此在請求格式中返回 “ok”,并附帶 200 OK HTTP 狀態(tài)碼。

我們將使用它作為 Scitter 測試中的保留條款。它位于 URL http://twitter.com/help/test.format(其中,“format” 為 “xml” 或 “json”;至于目前,我們將選擇使用 “xml”),并且僅有的支持 HTTP 方法是 GET。HttpClient 代碼簡明易懂,如清單 3 所示:

清單 3. Twitter PING!

package com.tedneward.scitter.test  {    class ExplorationTests    {      // ...          import org.apache.commons.httpclient._, methods._, params._, cookie._            @Test def callTwitterTest =      {        val testURL = "http://twitter.com/help/test.xml"               // HttpClient API 101        val client = new HttpClient()        val method = new GetMethod(testURL)         method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,           new DefaultHttpMethodRetryHandler(3, false))         client.executeMethod(method)                val statusLine = method.getStatusLine()                assertEquals(statusLine.getStatusCode(), 200)        assertEquals(statusLine.getReasonPhrase(), "OK")      }    }  }

此代碼中最重要的一部分是 HttpClient 樣板 — 感興趣的讀者應(yīng)該查閱 HttpClient API 文檔了解詳細(xì)信息。假設(shè)連接到公共 Internet 的網(wǎng)絡(luò)可用(并且 Twitter 并未修改其公共 API),那么該測試應(yīng)該能順利通過。

鑒于此,我們詳細(xì)分析 Scitter 客戶機(jī)的第一部分。這意味著我們需要解決一個設(shè)計問題:如何構(gòu)建 Scitter 客戶機(jī)來處理經(jīng)過驗證和未經(jīng)過驗證的調(diào)用。目前,我將采用典型的 Scala 方式,假定驗證是 “按對象” 執(zhí)行的,因此將需要驗證的調(diào)用放在類定義中,并在未驗證的調(diào)用放在對象定義中:

清單 4. Scitter.test

package com.tedneward.scitter  {    /**     * Object for consuming "non-specific" Twitter feeds, such as the public timeline.     * Use this to do non-authenticated requests of Twitter feeds.     */   object Scitter    {      import org.apache.commons.httpclient._, methods._, params._, cookie._       /**       * Ping the server to see if it's up and running.       *       * Twitter docs say:       * test       * Returns the string "ok" in the requested format with a 200 OK HTTP status code.       * URL: http://twitter.com/help/test.format       * Formats: xml, json       * Method(s): GET       */     def test : Boolean =      {        val client = new HttpClient()         val method = new GetMethod("http://twitter.com/help/test.xml")         method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,           new DefaultHttpMethodRetryHandler(3, false))         client.executeMethod(method)                val statusLine = method.getStatusLine()        statusLine.getStatusCode() == 200     }    }    /**     * Class for consuming "authenticated user" Twitter APIs. Each instance is     * thus "tied" to a particular authenticated user on Twitter, and will     * behave accordingly (according to the Twitter API documentation).     */   class Scitter(username : String, password : String)    {    }  }

目前,我們將網(wǎng)絡(luò)抽象放在一邊 — 稍后,當(dāng)離線測試變得更加重要時再添加它。當(dāng)我們更好地理解如何使用 HttpClient 類時,這還將幫助避免 “過度抽象” 網(wǎng)絡(luò)通信。

由于已經(jīng)明確區(qū)分了驗證和未驗證 Twitter 客戶機(jī),因此我們將快速創(chuàng)建一個經(jīng)過驗證的方法。看上去 Twitter 提供了一個可驗證用戶登錄憑證的 API。再次,HttpClient 代碼將類似于之前的代碼,除了將用戶名和密碼傳遞到 Twitter API 中之外。

這引出了 Twitter 如何驗證用戶的概念。快速查看 Twitter API 頁面后,可以發(fā)現(xiàn) Twitter 使用的是一種 Stock HTTP 驗證方法,這與任何經(jīng)過驗證的資源在 HTTP 中的方法相同。這意味著 HttpClient 代碼必須提供用戶名和密碼作為 HTTP 請求的一部分,而不是作為 POST 的主體,如清單 5 所示:

清單 5. 您好 Twitter,是我!

package com.tedneward.scitter.test  {    class ExplorationTests    {      def testUser = "TwitterUser"  def testPassword = "TwitterPassword"         @Test def verifyCreds =      {        val client = new HttpClient()         val verifyCredsURL = "http://twitter.com/account/verify_credentials.xml"       val method = new GetMethod(verifyCredsURL)         method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,           new DefaultHttpMethodRetryHandler(3, false))         client.getParams().setAuthenticationPreemptive(true)        val defaultcreds = new UsernamePasswordCredentials(testUser, testPassword)        client.getState().setCredentials(new AuthScope("twitter.com", 80,                                                       AuthScope.ANY_REALM), defaultcreds)                client.executeMethod(method)                val statusLine = method.getStatusLine()                assertEquals(200, statusLine.getStatusCode())        assertEquals("OK", statusLine.getReasonPhrase())      }    }  }

注意,要讓此測試順利通信,用戶名和密碼字段將需要輸入 Twitter 能接收的內(nèi)容 — 我在開發(fā)時使用了自己的 Twitter 用戶名和密碼,但顯然您需要使用自己設(shè)定的用戶名和密碼。注冊新的 Twitter 帳戶相當(dāng)簡單,因此我假定您已經(jīng)擁有一個帳戶,或者知道如何注冊(很好。我會等待完成此任務(wù))。

完成后,使用用戶名和密碼構(gòu)造函數(shù)參數(shù)將它映射到 Scitter 類非常簡單,如清單 6 所示:

清單 6. Scitter.verifyCredentials

package com.tedneward.scitter  {    import org.apache.commons.httpclient._, auth._, methods._, params._     // ...     /**     * Class for consuming "authenticated user" Twitter APIs. Each instance is     * thus "tied" to a particular authenticated user on Twitter, and will     * behave accordingly (according to the Twitter API documentation).     */   class Scitter(username : String, password : String)    {      /**       * Verify the user credentials against Twitter.       *       * Twitter docs say:       * verify_credentials       * Returns an HTTP 200 OK response code and a representation of the       * requesting user if authentication was successful; returns a 401 status       * code and an error message if not.  Use this method to test if supplied       * user credentials are valid.       * URL: http://twitter.com/account/verify_credentials.format       * Formats: xml, json       * Method(s): GET       */     def verifyCredentials : Boolean =      {        val client = new HttpClient()         val method = new GetMethod("http://twitter.com/help/test.xml")         method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,           new DefaultHttpMethodRetryHandler(3, false))                  client.getParams().setAuthenticationPreemptive(true)        val creds = new UsernamePasswordCredentials(username, password)        client.getState().setCredentials(          new AuthScope("twitter.com", 80, AuthScope.ANY_REALM), creds)         client.executeMethod(method)                val statusLine = method.getStatusLine()        statusLine.getStatusCode() == 200     }    }  }

清單 7 中相應(yīng)的 Scitter 類測試也相當(dāng)簡單:

清單 7. 測試 Scitter.verifyCredentials

package com.tedneward.scitter.test  {    class ScitterTests    {      import org.junit._, Assert._      import com.tedneward.scitter._       def testUser = "TwitterUsername"       def testPassword = "TwitterPassword"             // ...         @Test def verifyCreds =      {        val scitter = new Scitter(testUser, testPassword)        val result = scitter.verifyCredentials        assertTrue(result)      }    }  }

不算太糟。庫的基本結(jié)構(gòu)已經(jīng)成形,但顯然還有很長的路要走,特別是因為目前實際上未執(zhí)行任何特定于 Scala 的任務(wù) — 在面向?qū)ο笤O(shè)計中,庫的構(gòu)建并不像練習(xí)那樣簡單。因此,我們開始使用一些 XML,并通過更加合理的格式將它返回。

從 XML 到對象

現(xiàn)在可以添加的最簡單的 API 是 public_timeline,它收集 Twitter 從所有用戶處接收到的最新的 n 更新,并返回它們以便于進(jìn)行使用。與之前討論的另外兩個 API 不同,public_timeline API 返回一個響應(yīng)主體(而不是僅依賴于狀態(tài)碼),因此我們需要分解生成的 XML/RSS/ATOM/,然后將它們返回給 Scitter 客戶機(jī)。

現(xiàn)在,我們編寫一個探索測試,它將訪問公共提要并將結(jié)果轉(zhuǎn)儲到 stdout 以便進(jìn)行分析,如清單 8 所示:

清單 8. 大家都在忙什么?

package com.tedneward.scitter.test  {    class ExplorationTests    {      // ...          @Test def callTwitterPublicTimeline =      {        val publicFeedURL = "http://twitter.com/statuses/public_timeline.xml"               // HttpClient API 101        val client = new HttpClient()        val method = new GetMethod(publicFeedURL)        method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,           new DefaultHttpMethodRetryHandler(3, false))                client.executeMethod(method)                val statusLine = method.getStatusLine()        assertEquals(statusLine.getStatusCode(), 200)        assertEquals(statusLine.getReasonPhrase(), "OK")                val responseBody = method.getResponseBodyAsString()        System.out.println("callTwitterPublicTimeline got... ")        System.out.println(responseBody)      }    }  }

運(yùn)行后,結(jié)果每次都會有所不同,因為公共 Twitter 服務(wù)器上有許多用戶,但通常應(yīng)與清單 9 的 JUnit 文本文件轉(zhuǎn)儲類似:

清單 9. 我們的 Tweets 結(jié)果

< statuses type="array">     < status>       < created_at>Tue Mar 10 03:14:54 +0000 2009< /created_at>       < id>1303777336< /id>       < text>She really is. http://tinyurl.com/d65hmj< /text>       < source>< a href="http://iconfactory.com/software/twitterrific">twitterrific< /a>         < /source>       < truncated>false< /truncated>       < in_reply_to_status_id>< /in_reply_to_status_id>       < in_reply_to_user_id>< /in_reply_to_user_id>       < favorited>false< /favorited>       < user>           < id>18729101< /id>           < name>Brittanie< /name>           < screen_name>brittaniemarie< /screen_name>           < description>I'm a bright character. I suppose.< /description>           < location>Atlanta or Philly.< /location>           < profile_image_url>http://s3.amazonaws.com/twitter_production/profile_images/                               81636505/goodish_normal.jpg< /profile_image_url>           < url>http://writeitdowntakeapicture.blogspot.com< /url>           < protected>false< /protected>           < followers_count>61< /followers_count>       < /user>     < /status>     < status>       < created_at>Tue Mar 10 03:14:57 +0000 2009< /created_at>       < id>1303777334< /id>       < text>Number 2 of my four life principles.  "Life is fun and rewarding"< /text>       < source>web< /source>       < truncated>false< /truncated>       < in_reply_to_status_id>< /in_reply_to_status_id>       < in_reply_to_user_id>< /in_reply_to_user_id>       < favorited>false< /favorited>       < user>           < id>21465465< /id>           < name>Dale Greenwood< /name>           < screen_name>Greeendale< /screen_name>           < description>Vegetarian. Eat and use only organics.                          Love helping people become prosperous< /description>           < location>Melbourne Australia< /location>           < profile_image_url>http://s3.amazonaws.com/twitter_production/profile_images/                               90659576/Dock_normal.jpg< /profile_image_url>           < url>http://www.4abundance.mionegroup.com< /url>           < protected>false< /protected>           < followers_count>15< /followers_count>        < /user>      < /status>        (A lot more have been snipped)  < /statuses>

通過查看結(jié)果和 Twitter 文檔可以看出,調(diào)用的結(jié)果是一組具備一致消息結(jié)構(gòu)的簡單 “狀態(tài)” 消息。使用 Scala 的 XML 支持分離結(jié)果相當(dāng)簡單,但我們會在基本測試通過后立即簡化它們,如清單 10 所示:

清單 10. 大家都在忙什么?

package com.tedneward.scitter.test  {    class ExplorationTests    {      // ...          @Test def simplePublicFeedPullAndParse =      {        val publicFeedURL = "http://twitter.com/statuses/public_timeline.xml"               // HttpClient API 101        val client = new HttpClient()        val method = new GetMethod(publicFeedURL)        method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,           new DefaultHttpMethodRetryHandler(3, false))        val statusCode = client.executeMethod(method)        val responseBody = new String(method.getResponseBody())                val responseXML = scala.xml.XML.loadString(responseBody)        val statuses = responseXML \\ "status"        for (n < - statuses.elements)        {          n match          {            case < status>{ contents @ _*}< /status> =>            {              System.out.println("Status: ")              contents.foreach((c) =>                c match                {                  case < text>{ t @ _*}< /text> =>                    System.out.println("\tText: " + t.text.trim)                  case < user>{ contents2 @ _* }< /user> =>                  {                    contents2.foreach((c2) =>                      c2 match                      {                        case < screen_name>{ u }< /screen_name> =>                          System.out.println("\tUser: " + u.text.trim)                        case _ =>        ()                      }                    )                  }                  case _ =>        ()                }              )            }            case _ =>              () // or, if you prefer, System.out.println("Unrecognized element!")          }        }      }    }  }

隨著示例代碼模式的變化,這并不值得推薦 — 這有點類似于 DOM,依次導(dǎo)航到各個子元素,提取文本,然后導(dǎo)航到另一個節(jié)點。我可以僅執(zhí)行兩個 XPath 樣式的查詢,如清單 11 所示:

清單 11. 替代解析方法

for (n < - statuses.elements)  {       val text = (n \\ "text").text         val screenName = (n \\ "user" \ "screen_name").text  }

這顯然更加簡短,但它帶來了兩個基本問題:

我們可以強(qiáng)制 Scala 的 XML 庫針對每個元素或子元素遍歷一次圖,其速度會隨時間減慢。

我們?nèi)匀恍枰苯犹幚?XML 消息的結(jié)構(gòu)。這是兩個問題中最為重要的。

也就是說,這種方式不具備可伸縮性 — 假設(shè)我們最終對 Twitter 狀態(tài)消息中的每個元素都感興趣,我們將需要分別從各狀態(tài)中提取各個元素。

這又造成了另一個與各格式本身相關(guān)的問題。記住,Twitter 可以使用四種不同的格式,并且我們不希望 Scitter 客戶機(jī)需要了解它們之間的任何差異,因此 Scitter 需要一個能返回給客戶機(jī)的中間結(jié)構(gòu),以便未來使用,如清單 12 所示:

清單 12. Breaker,您的狀態(tài)是什么?

abstract class Status  {    val createdAt : String    val id : Long    val text : String    val source : String    val truncated : Boolean    val inReplyToStatusId : Option[Long]    val inReplyToUserId : Option[Long]    val favorited : Boolean    val user : User  }

這與 User 方式相類似,考慮到簡潔性,我就不再重復(fù)了。注意,User 子元素有一個有趣的問題 — 雖然存在 Twitter 用戶類型,但其中內(nèi)嵌了一個可選的 “最新狀態(tài)”。狀態(tài)消息還內(nèi)嵌了一個用戶。對于這種情況,為了幫助避免一些潛在的遞歸問題,我選擇創(chuàng)建一個嵌入在 Status 內(nèi)部的 User 類型,以反映所出現(xiàn)的 User 數(shù)據(jù);反之亦然,Status 也可以嵌入在 User 中,這樣可以明確避免該問題。(至少,在沒發(fā)現(xiàn)問題之前,這種方法是有效的)。

現(xiàn)在,創(chuàng)建了表示 Twitter 消息的對象類型之后,我們可以遵循 XML 反序列化的公共 Scala 模式:創(chuàng)建相應(yīng)的對象定義,其中包含一個 fromXml 方法,用于將 XML 節(jié)點分離到對象實例中,如清單 13 所示:

清單 13. 分解 XML

/**   * Object wrapper for transforming (format) into Status instances.   */ object Status  {    def fromXml(node : scala.xml.Node) : Status =    {      new Status {        val createdAt = (node \ "created_at").text        val id = (node \ "id").text.toLong        val text = (node \ "text").text        val source = (node \ "source").text        val truncated = (node \ "truncated").text.toBoolean        val inReplyToStatusId =          if ((node \ "in_reply_to_status_id").text != "")            Some((node \"in_reply_to_status_id").text.toLong)          else           None        val inReplyToUserId =           if ((node \ "in_reply_to_user_id").text != "")            Some((node \"in_reply_to_user_id").text.toLong)          else           None        val favorited = (node \ "favorited").text.toBoolean        val user = User.fromXml((node \ "user")(0))      }    }  }

其中最強(qiáng)大的一處是,它可以針對 Twitter 支持的其他任何格式進(jìn)行擴(kuò)展 — fromXml 方法可以在分解節(jié)點之前檢查它是否保存了 XML、RSS 或 Atom 類型的內(nèi)容,或者 Status 可以包含 fromXml、fromRss、fromAtom 和 fromJson 方法。實際上,后一種方法是我的優(yōu)先選擇,因為它會平等對待基于 XML 的格式和 JSON(基于文本)格式。

好奇和細(xì)心的讀者會注意到在 Status 及其內(nèi)嵌 User 的 fromXml 方法中,我使用的是 XPath 樣式的分解方法,而不是之前建議的遍歷內(nèi)嵌元素的方法?,F(xiàn)在,XPath 樣式的方法看上去更易于閱讀,但幸運(yùn)的是,我后來改變了注意,良好的封裝仍然是我的朋友 — 我可以在隨后修改它,Scitter 外部的任何人都不會知道。

注意 Status 內(nèi)部的兩個成員如何使用 Option[T] 類型;這是因為這些元素通常排除在 Status 消息外部,并且雖然元素本身會出現(xiàn),但它們顯示為空(類似于 < in_reply_to_user_id>< /in_reply_to_user_id>)。這正是 Option[T] 的作用所在。當(dāng)元素為空時,它們將使用 “None” 值。(這表示考慮到基于 Java 的兼容性,訪問它們會更加困難,但惟一可行方法是對最終生成的 Option 實例調(diào)用 get(),這不太復(fù)雜并且能很好地解決 “非 null 即 0” 問題)。

現(xiàn)在已經(jīng)可以輕而易舉地使用公共時間軸:

清單 14. 分解公共時間軸

@Test def simplePublicFeedPullAndDeserialize =  {    val publicFeedURL = "http://twitter.com/statuses/public_timeline.xml"       // HttpClient API 101    val client = new HttpClient()    val method = new GetMethod(publicFeedURL)    method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,       new DefaultHttpMethodRetryHandler(3, false))    val statusCode = client.executeMethod(method)    val responseBody = new String(method.getResponseBody())        val responseXML = scala.xml.XML.loadString(responseBody)    val statuses = responseXML \\ "status"    for (n < - statuses.elements)    {      val s = Status.fromXml(n)      System.out.println("\t'@" + s.user.screenName + "' wrote " + s.text)    }  }

顯然,這看上去更加簡潔,并且易于使用。

將所有這些結(jié)合到 Scitter 單一實例中相當(dāng)簡單,僅涉及執(zhí)行查詢、解析各個 Status 元素以及將它們添加到 List[Status] 實例中,如清單 15 所示:

清單 15. Scitter.publicTimeline

package com.tedneward.scitter  {    import org.apache.commons.httpclient._, auth._, methods._, params._    import scala.xml._     object Scitter    {      // ...          /**       * Query the public timeline for the most recent statuses.       *       * Twitter docs say:       * public_timeline       * Returns the 20 most recent statuses from non-protected users who have set       * a custom user icon.  Does not require authentication.  Note that the       * public timeline is cached for 60 seconds so requesting it more often than       * that is a waste of resources.       * URL: http://twitter.com/statuses/public_timeline.format       * Formats: xml, json, rss, atom       * Method(s): GET       * API limit: Not applicable       * Returns: list of status elements            */     def publicTimeline : List[Status] =      {        import scala.collection.mutable.ListBuffer              val client = new HttpClient()         val method =            new GetMethod("http://twitter.com/statuses/public_timeline.xml")         method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,           new DefaultHttpMethodRetryHandler(3, false))         client.executeMethod(method)                val statusLine = method.getStatusLine()        if (statusLine.getStatusCode() == 200)        {          val responseXML =            XML.loadString(method.getResponseBodyAsString())           val statusListBuffer = new ListBuffer[Status]           for (n < - (responseXML \\ "status").elements)            statusListBuffer += (Status.fromXml(n))                    statusListBuffer.toList        }        else       {          Nil        }      }    }  }

在實現(xiàn)功能全面的 Twiter 客戶機(jī)之前,我們顯然還有很長的路要走。但到目前為止,我們已經(jīng)實現(xiàn)基本的行為。

感謝各位的閱讀,以上就是“Twitter是什么”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對Twitter是什么這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識點的文章,歡迎關(guān)注!

文章名稱:Twitter是什么
鏈接分享:http://bm7419.com/article10/gihpdo.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)頁設(shè)計公司、網(wǎng)站維護(hù)網(wǎng)站設(shè)計、電子商務(wù)、軟件開發(fā)、移動網(wǎng)站建設(shè)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

商城網(wǎng)站建設(shè)