<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>权记 &#187; xml</title>
	<atom:link href="http://www.quanlei.com/tag/xml/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.quanlei.com</link>
	<description>一个关于我们生活点滴的网站，一个记录我们酸甜苦辣的日志。</description>
	<lastBuildDate>Sun, 06 Jun 2010 01:10:16 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>[09/51-52周主题] – Java Net and XML parser</title>
		<link>http://www.quanlei.com/2009/12/java-net-and-xml-parser/</link>
		<comments>http://www.quanlei.com/2009/12/java-net-and-xml-parser/#comments</comments>
		<pubDate>Sun, 27 Dec 2009 08:29:09 +0000</pubDate>
		<dc:creator>小权</dc:creator>
				<category><![CDATA[周主题]]></category>
		<category><![CDATA[编程相关]]></category>
		<category><![CDATA[http]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[twitter]]></category>
		<category><![CDATA[xml]]></category>

		<guid isPermaLink="false">http://www.quanlei.com/?p=1061</guid>
		<description><![CDATA[本周主题：Java Net and XML Parser 分两部分：一部Java Net(大部分来自Java Doc), 一部分XML Parser， 通过一个Twitter的例子来描述简单的使用情况。 一、Java Net java.net 包的概述： java.net包大致可分为两部分： 低级API &#8211; 用于处理以下抽象： 地址，也就是网络标识符，如 IP 地址。 套接字，也就是基本双向数据通信机制。 接口，用于描述网络接口。 高级API &#8211; 用于处理以下抽象： URI，表示统一资源标识符。 URL，表示统一资源定位符。 连接，表示到 URL 所指向资源的连接。 地址 在整个 java.net API 中，地址或者用作主机标识符或者用作套接字端点标识符。 InetAddress 类是表示 IP（Internet 协议）地址的抽象，它拥有两个子类： 用于 IPv4 地址的 Inet4Address。 用于 IPv6 地址的 Inet6Address。 但是，在大多数情况下，不必直接处理子类，因为 InetAddress 抽象应该覆盖大多数必需的功能。 套接字 套接字是在网络上建立机器之间的通信链接的方法。java.net 包提供 [...]]]></description>
			<content:encoded><![CDATA[<h2>本周主题：Java Net and XML Parser</h2>
<p>分两部分：一部Java Net(大部分来自Java Doc), 一部分XML Parser， 通过一个Twitter的例子来描述简单的使用情况。</p>
<h3>一、Java Net</h3>
<p>java.net 包的概述：</p>
<p>java.net包大致可分为两部分：</p>
<h4>低级API &#8211; 用于处理以下抽象：</h4>
<ul>
<li><em>地址</em>，也就是网络标识符，如 IP 地址。</li>
<li><em>套接字</em>，也就是基本双向数据通信机制。</li>
<li><em>接口</em>，用于描述网络接口。</li>
</ul>
<h4>高级API &#8211; 用于处理以下抽象：</h4>
<ul>
<li><em>URI</em>，表示统一资源标识符。</li>
<li><em>URL</em>，表示统一资源定位符。</li>
<li><em>连接</em>，表示到 <em>URL</em> 所指向资源的连接。</li>
</ul>
<h4>地址</h4>
<p>在整个 java.net API 中，地址或者用作主机标识符或者用作套接字端点标识符。</p>
<p>InetAddress 类是表示 IP（Internet 协议）地址的抽象，它拥有两个子类：</p>
<ul>
<li>用于 IPv4 地址的 <a title="java.net 中的类" href="http://gceclub.sun.com.cn/Java_Docs/html/zh_CN/api/java/net/Inet4Address.html"><code>Inet4Address</code></a>。</li>
<li>用于 IPv6 地址的 <a title="java.net 中的类" href="http://gceclub.sun.com.cn/Java_Docs/html/zh_CN/api/java/net/Inet6Address.html"><code>Inet6Address</code></a>。</li>
</ul>
<p>但是，在大多数情况下，不必直接处理子类，因为 InetAddress 抽象应该覆盖大多数必需的功能。</p>
<h4>套接字</h4>
<p>套接字是在网络上建立机器之间的通信链接的方法。java.net 包提供 4 种套接字：</p>
<ul>
<li><a title="java.net 中的类" href="http://gceclub.sun.com.cn/Java_Docs/html/zh_CN/api/java/net/Socket.html"><code>Socket</code></a> 是 TCP 客户端 API，通常用于将 (<code>java.net.Socket.connect(SocketAddress)</code>) 连接到远程主机。</li>
<li><a title="java.net 中的类" href="http://gceclub.sun.com.cn/Java_Docs/html/zh_CN/api/java/net/ServerSocket.html"><code>ServerSocket</code></a> 是 TCP 服务器 API，通常接受 (<code>java.net.ServerSocket.accept</code>) 源于客户端套接字的连接。</li>
<li><a title="java.net 中的类" href="http://gceclub.sun.com.cn/Java_Docs/html/zh_CN/api/java/net/DatagramSocket.html"><code>DatagramSocket</code></a> 是 UDP 端点 API，用于发送和接收 <code>java.net.DatagramPackets</code>。</li>
<li><a title="java.net 中的类" href="http://gceclub.sun.com.cn/Java_Docs/html/zh_CN/api/java/net/MulticastSocket.html"><code>MulticastSocket</code></a> 是 DatagramSocket 的子类，在处理多播组时使用。</li>
</ul>
<p>使用 TCP 套接字的发送和接收操作需要借助 InputStream 和 OutputStream 来完成，这两者是通过 java.net.Socket.getInputStream 和 java.net.Socket.getOutputStream 方法获取的。</p>
<h4>高级API</h4>
<p>java.net 包中的许多类可以提供更加高级的抽象，允许方便地访问网络上的资源。这些类为：</p>
<ul>
<li><a title="java.net 中的类" href="http://gceclub.sun.com.cn/Java_Docs/html/zh_CN/api/java/net/URI.html"><code>URI</code></a> 是表示在 RFC 2396 中指定的统一资料标识符的类。顾名思义，它只是一个标识符，不直接提供访问资源的方法。</li>
<li><a title="java.net 中的类" href="http://gceclub.sun.com.cn/Java_Docs/html/zh_CN/api/java/net/URL.html"><code>URL</code></a> 是表示统一资源定位符的类，它既是 URI 的旧式概念又是访问资源的方法。</li>
<li><a title="java.net 中的类" href="http://gceclub.sun.com.cn/Java_Docs/html/zh_CN/api/java/net/URLConnection.html"><code>URLConnection</code></a> 是根据 URL 创建的，是用于访问 URL 所指向资源的通信链接。此抽象类将大多数工作委托给底层协议处理程序，如 http 或 ftp。</li>
<li><a title="java.net 中的类" href="http://gceclub.sun.com.cn/Java_Docs/html/zh_CN/api/java/net/HttpURLConnection.html"><code>HttpURLConnection</code></a> 是 URLConnection 的子类，提供一些特定于 HTTP 协议的附加功能。</li>
</ul>
<p>建议的用法是使用 <a title="java.net 中的类" href="http://gceclub.sun.com.cn/Java_Docs/html/zh_CN/api/java/net/URI.html"><code>URI</code></a> 指定资源，然后在访问资源时将其转换为 <a title="java.net 中的类" href="http://gceclub.sun.com.cn/Java_Docs/html/zh_CN/api/java/net/URL.html"><code>URL</code></a>。从该 URL 可以获取 <a title="java.net 中的类" href="http://gceclub.sun.com.cn/Java_Docs/html/zh_CN/api/java/net/URLConnection.html"><code>URLConnection</code></a> 以进行良好控制，也可以直接获取 InputStream。</p>
<p>下面是一个示例：</p>
<pre class="brush: java;">
URI uri = new URI(&quot;http://java.sun.com/&quot;);
URL url = uri.toURL();
InputStream in = url.openStream();
</pre>
<h4>URLConnection 和 HttpURLConnection 的使用：</h4>
<p>抽象类 URLConnection 是所有表示应用程序与 URL 之间通信链路的类的超类。该类的实例可以用来对由 URL 引用的资源进行读取和写入操作</p>
<p>HttpURLConnection 仅是支持了 HTTP 特定功能的 URLConnection</p>
<ol>
<li>通过调用 URL 的 <code>openConnection</code> 方法产生一连接对象。</li>
<li>操纵设置参数和一般请求属性。</li>
<li>使用 <code>connect</code> 方法，实现对远程对象的实际连接。</li>
<li>远程对象一旦可用，就可以访问远程对象的域和内容。</li>
</ol>
<p>通过如下的方法修改设置参数：</p>
<ul><code> </code></p>
<li>setAllowUserInteraction</li>
<li>setDoInput</li>
<li>setDoOutput</li>
<li>setIfModifiedSince</li>
<li>setUseCaches</li>
</ul>
<p>通过使用如下的方法修改一般请求属性：</p>
<ul><code> </code></p>
<li>setRequestProperty</li>
</ul>
<p><code>AllowUserInteraction</code> 和 <code>UseCaches</code> 参数的缺省值可以通过使用 <code>setDefaultAllowUserInteraction</code> 和 <code>setDefaultUseCaches</code> 方法来设置。 而一般请求属性的缺省值可以通过方法 <code>setDefaultRequestProperty</code> 来设置 。</p>
<p>上面的每个 <code>set</code> 方法都有相应 <code>get</code> 方法来获取参数和一般请求属性的值。可用的特定参数和一般请求属性是特定于协议的。</p>
<p>对远程对象的连接完成后，用下列方法访问报头域和内容：</p>
<ul><code> </code></p>
<li>getContent</li>
<li>getHeaderField</li>
<li>getInputStream</li>
<li>getOutputStream</li>
</ul>
<p>确认报头域能够被频繁访问。方法：</p>
<ul><code> </code></p>
<li>getContentEncoding</li>
<li>getContentLength</li>
<li>getContentType</li>
<li>getDate</li>
<li>getExpiration</li>
<li>getLastModified</li>
</ul>
<p>提供对这些域的便利访问。 <code>getContentType</code> 方法由 <code>getContent</code> 方法调用以确定远程对象的类型； 子类来覆盖方法 <code>getContentType</code> 可能是有利的。</p>
<p>下面是一个通过Twitter API去获信息的demo：</p>
<pre class="brush: java;">
        URL url = new URL(&quot;http://t.bbercn.com/statuses/user_timeline.xml&quot;);
        String username = (String) params[0];
        String password = (String) params[1];
        String user_paw = username + &quot;:&quot; + password;
        String encoding = &quot;Basic &quot; + Base64Converter.encode(user_paw.getBytes());
        URLConnection uc = url.openConnection();
        uc.setRequestProperty(&quot;Authorization&quot;, encoding);
        InputStream content = (InputStream) uc.getInputStream();
</pre>
<p>剩下的工作就是对InputStream 进行本地处理，Twitter返回的是XML，那么我们下面就对XML进行解析，获取我们要获取的信息。</p>
<h3>XML Parser</h3>
<p>关于 xml 解析的工具有很多，具体可以看这里：http://www.open-open.com/31.htm 罗列的一些。</p>
<p>下面通过Commons-Digester来处理上面我们获取的InputStream</p>
<pre class="brush: java;">
public class ParseTools {

    private List statuses = new ArrayList&lt;Status&gt;();

    public List&lt;Status&gt; getStatuses() {
        Collections.sort(statuses);
        return statuses;
    }

    public void parseStatus(InputStream stream) throws IOException, SAXException {
        Digester digester = new Digester();
        digester.setValidating(false);
        digester.push(this);

        digester.addObjectCreate(&quot;statuses/status&quot;, Status.class);
        //status
        digester.addBeanPropertySetter(&quot;statuses/status/id&quot;);
        digester.addBeanPropertySetter(&quot;statuses/status/created_at&quot;);
        digester.addBeanPropertySetter(&quot;statuses/status/text&quot;);
        digester.addBeanPropertySetter(&quot;statuses/status/source&quot;);
        digester.addBeanPropertySetter(&quot;statuses/status/truncated&quot;);
        digester.addBeanPropertySetter(&quot;statuses/status/in_reply_to_status_id&quot;);
        digester.addBeanPropertySetter(&quot;statuses/status/in_reply_to_user_id&quot;);
        digester.addBeanPropertySetter(&quot;statuses/status/favorited&quot;);
        digester.addBeanPropertySetter(&quot;statuses/status/in_reply_to_screen_name&quot;);
        //user
        digester.addObjectCreate(&quot;statuses/status/user&quot;, User.class);
        digester.addBeanPropertySetter(&quot;statuses/status/user/id&quot;);
        digester.addBeanPropertySetter(&quot;statuses/status/user/name&quot;);
        digester.addBeanPropertySetter(&quot;statuses/status/user/screen_name&quot;);
        digester.addBeanPropertySetter(&quot;statuses/status/user/description&quot;);
        digester.addBeanPropertySetter(&quot;statuses/status/user/location&quot;);
        digester.addBeanPropertySetter(&quot;statuses/status/user/profile_image_url&quot;);
        digester.addBeanPropertySetter(&quot;statuses/status/user/url&quot;);
        digester.addBeanPropertySetter(&quot;statuses/status/user/isProtected&quot;);
        digester.addBeanPropertySetter(&quot;statuses/status/user/followers_count&quot;);
        digester.addBeanPropertySetter(&quot;statuses/status/user/friends_count&quot;);
        digester.addSetNext(&quot;statuses/status/user&quot;, &quot;setUser&quot;);
        digester.addSetNext(&quot;statuses/status&quot;, &quot;addStatuses&quot;, Status.class.getName());
        digester.parse(stream);
    }

    public void addStatuses(Status status) {
        Status d = new Status();
        d.setId(status.getId());
        d.setCreated_at(status.getCreated_at());
        d.setFavorited(status.isFavorited());
        d.setText(status.getText());
        d.setSource(status.getSource());
        d.setTruncated(status.isTruncated());
        d.setIn_reply_to_screen_name(status.getIn_reply_to_screen_name());
        d.setIn_reply_to_status_id(status.getIn_reply_to_status_id());
        d.setIn_reply_to_user_id(status.getIn_reply_to_user_id());
        d.setUser(status.getUser());
        getStatuses().add(d);
    }
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.quanlei.com/2009/12/java-net-and-xml-parser/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[09/50周主题] – JQuery入门</title>
		<link>http://www.quanlei.com/2009/12/0950-week-subject-jquery/</link>
		<comments>http://www.quanlei.com/2009/12/0950-week-subject-jquery/#comments</comments>
		<pubDate>Wed, 16 Dec 2009 14:54:17 +0000</pubDate>
		<dc:creator>小权</dc:creator>
				<category><![CDATA[前端开发]]></category>
		<category><![CDATA[周主题]]></category>
		<category><![CDATA[Ajax]]></category>
		<category><![CDATA[Dom]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[JQuery]]></category>
		<category><![CDATA[xml]]></category>
		<category><![CDATA[事件]]></category>
		<category><![CDATA[对象]]></category>
		<category><![CDATA[类]]></category>

		<guid isPermaLink="false">http://www.quanlei.com/?p=1073</guid>
		<description><![CDATA[周三赶鸭子上架的组织了一次JQuery入门培训，由于时间上的原因，自己没做Demo，拿官方现成的，主要是认识JQuery，了解JQuery核心函数，介绍一些常用的选择器，还有事件处理，以及Ajax的使用，这里简单分享下： 本周主题：JQuery 一、JQuery核心认识 $ 表示JQuery类，$(&#8230;) 构造一个JQuery类，这里的JQuery类是一个集合数组对象，而非Dom对象。 jQuery(expression,[context]) $(&#34;div &#62; p&#34;); $(&#34;input:radio&#34;, document.forms[0]); $(&#34;div&#34;, xml.responseXML); jQuery( html ) $(&#34;&#60;div&#62;Hello&#60;/div&#62;&#34;).appendTo(&#34;body&#34;); 主要用来加载html jQuery( elements ) $(document.body).css(&#34;background-color&#34;, &#34;black&#34;); $(myForm.elements).hide(); jQuery( callback ) $(function(){ alert('hello'); }); JQuey中执行方法是在页面加载结束后，官方解释是：A shorthand for $(document).ready(). 二、JQuery选择器 JQuery选择器是JQuery的一大亮点，快捷，高效的遍历整个HTML文档，常用的如下面几种： $(&#34;#id&#34;); $(&#34;div&#34;); $(&#34;.className&#34;); $(&#34;div,span,p.myClass&#34;) $(&#34;form input&#34;) $(&#34;form &#62; input&#34;) 强烈建议直接看官方文档：http://docs.jquery.com/Selectors 三、JQuery事件 $(&#34;p&#34;).bind(&#34;click&#34;, function(e){}); $(&#34;p&#34;).click(function() {}) trigger( event, data [...]]]></description>
			<content:encoded><![CDATA[<p><span style="color: #800000;"><span style="font-size: xx-large;">周</span></span>三赶鸭子上架的组织了一次JQuery入门培训，由于时间上的原因，自己没做Demo，拿官方现成的，主要是认识JQuery，了解JQuery核心函数，介绍一些常用的选择器，还有事件处理，以及Ajax的使用，这里简单分享下：</p>
<h2>本周主题：JQuery</h2>
<h3>一、JQuery核心认识</h3>
<blockquote><p>$ 表示JQuery类，$(&#8230;) 构造一个JQuery类，这里的JQuery类是一个集合数组对象，而非Dom对象。</p>
<h4>jQuery(expression,[context])</h4>
<blockquote><pre class="brush: xml;">
$(&quot;div &gt; p&quot;);
$(&quot;input:radio&quot;, document.forms[0]);
$(&quot;div&quot;, xml.responseXML);
</pre>
</blockquote>
<h4>jQuery( html )</h4>
<blockquote><pre class="brush: xml;">
$(&quot;&lt;div&gt;Hello&lt;/div&gt;&quot;).appendTo(&quot;body&quot;);
</pre>
<p>主要用来加载html</p></blockquote>
<h4>jQuery( elements )</h4>
<blockquote><pre class="brush: xml;">
$(document.body).css(&quot;background-color&quot;, &quot;black&quot;);
$(myForm.elements).hide();
</pre>
</blockquote>
<h4>jQuery( callback )</h4>
<blockquote><pre class="brush: xml;">
$(function(){
  alert('hello');
});
</pre>
<p>JQuey中执行方法是在页面加载结束后，官方解释是：A shorthand for $(document).ready().</p></blockquote>
</blockquote>
<h3>二、JQuery选择器</h3>
<blockquote><p>JQuery选择器是JQuery的一大亮点，快捷，高效的遍历整个HTML文档，常用的如下面几种：</p>
<pre class="brush: xml;">
$(&quot;#id&quot;);
$(&quot;div&quot;);
$(&quot;.className&quot;);
$(&quot;div,span,p.myClass&quot;)
$(&quot;form input&quot;)
$(&quot;form &gt; input&quot;)
</pre>
<p>强烈建议直接看官方文档：<a href="http://docs.jquery.com/Selectors ">http://docs.jquery.com/Selectors</a></p></blockquote>
<h3>三、JQuery事件</h3>
<blockquote><pre class="brush: xml;">
$(&quot;p&quot;).bind(&quot;click&quot;, function(e){});
$(&quot;p&quot;).click(function() {})
trigger( event, data ) //触发事件
triggerHandler( event, data ) //触发事件，但不触发浏览器的默认事件
$(&quot;p&quot;).live(&quot;click&quot;, function(){ //在p以及p的下面的子elements上都加上click事件
      $(this).after(&quot;&lt;p&gt;Another paragraph!&lt;/p&gt;&quot;);
});
</pre>
<p>更多，参见官方文档：<a href="http://docs.jquery.com/Events">http://docs.jquery.com/Events</a></p></blockquote>
<h3>四、JQuery Ajax</h3>
<blockquote><p>ajax这块感觉和其他框架没多少差别，用起来基本类似：<br />
1、$.post(&#8230;) 和 $.get(&#8230;)</p>
<blockquote><pre class="brush: jscript;">
$.post('save.cgi', {
    text: 'my string',
    number: 23
}, function() {
    alert('Your data has been saved.');
});
</pre>
</blockquote>
<p>2、$.ajax(&#8230;)</p>
<blockquote><pre class="brush: jscript;">
$.ajax({
    url: 'getdata.action',
    type: 'GET',
    dataType: 'html',
    Timeout: 1000,
    beforeSend: function(){
     // Handle the beforeSend event
   },
    success: function(html){
     // do something with html
   },
    complete: function(){
     // Handle the complete event
   },
    error: function(){
     alert('Error loading HTML document');
    },
});
</pre>
</blockquote>
</blockquote>
<h3>五、推荐阅读</h3>
<blockquote><p>
1、<a href="http://jquery.com/">http://jquery.com/</a><br />
2、<a href="http://jquery-api-zh-cn.googlecode.com/svn/trunk/index.html">jQuery 1.3 API 中文参考文档</a><br />
3、<a href="http://jqueryui.com/">http://jqueryui.com/</a><br />
4、<a href="http://jquery.org.cn/">http://jquery.org.cn/</a><br />
5、<a href="http://www.cnblogs.com/QLeelulu/archive/2008/04/21/1163021.html">有关Ajax的一个中文文章</a>
</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://www.quanlei.com/2009/12/0950-week-subject-jquery/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>周主题推迟一周</title>
		<link>http://www.quanlei.com/2009/12/week-subject-delay-a-week/</link>
		<comments>http://www.quanlei.com/2009/12/week-subject-delay-a-week/#comments</comments>
		<pubDate>Mon, 14 Dec 2009 08:47:46 +0000</pubDate>
		<dc:creator>小权</dc:creator>
				<category><![CDATA[周主题]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[xml]]></category>
		<category><![CDATA[主题]]></category>
		<category><![CDATA[任务]]></category>
		<category><![CDATA[公司]]></category>
		<category><![CDATA[培训]]></category>
		<category><![CDATA[忙]]></category>
		<category><![CDATA[项目]]></category>

		<guid isPermaLink="false">http://www.quanlei.com/?p=1070</guid>
		<description><![CDATA[由于最近另一个项目的启动，工作方面基本上是掐着时间在忙，所以周主题的任务就只能稍微往后推一周了。 预计本周四结合公司的培训内容，出一个有关JQuery的入门介绍，这个内容顺便就补给上周的周主题。 顺便预告下：接下来这周和下周会整理有关Java.Net包下一些常用类的使用，包括HttpClient的使用，以及XML Parser方面的汇总。]]></description>
			<content:encoded><![CDATA[<p><span style="font-size: xx-large;"><span style="color: #800000;">由</span></span>于最近另一个项目的启动，工作方面基本上是掐着时间在忙，所以周主题的任务就只能稍微往后推一周了。</p>
<p>预计本周四结合公司的培训内容，出一个有关JQuery的入门介绍，这个内容顺便就补给上周的周主题。</p>
<p>顺便预告下：接下来这周和下周会整理有关Java.Net包下一些常用类的使用，包括HttpClient的使用，以及XML Parser方面的汇总。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.quanlei.com/2009/12/week-subject-delay-a-week/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>通过Java实现你的twitter应用</title>
		<link>http://www.quanlei.com/2009/09/write-your-own-twitter-app/</link>
		<comments>http://www.quanlei.com/2009/09/write-your-own-twitter-app/#comments</comments>
		<pubDate>Wed, 09 Sep 2009 07:01:06 +0000</pubDate>
		<dc:creator>小权</dc:creator>
				<category><![CDATA[技术]]></category>
		<category><![CDATA[编程相关]]></category>
		<category><![CDATA[dom4j]]></category>
		<category><![CDATA[HttpClient]]></category>
		<category><![CDATA[iText]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[twitter]]></category>
		<category><![CDATA[xml]]></category>

		<guid isPermaLink="false">http://www.quanlei.com/?p=654</guid>
		<description><![CDATA[关于Twitter这里就不多介绍了, 基本上能看到这篇文章的都用过的, 当然不知道也没关系, Google一下.由于Twitter的API 开放性, 所以其应用现在可以用多如牛毛也描述了, 各种各样的, 本文基于Java, 通过twitter API来获取twitter消息, 并以PDF的形式进行归档.准备工具: 1. HttpClient 3.x 库文件, 通过此库来从Twitter API获取消息, 同时需要 Comomons Logging 和 Codec 两个库文件. 请自行下载. 2. dom4j 库文件, 通过此库来解析Twitter的消息XML和获取中间的数据. 3. iText 库文件, 用来创建PDF文档. 每个Twitter应用都是基于twitter API来实现的, 有关Twitter API的使用可以看这里: Twitter API wiki(官方的,需要翻墙), 这里我们假设你只对获取数据感兴趣, 同时想以某种方式显示他们, 至于其他功能, 相信通过本教程的介绍, 你可以自己去钻研了.从TweetConsumer开始: import org.dom4j.Element; public interface TweetConsumer { public String tweet(Element element) throws [...]]]></description>
			<content:encoded><![CDATA[<p><span style="color: #000000;">关于Twitter这里就不多介绍了, 基本上能看到这篇文章的都用过的, 当然不知道也没关系,  Google一下.由于Twitter的API 开放性, 所以其应用现在可以用多如牛毛也描述了, 各种各样的, 本文基于Java,  通过twitter API来获取twitter消息, 并以PDF的形式进行归档.准备工具:</span></p>
<p><em>1. </em><a href="http://hc.apache.org/httpclient-3.x/"><span style="color: #000000; font-size: x-small;"><em>HttpClient 3.x</em></span></a><span style="font-size: x-small;"><em> 库文件, 通过此库来从Twitter  API获取消息, 同时需要 Comomons </em></span><a href="http://commons.apache.org/logging/"><span style="color: #000000; font-size: x-small;"><em>Logging</em></span></a><span style="font-size: x-small;"><em> 和 </em></span><a href="http://commons.apache.org/codec/"><span style="color: #000000; font-size: x-small;"><em>Codec</em></span></a><span style="font-size: x-small;"><em> 两个库文件. 请自行下载.</em></span><span style="font-size: x-small;"><em><span style="font-size: x-small;"><em> </em></span></em></span></p>
<p><span style="font-size: x-small;"><em>2. </em></span><a href="http://dom4j.org/"><span style="color: #000000; font-size: x-small;"><em>dom4j</em></span></a><span style="font-size: x-small;"><em> 库文件,  通过此库来解析Twitter的消息XML和获取中间的数据.</em></span><span style="font-size: x-small;"><em> </em></span></p>
<p><span style="font-size: x-small;"><em><span style="font-size: x-small;"><em>3. <a href="http://1t3xt.com/products/itext.php">iText</a> 库文件, 用来创建PDF文档.</em></span></em></span></p>
<p><span style="font-size: x-small;"><em><span style="font-size: x-small;"><em> </em></span></em></span><br />
<span style="color: #000000;"><span style="font-size: x-small;">每个Twitter应用都是基于twitter API来实现的, 有关Twitter API的使用可以看这里: <a href="http://apiwiki.twitter.com/">Twitter API wiki</a>(官方的,需要翻墙),  这里我们假设你只对获取数据感兴趣, 同时想以某种方式显示他们, 至于其他功能, 相信通过本教程的介绍, 你可以自己去钻研了.</span><span style="font-size: x-small;">从TweetConsumer开始:</span>
<pre class="brush: java;">
import org.dom4j.Element;
public interface TweetConsumer {
    public String tweet(Element element) throws TweetException;
}
</pre>
<p>Twitter API提供XML, JSON 和RSS几种格式, 这里我们选择XML格式, 通过dom4j来解析, 上面是一个叫做TweetConsumer的借口, 作用就是来处理消息的, 其实现在后面会讲到.</p>
<p>自定义一个消息异常, 当出现问题时抛出:</p>
<pre class="brush: java;">
public class TweetException extends Exception {
    private static final long serialVersionUID = 7577136074623618615L;
    public TweetException(Exception e) {
        super(e);
    }
}
</pre>
<p>接下来是本文的重点, 通过Twitter API去获取消息:</p>
<pre class="brush: java;">
public class TweetProducer {
    protected HttpClient client;
    protected TweetConsumer consumer;

    public void createClient(String username, String password) {
        client = new HttpClient();
        client.getState().setCredentials(
            //由于GFW的原因, 直连twitter肯定是不行了, 建议使用第三方API,比如我的GAE应用:xiao-quan.appspot.com
            new AuthScope(&quot;twitter.com&quot;, 80, AuthScope.ANY_REALM),
            new UsernamePasswordCredentials(username, password));
        client.getParams().setAuthenticationPreemptive(true);
    }

    public void setConsumer(TweetConsumer consumer) {
        this.consumer = consumer;
    }

    public String execute(String since_id) throws TweetException {
        String id = null;
        String tmp;
        //由于GFW的原因, 直连twitter肯定是不行了, 建议使用第三方API,比如我的GAE应用:http://xiao-quan.appspot.com/api/statuses/friends_timeline.xml
        GetMethod get = new GetMethod(&quot;http://twitter.com/statuses/friends_timeline.xml&quot;);
        if (since_id != null &amp;amp;&amp;amp; since_id.length() &gt; 0) {
            get.setQueryString(&quot;?count=200&amp;amp;since_id=&quot; + since_id);
        }
        else {
            get.setQueryString(&quot;?count=200&quot;);
        }
        get.setDoAuthentication(true);
        try {
            client.executeMethod(get);
            SAXReader reader = new SAXReader();
            Document document = reader.read(get.getResponseBodyAsStream());
            Element root = document.getRootElement();
            for (Iterator i = root.elementIterator(); i.hasNext(); ) {
                tmp = consumer.tweet((Element)i.next());
                if (id == null) id = tmp;
            }
        } catch (HttpException e) {
            throw new TweetException(e);
        } catch (IOException e) {
            throw new TweetException(e);
        } catch (DocumentException e) {
            throw new TweetException(e);
        } finally {
            get.releaseConnection();
        }
        return id;
    }
}
</pre>
<p>TweetProducer 里面有三个方法:<br />
<em> createClient(), 创建HttpClient对象, 通过HttpClient来连接Twitter API, 由于Twitter使用了HTTP Basic Authentication,<br />
所以你需要提供你的twitter用户名和密码来登录, 获取你的朋友们的消息.<br />
setConsumer(), 传一个TweetConsumer接口给TweetProducer, 我们有多种输出方案, 当然这里要通用点.<br />
excute(), 这是才是做事情的地方, 获取哪个消息ID以后的消息, 返回一个消息ID.<br />
</em></p>
<p>获取消息:</p>
<pre class="brush: java;">
GetMethod get = new GetMethod(&quot;http://twitter.com/statuses/friends_timeline.xml&quot;);
</pre>
<p>Twitter API默认获取的消息条数是20, 最大200, 你可以自己定义获取的数量, 同时也可以通过一些参数来指定获取第几页的消息等, 具体使用参考Twitter API WIKI上的定义.</p>
<p>例如, 获取消息ID为since_id以后的200个消息:</p>
<pre class="brush: java;">
get.setQueryString(&quot;?count=200&amp;since_id=&quot; + since_id);
</pre>
<p>设置完查询条件后, 执行:</p>
<pre class="brush: java;">
client.executeMethod(get);
</pre>
<p>将返回的信息传给SAXReader,以便获取消息root:</p>
<pre class="brush: java;">
SAXReader reader = new SAXReader();
Document document = reader.read(get.getResponseBodyAsStream());
Element root = document.getRootElement();
</pre>
<p>最后迭代每个带 标签的Element:</p>
<pre class="brush: java;">
for (Iterator i = root.elementIterator(); i.hasNext(); ) {
    tmp = consumer.tweet((Element)i.next());
    if (id == null) id = tmp;
}
</pre>
<p>由于Twitter的消息列表是按时间降序排列, 那么第一个消息就是最新的消息了, 这个消息ID就是excute()要返回的String.</p>
<p>获取到消息后, 接下来我们就输出消息:</p>
<pre class="brush: java;">
import org.dom4j.Element;

public class SystemOutTweets implements TweetConsumer {
    public String tweet(Element tweet) {
        System.out.println(tweet.asXML());
        return tweet.elementText(&quot;id&quot;);
    }

    public static void main(String[] args) throws TweetException {
        TweetProducer t = new TweetProducer();
        t.createClient(&quot;gavinquan&quot;, &quot;123456&quot;);
        t.setConsumer(new SystemOutTweets());
        System.out.println(&quot;Start tweeting:&quot;);
        String id = t.execute(null);
        System.out.println(&quot;The End; last tweet: &quot; + id);
    }
}
</pre>
<p>将上面的介绍的代码整理好, 并执行, 就会在控制台输出, XML格式的消息列表, 如下是其中的一个片段:</p>
<pre class="brush: xml;">
&lt;status&gt;
  &lt;created_at&gt;Wed Sep 09 06:07:04 +0000 2009&lt;/created_at&gt;
  &lt;id&gt;3858278078&lt;/id&gt;
  &lt;text&gt;gmail服务器错误了？&lt;/text&gt;
  &lt;source&gt;&lt;a href=&quot;http://twitterfox.net/&quot; rel=&quot;nofollow&quot;&gt;TwitterFox&lt;/a&gt;&lt;/source&gt;
  &lt;truncated&gt;false&lt;/truncated&gt;
  &lt;in_reply_to_status_id/&gt;
  &lt;in_reply_to_user_id/&gt;
  &lt;favorited&gt;false&lt;/favorited&gt;
  &lt;in_reply_to_screen_name/&gt;
  &lt;user&gt;
    &lt;id&gt;10415752&lt;/id&gt;
    &lt;name&gt;hugege&lt;/name&gt;
    &lt;screen_name&gt;hugege&lt;/screen_name&gt;
    &lt;location&gt;Shantou Guangdong China &lt;/location&gt;
    &lt;description&gt;www.gegehost.com 博客主机服务&lt;/description&gt;
    &lt;profile_image_url&gt;http://a1.twimg.com/profile_images/329549706/hugegelogo_normal.jpg&lt;/profile_image_url&gt;
    &lt;url&gt;http://hugege.com/&lt;/url&gt;
    &lt;protected&gt;false&lt;/protected&gt;
    &lt;followers_count&gt;1607&lt;/followers_count&gt;
    &lt;profile_background_color&gt;C6E2EE&lt;/profile_background_color&gt;
    &lt;profile_text_color&gt;663B12&lt;/profile_text_color&gt;
    &lt;profile_link_color&gt;1F98C7&lt;/profile_link_color&gt;
    &lt;profile_sidebar_fill_color&gt;DAECF4&lt;/profile_sidebar_fill_color&gt;
    &lt;profile_sidebar_border_color&gt;C6E2EE&lt;/profile_sidebar_border_color&gt;
    &lt;friends_count&gt;1335&lt;/friends_count&gt;
    &lt;created_at&gt;Tue Nov 20 16:00:58 +0000 2007&lt;/created_at&gt;
    &lt;favourites_count&gt;3&lt;/favourites_count&gt;
    &lt;utc_offset&gt;28800&lt;/utc_offset&gt;
    &lt;time_zone&gt;Beijing&lt;/time_zone&gt;
    &lt;profile_background_image_url&gt;http://s.twimg.com/a/1252448032/images/themes/theme2/bg.gif&lt;/profile_background_image_url&gt;
    &lt;profile_background_tile&gt;false&lt;/profile_background_tile&gt;
    &lt;statuses_count&gt;1540&lt;/statuses_count&gt;
    &lt;notifications&gt;false&lt;/notifications&gt;
    &lt;verified&gt;false&lt;/verified&gt;
    &lt;following&gt;false&lt;/following&gt;
  &lt;/user&gt;
&lt;/status&gt;
</pre>
<p>同时会输出, 你的最后一个消息的消息ID:</p>
<pre class="brush: java;">
The End; last tweet: 3858279409
</pre>
<p>当然你也可以直接通过这个ID, 来去获取你的该ID以后的消息:</p>
<pre class="brush: java;">
t.execute(&quot;3858279409&quot;);
</pre>
<p>OK, 到这里, 我们的任务已经过去一半多了, 获取twitter消息, 那么接下来的内容, 我们来看如何将消息以PDF的形式进行归档.</p>
<p>通过iText生成PDF, 需要5步, 请看下面的Demo :</p>
<pre class="brush: java;">
import java.io.FileOutputStream;
import com.lowagie.text.Document;
import com.lowagie.text.Paragraph;
import com.lowagie.text.pdf.PdfWriter;

public class HelloWorld {
    public static void main(String args[]) {
        try {
            // step 1: create a Document object
            Document document = new Document();
            // step 2: connect the Document with an OutputStream using a PdfWriter
            PdfWriter.getInstance(document, new FileOutputStream(&quot;hello.pdf&quot;));
            // step 3: open the document

            document.open();
            // step 4: add content
            document.add(new Paragraph(&quot;Hello World&quot;));
            // step 5: close the document
            document.close();
        } catch (Exception e) {
            System.out.println(e);
        }
    }
}
</pre>
<p>大体工作流程就如上面所说,相信都可以看懂, OK, 下面我就直接给出代码, 重点地方提一下.</p>
<p>PDFWriter类</p>
<pre class="brush: java;">
import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.Element;
import com.lowagie.text.Font;
import com.lowagie.text.PageSize;
import com.lowagie.text.Phrase;
import com.lowagie.text.Rectangle;
import com.lowagie.text.pdf.BaseFont;
import com.lowagie.text.pdf.PdfPTable;
import com.lowagie.text.pdf.PdfWriter;
import com.quanlei.exception.TweetException;
import com.quanlei.twitter.TweetConsumer;
import com.quanlei.twitter.TweetProducer;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class PdfTwitter implements TweetConsumer {

    private int counter = 0;
    private Document document;
    private Font small_white = new Font(Font.HELVETICA, 8, Font.BOLD);
    private Font bold = new Font(Font.HELVETICA, 11, Font.BOLD);
    private BaseFont bfChinese = BaseFont.createFont(&quot;STSong-Light&quot;,
            &quot;UniGB-UCS2-H&quot;, BaseFont.NOT_EMBEDDED);
    private Font FontChinese = new Font(bfChinese, 12, Font.NORMAL);
    private SimpleDateFormat simpleDateTimeFormat =
            new SimpleDateFormat(&quot;yyyy-MM-dd HH:mm:ss&quot;);

    public PdfTwitter() throws DocumentException, IOException {
        document = new Document(PageSize.A4, 72, 36, 36, 36);

        PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(
                &quot;world.pdf&quot;));
        writer.setPageEvent(new TwitterPage());
        document.open();
    }

    public void close() {
        document.close();
    }

    public String tweet(org.dom4j.Element tweet) throws TweetException {
        try {
            org.dom4j.Element user = tweet.element(&quot;user&quot;);
            PdfPTable table = new PdfPTable(new float[]{1, 10, 12});
            table.setTableEvent(new TableBackground());

            table.setWidthPercentage(100);
            table.setSpacingBefore(8);
            table.getDefaultCell().setPadding(5);
            table.getDefaultCell().setBorder(Rectangle.NO_BORDER);
            table.addCell(&quot;&quot;);
            table.addCell(new Phrase(user.elementText(&quot;screen_name&quot;),
                    small_white));
            table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_RIGHT);

            table.addCell(new Phrase(simpleDateTimeFormat.format(
                    new Date(tweet.elementText(&quot;created_at&quot;))),
                    small_white));
            table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_LEFT);
            table.getDefaultCell().setFixedHeight(38);
            table.addCell(new Phrase(String.valueOf(++counter), small_white));
            table.getDefaultCell().setColspan(2);
            Phrase p = new Phrase();
            p.add(new Phrase(user.elementText(&quot;name&quot;), FontChinese));
            p.add(new Phrase(&quot;: &quot;, bold));
            p.add(new Phrase(tweet.elementText(&quot;text&quot;), FontChinese));
            table.addCell(p);
            document.add(table);
            return tweet.elementText(&quot;id&quot;);
        } catch (DocumentException e) {
            e.printStackTrace();
            throw new TweetException(e);
        } catch (IOException e) {
            e.printStackTrace();
            throw new TweetException(e);
        }
    }

    public static void main(String[] args)
            throws DocumentException, org.dom4j.DocumentException,
            FileNotFoundException, IOException, TweetException {
        PdfTwitter pdf = new PdfTwitter();
        TweetProducer t = new TweetProducer();
        t.createClient(&quot;gavinquan&quot;, &quot;123456&quot;);
        t.setConsumer(pdf);
        t.execute(null);
        pdf.close();
    }
}
</pre>
<p>上面的类已经可以输出PDF了, 但是不是很美观, 加点修饰, 每个Twitter消息一个框, 这是背景:</p>
<pre class="brush: java;">
import java.io.IOException;
import com.lowagie.text.DocumentException;
import com.lowagie.text.Element;
import com.lowagie.text.pdf.BaseFont;
import com.lowagie.text.pdf.PdfContentByte;
import com.lowagie.text.pdf.PdfPTable;
import com.lowagie.text.pdf.PdfPTableEvent;

public class TableBackground implements PdfPTableEvent {

    protected BaseFont bf;

    public TableBackground() throws DocumentException, IOException {
        bf = BaseFont.createFont(BaseFont.TIMES_BOLDITALIC, BaseFont.WINANSI,
                BaseFont.NOT_EMBEDDED);
    }

    public void tableLayout(PdfPTable table, float[][] width, float[] height,
            int headerRows, int rowStart, PdfContentByte[] canvas) {
        PdfContentByte cb = canvas[PdfPTable.BACKGROUNDCANVAS];
        cb.saveState();
        cb.setRGBColorFill(0x9a, 0xe4, 0xe8);
        cb.roundRectangle(width[0][0], height[2], width[0][3] - width[0][0],
                height[0] - height[2], 4);
        cb.roundRectangle(width[0][1], height[2] + 3,
                width[0][3] - width[0][1] - 3, height[1] - height[2] - 6, 4);
        cb.eoFill();
        cb.beginText();
        cb.setRGBColorStroke(0x9a, 0xe4, 0xe8);
        cb.setFontAndSize(bf, 28);
        cb.setTextRenderingMode(PdfContentByte.TEXT_RENDER_MODE_STROKE);
        cb.showTextAligned(Element.ALIGN_LEFT, &quot;\&quot;&quot;, width[0][1],
                height[1] - 10, 0);
        cb.endText();
        cb.restoreState();
    }
}
</pre>
<p>下面再画蛇添足, 加点外围修饰, 每个PDF页面左侧加上文字, 算是起点宣传作用:</p>
<pre class="brush: java;">
import java.io.IOException;
import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.Element;
import com.lowagie.text.pdf.BaseFont;
import com.lowagie.text.pdf.PdfContentByte;
import com.lowagie.text.pdf.PdfPageEventHelper;
import com.lowagie.text.pdf.PdfWriter;

public class TwitterPage extends PdfPageEventHelper {

    protected BaseFont bf;

    public TwitterPage() throws DocumentException, IOException {
        bf = BaseFont.createFont(&quot;STSong-Light&quot;, &quot;UniGB-UCS2-H&quot;,
                BaseFont.NOT_EMBEDDED);
    }

    @Override
    public void onEndPage(PdfWriter writer, Document document) {
        PdfContentByte cb = writer.getDirectContent();
        cb.saveState();
        cb.beginText();
        cb.setRGBColorStroke(0x9a, 0xe4, 0xe8);
        cb.setTextRenderingMode(PdfContentByte.TEXT_RENDER_MODE_STROKE);
        cb.setFontAndSize(bf, 18);
        cb.showTextAligned(Element.ALIGN_RIGHT, &quot;www.quanlei.com&quot;, 68, 806, 90);
        cb.endText();
        cb.restoreState();
    }
}
</pre>
<p>最后配个截图, 为本文画上句号, 注, 由于图缩略了, 效果有点虚了:</p>
<p style="text-align: left;"><img title="PDF效果图" src="http://www.quanlei.com/wp-content/uploads/2009/09/pdf1.PNG" alt="PDF效果图" width="597" height="480" /></p>
<p>英文原版出处: http://www.javaworld.com/javaworld/jw-03-2009/jw-03-write-your-own-twitter-app.html , 本文抽取了原英文的重点, 并配以文字介绍,加工而成.</p>
<p></span></p>
]]></content:encoded>
			<wfw:commentRss>http://www.quanlei.com/2009/09/write-your-own-twitter-app/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
