栏目导航
热点推荐
- 三十条有用的 Java 编程规则
- Java制作水印图片源码
- Java常见异常及可能的导致原因
- Java中的修饰词使用方法总结
- J2EE系统异常的处理准则
- Java中的异常、断言、日志解析(
- Java面试技巧:Java面试题集锦(
- 面向Java开发人员的Scala指南:
- Java程序员:一刻钟精通正则表达
- 网友经验分享:学好java开发的关
- 专家解答:创建表格与数据库进行
- Java远程访问Domino数据库
阅览排行
面向Java开发人员的Scala指南: 增强Scitter库
www.jz123.cn 2009-09-03 来源: IT专家网 责任编辑(袁袁) 我要投递新闻
欢迎回来,Scala 迷们。上个月,我们谈到了 Twitter,这个微博客站点目前正引起社会性网络的极大兴趣,我们还谈到它的基于 XML-/REST 的 API 如何使它成为开发人员进行研究和探索的一个有趣平台。为此,我们首先充实了 “Scitter” 的基本结构,Scitter 是用于访问 Twitter 的一个 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 } } } |
代码有点长,但是很容易分为几个基本部分:
● case 类 User 和 Status,表示 Twitter 在对 API 调用的响应中发回给客户机的基本类型,包括用于构造或提取 XML 的一些方法。
● 一个 Scitter 独立对象,处理那些不需要对用户进行验证的操作。
● 一个 Scitter 实例(用 username 和 password 参数化),用于那些需要对用户执行验证的操作。
到目前为止,对于这两种 Scitter 类型,我们只谈到了测试、verifyCredentials 和 public_timeline API.虽然这些有助于确定 HTTP 访问的基础(使用 Apache HttpClient 库)可以工作,并且我们将 XML 响应转换成 Status 对象的基本方式也是可行的,但是现在我们甚至不能进行基本的 “我的朋友在说什么” 的公共时间线查询,也没有采取过基本的措施来防止代码库中出现 “重复” 问题,更不用说寻找一些方法来模拟用于测试的网络访问代码。
上一篇:Java Math 类中的新功能(一): 实数 下一篇:通过Java或Jsp向数据库存取二进制图片