JAVA的RSS处理





一:什么是RSS
 RSS(really simple syndication)
:网页内容聚合器。RSS的格式是XML。必须符合XML
1.0规范。
 RSS的作用:订阅BLOG,订阅新闻
二:RSS的历史版本:
 http://blogs.law.harvard.edu/tech/rssVersionHistory
 RSS的版本有很多个,0.90、0.91、0.92、0.93、0.94、1.0

2.0。与RSS相对的还有ATOM。
 国内主要是RSS2.0,国外主要用ATOM0.3.
 由于RSS出现2派,导致混乱场面。其中RSS2.0规范由哈佛大学定义并锁定。
 地址:http://blogs.law.harvard.edu/tech/rss
三:RSS
文件形式
    1:例子:
 <?xml
version="1.0"?>
 <rss
version="2.0">
   
<channel>
    <title>The channel‘s name goes
here</title>
   
<link>http://www.urlofthechannel.com/</link>
   
<description>This channel is an example channel for an
article.
    </description>
   
<language>en-us</language>
   
<image>
      <title>The image
title goes here</title>
     
<url>http://www.urlofthechannel.com/images/logo.gif</url>
     
<link>http://www.urlofthechannel.com/</link>
   
</image>
   
<item>
      <title>The Future of
content</title>
     
<link>http://www.itworld.com/nl/ecom_in_act/11122003/</link>
     
<description> The issue of people distributing and
reusing
      digital media is a problem for
many businesses. It may also be
      a hidden
opportunity. Just as open source licensing has
opened
      up new possibilities in the world
of technology, it promises to do
      the
same in the area of creative
content.</description>
   
</item>
   
<item>
      <title>Online Music
Services - Better than
free?</title>
     
<link>http://www.itworld.com/nl/ecom_in_act/08202003/</link>
     
<description>More people than ever are downloading music from

      the Internet. Many use person-to-person
file sharing programs like
      Kazaa to
share and download music in MP3 format, paying nothing.

      This has made it difficult for
companies to setup online music
     
businesses. How can companies compete against
free?</description>
    </item>
 
</channel>
 </rss>
    2:RSS文件由一个
<channel> 元素及其子元素组成。除了频道内容本身之外,<channel>

 还以项的形式包含表示频道元数据的元素 —— 比如 <title>、<link> 和
<description>。
 项通常是频道的主要部分,包含经常变化的内容。
   
3:频道(channel)用<channel>表示
 频道一般有三个元素,提供关于频道本身的信息:
 <title>:频道或提要的名称。

 <link>:与该频道关联的 Web 站点或者站点区域的 URL。

 <description>:简要介绍该频道是做什么的。
 许多频道子元素都是可选的。常用的
<image> 元素包含三个必需的子元素:
 <url>:表示该频道的 GIF、JPEG 或 PNG 图像的
URL。
 <title>:图象的描述。当频道以 HTML 呈现时,用作 HTML <image> 标签的
ALT 属性。
 <link>:站点的 URL。如果频道以 HTML 呈现,该图像作为到这个站点的链接。

 <image>
还有三个可选的子元素:
 <width>:数字,表示图象的像素宽度,最大值是 188,默认值为 88。

 <height>:数字,表示图象的像素高度。最大值是 400,默认值为 31。

 <description>:包含文本,在呈现时可以作为围绕着该图像形成的链接元素的 title 属性。

 此外还可以使用许多其他可选的频道元素。多数都是不言自明的:
 <language>:en-us

 <copyright>:Copyright 2003, James Lewin

 <managingEditor>:[email protected]_me.com (Dan
Deletekey)
 <webMaster>:[email protected]_me.com (Dan
Deletekey)
 <pubDate>:Sat, 15 Nov 2003 0:00:01 GMT

 <lastBuildDate>:Sat, 15 Nov 2003 0:00:01 GMT

 <category>:ebusiness
 <generator>:Your CMS
2.0
 <docs>:http://blogs.law.harvard.edu/tech/rss

 <cloud>:允许进程注册为“cloud”,频道更新时通知它,为 RSS 提要实现了一种轻量级的发布-订阅协议。

 <ttl>:存活时间 是一个数字,表示提要在刷新之前缓冲的分钟数。

 <rating>:关于该频道的 PICS 评价。

 <textInput>:定义可与频道一起显示的输入框。

 <skipHours>:告诉聚集器哪些小时的更新可以忽略。

 <skipDays>:告诉聚集器那一天的更新可以忽略。
   
4:摘要(feed)用<item>表示,<item>的格式如下:
 每个摘要通常包含三个元素:
 <title>:这是项的名称,在标准应用中被转换成
HTML 中的标题。
 <link>:这是该项的 URL。title 通常作为一个链接,指向包含在
<link> 元素中的 URL。
 <description>:通常作为 link 中所指向的 URL
的摘要或者补充。
 所有的元素都是可选的,但是一个项至少要么 包含一个 <title>,要么包含一个
<description>。
 项还有其他一些可选的元素:
 <author>:作者的
e-mail 地址。
 <category>:支持有组织的记录。

 <comments>:关于项的注释页的 URL。

 <enclosure>:支持和该项有关的媒体对象。

 <guid>:唯一与该项联系在一起的永久性链接。

 <pubDate>:该项是什么时候发布的。
 <source>:该项来自哪个 RSS
频道,当
四:主流java rss lib及其评测:
 主要有一下几种:
   
1:Rome: http://wiki.java.net/bin/view/Javawsxml/Rome
 Rome是
java.net
上的一个开源项目,现在的版本是0.5。为什么叫Rome呢,按它的介绍上的说法,有个“条条大路通罗马”的意思,有些RSS的意味。Rome可能是 sun
公司从自己某个子项目中抽离出来的,package和类的命名就象j2sdk一样感觉规范。功能上支持RSS的所有版本及 Atom
0.3(Atom是和RSS类似的一种内容聚合的方式)。Rome 本身是提供API和功能实现.
   
2:rssutils: http://gceclub.sun.com.cn/staticcontent/html/2004-04-22/rss.html
 rssutils是一个工具包,sun
的 develope站点上有文章 RSS Utilities: A Tutorial 专门介绍用taglib
显示RSS内容,附带的可以下载这个工具包,但我从网上搜索不到它的出处,自然也无法看到它的源码。但从反编译的代码来看,也是sun公司内部高手所做,设计精巧,代码简练。实现一个handler,用sax的方式解析xml内容,handler内部用反射和javabean的机制构造RSS元素对象并赋值。
   
3rsslib4j: http://sourceforge.net/projects/rsslib4j
 rsslib4j
是 sourceforget 上的项目,同样支持所有RSS版本。
   
4:rsslibj:http://enigmastation.com/rsslibj/
   
5:总结
 Rome:
 优 -
1)可扩展性好,有前途。2)功能强大,除了用来解析RSS,还可以聚合和构造RSS。
 劣 -
1)兼容性待加强,2)绑定jdom。
 rssutils:
 优 - 1)代码设计精妙,值得学习。2)附带
taglib 实现,直接可在 jsp 中应用。
 劣 - 1)没有源码。 2)兼容性有待加强。
3)功能较弱,只能用来解析RSS,没有聚合和构造RSS功能。
 rsslib4j:
 优 -
1)简单有效,体积小。2)兼容性不错。
 劣 -
1)有小bug。2)功能较弱,只能用来解析RSS,没有聚合和构造RSS功能。
 rsslibj:
 优 -
1)简单有效,体积小,才25K。2)能解析和生成RSS(动态和静态)
 劣 -
1)有小bug。2)版本很久没有更新了,陈旧.

五:选择ROME作为RSS实现工具
 在官网http://wiki.java.net/bin/view/Javawsxml/Rome下载rome-0.8.jar,
 rome用到了jdom1.0,下载地址:http://www.jdom.org
 rome支持:rss_0.9

   rss_0.91
   rss_0.92
  
rss_0.93
   rss_0.94
   rss_1.0

   rss_2.0
   atom_0.3
  
atom_1.0

 生成RSS类新需要在程序中指定,如:rss_2.0
六:包结构
 com.sun.syndication.feed 提供RSS
and Atom beans的父类
 com.sun.syndication.feed.atom 提供实现Atom
feeds核心元素的beans
 com.sun.syndication.feed.module
提供处理聚合modules的beans
 com.sun.syndication.feed.rss 提供实现Rss
feeds核心元素的beans
 com.sun.syndication.feed.synd 我们主要用的就是这个包,SyndFeed
and SyndEntryImpl

 com.sun.syndication.io  提供对读取和分析feeds的输入和输出
七:实例:

1:读取远端url的rss,然后输出到控制台:
/**
 * 关键代码:
 *
SyndFeedInput input = new SyndFeedInput();
 * SyndFeed feed =
input.build(new XmlReader(feedUrl));
 */

package com.sun.syndication.samples;

import com.sun.syndication.feed.synd.SyndFeed;
import
com.sun.syndication.io.SyndFeedInput;
import
com.sun.syndication.io.XmlReader;
import java.net.URL;

/**
 * It Reads and prints any RSS/Atom feed
type.
 */
public class FeedReader {

public static void main(String[] args)
{
        boolean ok =
false;
        if (args.length==0)
{
           
try
{
               
URL feedUrl = new URL("http://seu.org.cn/bbs/rss.php");
  //SyndFeedInput:从远程读到xml结构的内容转成SyndFeedImpl实例
               
SyndFeedInput input = new
SyndFeedInput();
  //rome按SyndFeed类型生成rss和atom的实例,
  //SyndFeed是rss和atom实现类SyndFeedImpl的接口
               
SyndFeed feed = input.build(new
XmlReader(feedUrl));
  //打印到控制台
               
System.out.println(feed);
               
ok =
true;
           
}
           
catch (Exception ex)
{
               
ex.printStackTrace();
               
System.out.println("ERROR:
"+ex.getMessage());
           
}
        }

if (!ok)
{
           
System.out.println();
           
System.out.println("FeedReader reads and prints any RSS/Atom feed
type.");
           
System.out.println("The first parameter must be the URL of the feed to
read.");
           
System.out.println();
       
}
    }
}
2:将多个远程RSS在本地聚集成一个RSS
package
com.sun.syndication.samples;

import java.net.URL;
import java.io.InputStreamReader;
import
java.io.PrintWriter;
import java.util.List;
import
java.util.ArrayList;

import com.sun.syndication.feed.synd.SyndFeed;
import
com.sun.syndication.feed.synd.SyndFeedImpl;
import
com.sun.syndication.io.SyndFeedOutput;
import
com.sun.syndication.io.SyndFeedInput;
import
com.sun.syndication.io.XmlReader;

/**
 * It aggregates a list of RSS/Atom feeds (they can be of
different types)
 * into a single feed of the specified
type.
 * <p>
 * @author Alejandro
Abdelnur
 *
 */
public class FeedAggregator {

public static void main(String[] args)
{
        boolean ok =
false;
        if
(args.length>=2)
{
           
try
{
               
String outputType = args[0];

SyndFeed feed = new
SyndFeedImpl();
               
feed.setFeedType(outputType);

feed.setTitle("Aggregated
Feed");
               
feed.setDescription("Anonymous Aggregated
Feed");
               
feed.setAuthor("anonymous");
               
feed.setLink("http://www.anonymous.com");

List entries = new
ArrayList();
               
feed.setEntries(entries);

for (int i=1;i<args.length;i++)
{
                   
URL inputUrl = new URL(args[i]);

SyndFeedInput input = new
SyndFeedInput();
                   
SyndFeed inFeed = input.build(new XmlReader(inputUrl));

entries.addAll(inFeed.getEntries());

&nbp;        
}

SyndFeedOutput output = new
SyndFeedOutput();
               
output.output(feed,new PrintWriter(System.out));

ok =
true;
           
}
           
catch (Exception ex)
{
               
System.out.println("ERROR:
"+ex.getMessage());
           
}
        }

if (!ok)
{
           
System.out.println();
           
System.out.println("FeedAggregator aggregates different feeds into a
single
one.");
           
System.out.println("The first parameter must be the feed type for the
aggregated
feed.");
           
System.out.println(" [valid values are: rss_0.9, rss_0.91U, rss_0.91N,
rss_0.92, rss_0.93,
]");
           
System.out.println("
[                 
rss_0.94, rss_1.0, rss_2.0 & atom_0.3 
]");
           
System.out.println("The second to last parameters are the URLs of feeds to
aggregate.");
           
System.out.println();
       
}
    }

}
3:将动态生成的RSS存盘,形成静态RSS
package
com.sun.syndication.samples;

import com.sun.syndication.feed.synd.*;
import
com.sun.syndication.io.SyndFeedOutput;

import java.io.FileWriter;
import java.io.Writer;
import
java.text.DateFormat;
import java.text.SimpleDateFormat;
import
java.util.ArrayList;
import java.util.List;

/**
 * It creates a feed and writes it to a file.
 *
<p>
 * @author Alejandro
Abdelnur
 *
 */
public class FeedWriter {

private static final String DATE_FORMAT =
"yyyy-MM-dd";

public static void main(String[] args)
{
        boolean ok =
false;
        if (args.length==0)
{
           
try
{
               
String feedType =
"rss_2.0";//指定rss类型
               
String fileName = "F:\\ss.xml";//静态rss存放目录

DateFormat dateParser = new SimpleDateFormat(DATE_FORMAT);

//feed是通过SyndFeedImpl的实例 
               
SyndFeed feed = new
SyndFeedImpl();
               
feed.setFeedType(feedType);

feed.setTitle("Sample Feed (created with
Rome)");
               
feed.setLink("http://rome.dev.java.net");
               
feed.setDescription("This feed has been created using Rome (Java
syndication
utilities");
  
  //entries就是item集合
               
List entries = new
ArrayList();
  //一个entry就是一个item
               
SyndEntry
entry;
               
SyndContent
description;
  
  //第一个item
               
entry = new
SyndEntryImpl();
               
entry.setTitle("Rome
v1.0");
               
entry.setLink("http://wiki.java.net/bin/view/Javawsxml/Rome01");
               
entry.setPublishedDate(dateParser.parse("2004-06-08"));
               
description = new
SyndContentImpl();
               
description.setType("text/plain");
               
description.setValue("Initial release of
Rome");
               
entry.setDescription(description);
               
entries.add(entry);

//第二个item
               
entry = new
SyndEntryImpl();
               
entry.setTitle("Rome
v2.0");
               
entry.setLink("http://wiki.java.net/bin/view/Javawsxml/Rome02");
               
entry.setPublishedDate(dateParser.parse("2004-06-16"));
               
description = new
SyndContentImpl();
               
description.setType("text/xml");
               
description.setValue("Bug fixes, <xml>XML</xml> minor API
changes and some new
features");
               
entry.setDescription(description);
               
entries.add(entry);

//第三个item
               
entry = new
SyndEntryImpl();
               
entry.setTitle("Rome
v3.0");
               
entry.setLink("htp://wiki.java.net/bin/view/Javawsxml/Rome03");
               
entry.setPublishedDate(dateParser.parse("2004-07-27"));
               
description = new
SyndContentImpl();
               
description.setType("text/html");
               
description.setValue("<p>More Bug fixes, mor API changes, some new
features and some Unit
testing</p>"+
                                    
"<p>For details check the <a href=\"Changes">http://wiki.java.net/bin/view/Javawsxml/RomeChangesLog#RomeV03\">Changes
Log</a></p>");
               
entry.setDescription(description);
  
  //将所有item存入entries
               
entries.add(entry);
  
  //将entries加入channel
               
feed.setEntries(entries);

Writer writer = new
FileWriter(fileName);
               
SyndFeedOutput output = new
SyndFeedOutput();
  //存盘,形成静态rss
               
output.output(feed,writer);
               
writer.close();

System.out.println("The feed has been written to the file
["+fileName+"]");
               
System.out.println(feed);

ok =
true;
           
}
           
catch (Exception ex)
{
               
ex.printStackTrace();
               
System.out.println("ERROR:
"+ex.getMessage());
           
}
        }

if (!ok)
{
           
System.out.println();
           
System.out.println("FeedWriter creates a RSS/Atom feed and writes it to a
file.");
           
System.out.println("The first parameter must be the syndication format for
the
feed");
           
System.out.println("  (rss_0.90, rss_0.91, rss_0.92, rss_0.93,
rss_0.94, rss_1.0 rss_2.0 or
atom_0.3)");
           
System.out.println("The second parameter must be the file name for the
feed");
           
System.out.println();
       
}
    }

}

4:动态生成rss,给一个blog站点动态生成rss
package com.vaga.rss.web.admin;

import java.io.IOException;
import java.text.DateFormat;
import
java.text.ParseException;
import java.text.SimpleDateFormat;
import
java.util.ArrayList;
import java.util.Iterator;
import
java.util.List;

import javax.servlet.http.HttpServletRequest;
import
javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.ModelAndView;
import
org.springframework.web.servlet.mvc.ParameterizableViewController;

import com.sun.syndication.feed.synd.SyndContent;
import
com.sun.syndication.feed.synd.SyndContentImpl;
import
com.sun.syndication.feed.synd.SyndEntry;
import
com.sun.syndication.feed.synd.SyndEntryImpl;
import
com.sun.syndication.feed.synd.SyndFeed;
import
com.sun.syndication.feed.synd.SyndFeedImpl;
import
com.sun.syndication.io.FeedException;
import
com.sun.syndication.io.SyndFeedOutput;
import
com.sun.syndication.feed.synd.SyndContent;
import
com.sun.syndication.feed.synd.SyndEntry;
import
com.totsp.xml.syndication.content.ContentModule;
import
com.vaga.blog.model.WeblogEntry;
import
com.vaga.blog.model.Website;
import
com.vaga.blog.service.WeblogEntryManager;
import
com.vaga.blog.service.WebsiteManager;

public class SiteRssViewController  extends
ParameterizableViewController {
 // Constants
  /**
Namespace URI for content:encoded elements */
   private
static final String CONTENT_NS ="http://purl.org/rss/1.0/modules/content/";
  
private static final String FEED_TYPE = "type";
   private
static final String MIME_TYPE = "application/xml;
charset=UTF-8";
   private static final String
COULD_NOT_GENERATE_FEED_ERROR = "Could not generate feed";
  
private static final String _defaultFeedType="rss_2.0";
  
private static final String DATE_FORMAT = "yyyy-MM-dd";
  
//controller starts
   private WeblogEntryManager
weblogEntryManager;//spring依赖注入
   private WebsiteManager
websiteManager; //spring依赖注入
 //spring依赖注入
  
public void setWeblogEntryManager(WeblogEntryManager weblogEntryManager)
{
  this.weblogEntryManager =
weblogEntryManager;
  
}
 //spring依赖注入
   public void
setWebsiteManager(WebsiteManager websiteManager)
{
  this.websiteManager = websiteManager;
  
}
 
 protected ModelAndView
handleRequestInternal(HttpServletRequest request,HttpServletResponse
response) throws Exception {
 try
{
           SyndFeed
feed =
getFeed(request);
          
String feedType =
request.getParameter(FEED_TYPE);//null
          
feedType = (feedType!=null) ? feedType :
_defaultFeedType;
          
feed.setFeedType(feedType);//rss_2.0
          
response.setContentType(MIME_TYPE);
          
SyndFeedOutput output = new
SyndFeedOutput();
          
output.output(feed,response.getWriter());//向发出请求的用户输出该RSS(xml格式)
      
}
       catch (FedException ex)
{
           String
msg =
COULD_NOT_GENERATE_FEED_ERROR;
          
log(msg,ex);
          
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,msg);
      
}
  return null;
 }

/**
    *
请求的类型如下:
    *
siteRss.htm?websiteId=21   |ID=66的个人站点最新20条文章
   
*
siteRss.htm?websiteId=21&entryType=hot |ID=66的个人站点最热20条文章
   
*
    * @param request
   
*/
    protected SyndFeed getFeed(HttpServletRequest
request) throws IOException,FeedException
{
       DateFormat dateParser = new
SimpleDateFormat(DATE_FORMAT);
      
//feed就是channel
       SyndFeed feed =
new SyndFeedImpl();
      
//item集合
       List entries = new
ArrayList();
      
//一个entry就是代表一个item
       SyndEntry
entry;
       SyndContent
description;
      
setFeed(request,feed);
       Iterator
iterator =
setIterator(request);
  //将文章的20记录转成20个item
          
while(iterator.hasNext()){
          
 entry = new
SyndEntryImpl();
          
 WeblogEntry weblogEntry =
(WeblogEntry)iterator.next();
          
 entry.setTitle(weblogEntry.getTitle());
          
 entry.setLink(feed.getLink()+"?weblogEntryId="+weblogEntry.getId());
          
 try
{
          
  entry.setPublishedDate(dateParser.parse(weblogEntry.getPubTime().toString()));
          
 }
          
 catch (ParseException ex)
{
          
  ex.printStackTrace();
          
 }
          
 //该item的description
          
 description = new
SyndContentImpl();
          
 description.setType("text/plain");
          
 String
text=null;
          
 if(weblogEntry.getText().length()>500){
          
  text = weblogEntry.getText().substring(0,
500);
          
 }else{
          
  text =
weblogEntry.getText();
          
 }
          
 description.setValue(text);
          
 entry.setDescription(description);
          
 addFooter(entry);
          
 entries.add(entry);
          
}

//将所有的item存入channel
      
feed.setEntries(entries);
       return
feed;
   }
 private SyndFeed
setFeed(HttpServletRequest request,SyndFeed feed){
   
//blog中的website  
    Website website =
websiteManager.getWebsite(request.getParameter("websiteId"));
   
设置当前website的channel属性
   
feed.setTitle(website.getName());
   
feed.setAuthor(website.getCreator());
   
feed.setCopyright(website.getEmailAddress());
   
feed.setLink("http://wxz.vaga.com.cn:8080/blog/weblog/"+website.getHandle());
   
feed.setDescription(website.getDescription());
      
return feed;  
 }

//从数据库中获得20条该website的文章
 private Iterator
setIterator(HttpServletRequest
request){
  if(request.getParameter("entryType")==null){
   return
weblogEntryManager.getRecentWeblogEntriesForRss(request.getParameter("websiteId"),
null, "PUBLISHED",
21).iterator();
  }else{
   return
weblogEntryManager.getHotWeblogEntriesForRss(request.getParameter("websiteId"),
null, 21).iterator();
  }
 }

/**
     * Add footer
to an entry.给每个文章摘要添加页脚
     * @param
entry
     */
    public static
void addFooter(SyndEntry entry)
   
{
        // Prep variables used in
loops
        String title =
entry.getTitle();
        String
link = entry.getLink();

// Use the add-on
ContentModule to handle
        //
<content:encoded/> elments within the
feed
        ContentModule module
=((ContentModule) entry.getModule(CONTENT_NS));

// If content:encoded is
found, use that.
       
if(module!=null)
       
{
            //
Container for footer-appended HTML
strings
           
List newStringList = new ArrayList();

//
Iterate through encoded HTML, creating
footers
           
Iterator oldStringIter
=module.getEncodeds().iterator();
           
while
(oldStringIter.hasNext())
           
{
               
String original = (String)
oldStringIter.next();
               
newStringList.add(createFooter(original,link,
title));
           
}

//
Set new encoded HTML strings on
entry
           
module.setEncodeds(newStringList);
       
}
       
else
       
{
            //
Fall back to adding footer in
<description/>
           
// This results in escaped HTML.  Ugly, but
common.
         //Target the
description node
       
 SyndContent content =
entry.getDescription();
           
// Create and set a footer-appended
description
           
String original =
content.getValue();
           
content.setValue(createFooter(original,link,
title));
           

        }
   
}

/**
     * Create a feed
item footer of immediate actions
     * by using
information from the feed item itself
     * @param
original  The original text of the feed
item
     * @param
link      The link for the feed
item
     * @param title    
The title of the feed item
     *
@return
     */
    private
static String createFooter(String original, String link,String
title)
    { 
     // Use
StringBuffer to create a sb
     StringBuffer
sb;
     if(original==null){
   
  sb=new StringBuffer("<br />");
   
 }else{
      sb= new
StringBuffer(original);
   
 }              

        sb.append("\n\n<div
class=‘feedwarmer‘><hr/>");
       
sb.append("<i>相关操作:</i> ");

// Add email link using
title and item link
       
sb.append("<a href=‘mailto:?body=Check this out:
");
       
sb.append(link).append("‘>推荐该链接</a> | ");

// Add delicious link
using item title link
       
sb.append("<a
href=‘http://del.icio.us/post/?url=");
       
sb.append(link).append("&title=").append(title);
       
sb.append("‘>添加到delicious</a> | ");

// Add Google Blogs Search
link using item title
       
sb.append("<a
href=‘http://blogsearch.google.com/");
       
sb.append("blogsearch?hl=en&q=").append(title);
       
sb.append("‘>搜索相关内容</a>");

// Finish and return the
sb
       
sb.append("</div>\n");
       
return sb.toString();
    }
}

JAVA的RSS处理

时间: 2024-07-30 16:01:03

JAVA的RSS处理的相关文章

java使用Rome解析Rss的实例(转)

Rome简介 Rome是为RSS聚合而开发的开源包,它可以支持0.91.0.92.0.93.0.94.1.0.2.0,可以说rss的版本基本上都支持了. Rss简介 RSS是站点用来和其他站点之间共享内容的一种简易方式(也叫聚合内容),通常被用于新闻和其他按顺序排列的网站,例如Blog.RSS就是一种用来分发和汇集网页内容的XML格式!RSS =Really Simple Syndication(真正简单的聚合 )或Rich Site Summary(丰富站点摘要 )Rss目前已经被广泛的应用

Android(java)学习笔记206:利用开源SmartImageView优化网易新闻RSS客户端

1.我们自己编写的SmartImageView会有很多漏洞,但是我们幸运的可以在网上利用开源项目的,开源项目中有很多成熟的代码,比如SmartImageView都编写的很成熟的 国内我们经常用到https://github.com/  或者 http://code.google.org/ (但是google在中国屏蔽很厉害),暂时我们可以使用http://code.taobao.org(淘宝开源项目) 2.我们登录 https://github.com/  :搜索 smart image vie

Java开发中的23种设计模式详解(转)

设计模式(Design Patterns) --可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了可重用代码.让代码更容易被他人理解.保证代码可靠性. 毫无疑问,设计模式于己于他人于系统都是多赢的,设计模式使代码编制真正工程化,设计模式是软件工程的基石,如同大厦的一块块砖石一样.项目中合理的运用设计模式可以完美的解决很多问题,每种模式在现在中都有相应的原理来与之对应,每一个模式描述了一个在我们周

五年磨一剑:Java 开源博客 Solo 1.0.0 发布了!

从 Solo 第一个版本发布至今,已经过去 5 年了.今天我们非常自豪地宣布,Solo 1.0.0 正式发布,感谢一直以来关注 B3log 开源的朋友! 目前 B3log 开源有三款产品: GitHub 上 Star 数最多的 Java 博客 Solo Golang 黑科技之在线 IDE Wide 基于实时交互技术的社区 Sym 特性 基于标签的文章分类 博客/标签 Atom/RSS.Sitemap 输出 评论回复及邮件提醒 自定义页面.导航 多编辑器:Markdown.TinyMCE.Kind

0. Java开发中的23种设计模式详解(转)

设计模式(Design Patterns) ——可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了可重用代码.让代码更容易被他人理解.保证代码可靠性. 毫无疑问,设计模式于己于他人于系统都是多赢的,设计模式使代码编制真正工程化,设计模式是软件工程的基石,如同大厦的一块块砖石一样.项目中合理的运用设计模式可以完美的解决很多问题,每种模式在现在中都有相应的原理来与之对应,每一个模式描述了一个在我们周

Java设计模式详尽资料

设计模式(Design Patterns) ——可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了可重用代码.让代码更容易被他人理解.保证代码可靠性. 毫无疑问,设计模式于己于他人于系统都是多赢的,设计模式使代码编制真正工程化,设计模式是软件工程的基石,如同大厦的一块块砖石一样.项目中合理的运用设计模式可以完美的解决很多问题,每种模式在现在中都有相应的原理来与之对应,每一个模式描述了一个在我们周

Jsoup简介——使用Java抓取网页数据

概述 jsoup 是一款Java 的HTML解析器,可直接解析某个URL地址.HTML文本内容.它提供了一套非常省力的API,可通过DOM,CSS以及类似于jQuery的操作方法来取出和操作数据.jsoup的主要功能如下: 1. 从一个URL,文件或字符串中解析HTML: 2. 使用DOM或CSS选择器来查找.取出数据: 3. 可操作HTML元素.属性.文本: jsoup是基于MIT协议发布的,可放心使用于商业项目. 关于Jsoul的更多介绍,请访问Jsoul的官网:http://jsoup.o

死磕内存篇2 --JAVA进程是怎么突然挂掉的

JVM内存不足导致进程死掉. Native memory allocation (mmap) failed to map 一台服务器上部署很多JAVA进程已经是微服务的常态,但也有些坑. 背景,测试服务器上的一些JAVA进程突然挂掉,查看call back的日志发现如下: # There is insufficient memory for the Java Runtime Environment to continue. # Native memory allocation (mmap) fa

(转)Java经典设计模式(3):十一种行为型模式(附实例和详解)

原文出处: 小宝鸽 Java经典设计模式共有21中,分为三大类:创建型模式(5种).结构型模式(7种)和行为型模式(11种). 本文主要讲行为型模式,创建型模式和结构型模式可以看博主的另外两篇文章:Java经典设计模式之五大创建型模式(附实例和详解).Java经典设计模式之七大结构型模式(附实例和详解). 行为型模式细分为如下11种:策略模式.模板方法模式.观察者模式.迭代子模式.责任链模式.命令模式.备忘录模式.状态模式.访问者模式.中介者模式.解释器模式. 接下来对11种行为型模式逐个进行介