隨筆 - 1  文章 - 0  trackbacks - 0
          <2008年1月>
          303112345
          6789101112
          13141516171819
          20212223242526
          272829303112
          3456789

          常用鏈接

          留言簿(1)

          隨筆檔案

          搜索

          •  

          最新評(píng)論

          前兩天上新浪,看到新浪 RSS 頻道開通,不容易啊,等了這么久。
              
              我的目標(biāo)是做一個(gè)簡(jiǎn)單的portlet,每次讀取新浪的RSS站點(diǎn)顯示最新的新聞條目。

              花了一個(gè)下午,去sourceforge和google 上搜索 opensource 的 java rss lib,還真有不少(順便提一下,sourceforget的搜索真的很爛)。簡(jiǎn)單過(guò)濾以后,覺(jué)得以下三個(gè)類庫(kù)比較有搞頭。Rome 、rssutils和rsslib4j。具體的評(píng)測(cè)如下:

          一. Rome
              Rome 是 java.net 上的一個(gè)開源項(xiàng)目,現(xiàn)在的版本是0.5。為什么叫Rome呢,按它的介紹上的說(shuō)法,有個(gè)“條條大路通羅馬”的意思,有些RSS的意味。Rome可能是 sun 公司從自己某個(gè)子項(xiàng)目中抽離出來(lái)的,package和類的命名就象j2sdk一樣感覺(jué)規(guī)范。功能上支持RSS的所有版本及 Atom 0.3(Atom是和RSS類似的一種內(nèi)容聚合的方式)。Rome 本身是提供API和功能實(shí)現(xiàn),其下獨(dú)立出一個(gè) rome-fetcher 項(xiàng)目,專門用來(lái)讀取RSS內(nèi)容。正和我意啊。
              參照 fetcher 上的范例,解析 RSS 相當(dāng)簡(jiǎn)單,代碼片斷如下:

              FeedFetcher fetcher = new HttpURLFeedFetcher();
              SyndFeed feed = fetcher.retrieveFeed(feedUrl);
              System.out.println(feedUrl + " has a title: " + new String(feed.getTitle().getBytes("iso8859-1"), "utf-8") + " and contains "     + feed.getEntries().size() + " entries.");
              for (Iterator iter = feed.getEntries().iterator(); iter.hasNext(); ) {
                  SyndEntry entry = (SyndEntry) iter.next();
                  System.out.println("<a href=" + entry.getLink() + ">" + entry.getTitle() + "</a>[" + entry.getPublishedDate() + "]");
              }
              
              為什么用  new String(feed.getTitle().getBytes("iso8859-1"), "utf-8")  進(jìn)行轉(zhuǎn)碼,是因?yàn)镽ome來(lái)解析 新浪新聞 RSS的時(shí)候試圖從 URLConnection 的 header  中得到編碼信息,否則總是用 iso8859-1。而新浪的RSS response header 中不包含編碼信息,所以要做一番轉(zhuǎn)碼。另外還有就是 entry.getPubDate() 也將返回null,因?yàn)镽ome 用多種pattern 去試圖解析時(shí)間信息,新浪的時(shí)間格式還是符合RFC822的,但是Rome 使用SimpleDateFormat 來(lái)解析時(shí)間,它忘記了一點(diǎn),就是 SimpleDateFormat的解析是關(guān)聯(lián)于 Locale 的,所以由于我本地locale是China,SimpleDateFormat的parse方法解析不出英文的時(shí)間字符。以上代碼前加 Locale.setDefault(Locale.Englisth) 可以搞定,但總覺(jué)得不爽。

              如果也不想轉(zhuǎn)碼的話,Rome 還提供了一個(gè) XmlReader 的類,通過(guò)分析 header 和 xml 內(nèi)容推斷 encoding,修改 HttpURLFeedFetcher 的源碼 :

              // 改變 InputStreamReader , 換用 XmlReader
              //InputStreamReader reader = new InputStreamReader(is, ResponseHandler.getCharacterEncoding(connection));
              XmlReader reader = new XmlReader(connection);
              SyndFeedInput input = new SyndFeedInput();
              SyndFeed feed = input.build(reader);

              那么中文不用轉(zhuǎn)碼也能正確顯示了,不過(guò)修改源碼后我再解析 百度新聞 RSS 的時(shí)候,底層的JDOM卻會(huì)抱錯(cuò)說(shuō)xml 格式不正確。也許Rome的開發(fā)者也遇到過(guò)這樣的問(wèn)題,所以才沒(méi)有使用 XmlReader。

          二. rssutils
              它是一個(gè)工具包,sun 的 develope站點(diǎn)上有文章 RSS Utilities: A Tutorial 專門介紹用taglib 顯示RSS內(nèi)容,附帶的可以下載這個(gè)工具包,但我從網(wǎng)上搜索不到它的出處,自然也無(wú)法看到它的源碼。但從反編譯的代碼來(lái)看,也是sun公司內(nèi)部高手所做,設(shè)計(jì)精巧,代碼簡(jiǎn)練。實(shí)現(xiàn)一個(gè)handler,用sax的方式解析xml內(nèi)容,handler內(nèi)部用反射和javabean的機(jī)制構(gòu)造RSS元素對(duì)象并賦值。代碼片斷如下:

                  RssParser parser = new RssParserImpl();
                  Rss rss = parser.parse(new URL(url));
                  System.out.println(rss.getChannel().getTitle());
                  for (Iterator iter = rss.getChannel().getItems().iterator(); iter.hasNext();) {
                      Item item = (Item)iter.next();
                      System.out.println("<a href=" + item.getLink() + "</a>" + item.getTitle() + " " + item.getPubDate());
                  }

              如上所示,代碼也是相當(dāng)簡(jiǎn)單,沒(méi)有轉(zhuǎn)碼的需求,時(shí)間也正確顯示(因?yàn)楦緵](méi)做分析,當(dāng)字符串直接返回)。但是該工具包并非真正對(duì)外公布,代碼中有些不嚴(yán)謹(jǐn)?shù)牡胤剑鏢ystem.out的輸出,很不爽。而且如果 RSS 的 xml內(nèi)容如果缺少部分不常用元素 ,它也會(huì)printStackTrace一大串,服了它了。另外還有一個(gè)大問(wèn)題,就是當(dāng)我用它解析 百度新聞 的時(shí)候,直接就報(bào)錯(cuò):org.xml.sax.SAXParseException: 字符轉(zhuǎn)換錯(cuò)誤:“Unconvertible UTF-8 character beginning with 0xb0”。網(wǎng)上查了查,可能是 java 修改過(guò)的 UTF-8 和標(biāo)準(zhǔn) UTF-8 些微不兼容導(dǎo)致。詳情參看 Java 平臺(tái)中的增補(bǔ)字符 一文。

          三.  rsslib4j
              rsslib4j 是 sourceforget 上的項(xiàng)目,主頁(yè)是 http://sourceforge.net/projects/rsslib4j,現(xiàn)在最新的版本是0.2,才0.2,可是開發(fā)狀態(tài)卻已經(jīng)是穩(wěn)定產(chǎn)品化了。同樣支持所有RSS版本。
              rsslib4j 解析 RSS 的方式和 rssutils 一樣,我看了看源碼,設(shè)計(jì)比較簡(jiǎn)單,代碼可讀性一般,大量使用if。代碼片斷如下:

                  RSSHandler hand = new RSSHandler();
                  RSSParser.parseXmlFile(new URL(url), hand, false);
                  RSSChannel ch = hand.getRSSChannel();
                  System.out.println(ch.toString());
                  LinkedList lst = hand.getRSSChannel().getItems();
                  for (int i = 0; i < lst.size(); i++) {
                      RSSItem itm = (RSSItem) lst.get(i);
                      System.out.println(itm.toString());
                 }

              看起來(lái)也是相當(dāng)清晰易懂,執(zhí)行結(jié)果也和rssutils一樣,不過(guò)用它來(lái)解析 百度新聞 卻不會(huì)出現(xiàn) rssutils 的utf-8編碼錯(cuò)誤,真是奇怪,兩者都是調(diào)JAXP的 SAXParser 。不過(guò)它的代碼也有bug,不能解析出 channel 的一些信息,查看源碼,有點(diǎn)簡(jiǎn)單邏輯錯(cuò)誤,修正后解決。想寫封email給項(xiàng)目開發(fā)者可惜英文不行,通過(guò)cvs去commit一下也嫌麻煩,作罷。

          總結(jié)

          Rome:
          優(yōu) - 1)可擴(kuò)展性好,有前途。2)功能強(qiáng)大,除了用來(lái)解析RSS,還可以聚合和構(gòu)造RSS。
          劣 - 1)兼容性待加強(qiáng),2)綁定jdom。為什么不喜歡 jdom呢,因?yàn)樗黙pi 老變,還很絕,搞得不兼容。

          rssutils:
          優(yōu) - 1)代碼設(shè)計(jì)精妙,值得學(xué)習(xí)。2)附帶 taglib 實(shí)現(xiàn),直接可在 jsp 中應(yīng)用。
          劣 - 1)沒(méi)有源碼。 2)兼容性有待加強(qiáng)。 3)功能較弱,只能用來(lái)解析RSS,沒(méi)有聚合和構(gòu)造RSS功能。

          rsslib4j:
          優(yōu) - 1)簡(jiǎn)單有效,體積小。2)兼容性不錯(cuò)。
          劣 - 1)有小bug。2)功能較弱,只能用來(lái)解析RSS,沒(méi)有聚合和構(gòu)造RSS功能。

          編輯選擇: rsslib4j
          我只用來(lái)讀讀新浪新聞,rsslib4j 夠用就好,不過(guò)要自己修改和編譯源碼。

          Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=282333

          posted on 2008-01-31 00:23 wangxlyy 閱讀(356) 評(píng)論(0)  編輯  收藏

          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 桑日县| 高碑店市| 弋阳县| 沾益县| 黔江区| 宾阳县| 澳门| 恩平市| 连云港市| 永靖县| 体育| 南木林县| 石柱| 新竹县| 和顺县| 胶南市| 盱眙县| 荃湾区| 迭部县| 娄底市| 双辽市| 读书| 荆州市| 平定县| 岳普湖县| 蒲城县| 建瓯市| 历史| 霍邱县| 临夏县| 瑞安市| 綦江县| 沁源县| 湖北省| 盐亭县| 富平县| 尼玛县| 农安县| 辽源市| 讷河市| 如东县|