歡迎您光臨本站 註冊首頁

面向 Java 開發人員的 Scala 指南: 增強 Scitter 庫

←手機掃碼閱讀     火星人 @ 2014-03-12 , reply:0
  
抽象地談論 Scala 的確有趣,然而一旦將其付諸實踐,就會發現將它作為 “玩具” 與在工作中使用它的區別。Scala 狂熱者 Ted Neward 撰寫了一篇 對 Scitter 的介紹,Scitter 是一個用於訪問 Twitter 的 Scala 庫,本文是其後續篇,在本文中,Ted Neward 為這個客戶機庫提供了一組更有趣也更有用的特性。

歡迎回來,Scala 迷們。上個月,我們談到了 Twitter,這個微博客站點目前正引起社會性網路的極大興趣,我們還談到它的基於 XML-/REST 的 API 如何使它成為開發人員進行研究和探索的一個有趣平台。為此,我們首先充實了 “Scitter” 的基本結構,Scitter 是用於訪問 Twitter 的一個 Scala 庫。

關於本系列

Ted Neward 將和您一起深入探討 Scala 編程語言。在這個 developerWorks 系列 中,您將了解有關 Scala 的所有最新討論,並在實踐中看到 Scala 的語言功能。在進行相關比較時,Scala 代碼和 Java™ 代碼將放在一起展示,但是(您將發現)Scala 與 Java 中的許多東西都沒有直接的關聯,這正是 Scala 的魅力所在!如果用 Java 代碼就能夠實現的話,又何必再學習 Scala 呢?

我們對於 Scitter 有幾個目標:

  • 簡化 Twitter 訪問,比過去打開 HTTP 連接然後 “手動” 執行操作更容易。
  • 可以從 Java 客戶機輕鬆訪問它。
  • 輕鬆模擬以便進行測試。

在這一期,我們不必完成整個 Twitter API,但是我們將完成一些核心部分,目的是讓這個庫達到公共源代碼控制庫的程度,便於其他人來完成這項工作。

到目前為止:Scitter 0.1

首先我們簡單回顧一下到目前為止我們所處的階段:


清單 1. Scitter v0.1
				  package com.tedneward.scitter  {    import org.apache.commons.httpclient._, auth._, methods._, params._    import scala.xml._      /**     * Status message type. This will typically be the most common message type     * sent back from Twitter (usually in some kind of collection form). Note     * that all optional elements in the Status type are represented by the     * Scala Option[T] type, since that's what it's there for.     */    abstract class Status    {      /**       * Nested User type. This could be combined with the top-level User type,       * if we decide later that it's OK for this to have a boatload of optional       * elements, including the most-recently-posted status update (which is a       * tad circular).       */      abstract class User      {        val id : Long        val name : String        val screenName : String        val description : String        val location : String        val profileImageUrl : String        val url : String        val protectedUpdates : Boolean        val followersCount : Int      }      /**       * Object wrapper for transforming (format) into User instances.       */      object User      {        /*        def fromAtom(node : Node) : Status =        {                }        */        /*        def fromRss(node : Node) : Status =        {                }        */        def fromXml(node : Node) : User =        {          new User {            val id = (node \ "id").text.toLong            val name = (node \ "name").text            val screenName = (node \ "screen_name").text            val description = (node \ "description").text            val location = (node \ "location").text            val profileImageUrl = (node \ "profile_image_url").text            val url = (node \ "url").text            val protectedUpdates = (node \ "protected").text.toBoolean            val followersCount = (node \ "followers_count").text.toInt          }        }      }          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    }    /**     * Object wrapper for transforming (format) into Status instances.     */    object Status    {      /*      def fromAtom(node : Node) : Status =      {            }      */      /*      def fromRss(node : Node) : Status =      {            }      */      def fromXml(node : 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))        }      }    }        /**     * Object for consuming "non-specific" Twitter feeds, such as the public timeline.     * Use this to do non-authenticated requests of Twitter feeds.     */    object Scitter    {      /**       * 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      }      /**       * 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        }      }    }    /**     * 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      }    }  }  


[火星人 ] 面向 Java 開發人員的 Scala 指南: 增強 Scitter 庫已經有638次圍觀

http://coctec.com/docs/linux/show-post-68760.html