RSS结构

来源:互联网 发布:linux监视局域网流量 编辑:程序博客网 时间:2024/05/17 06:09

RSS(也叫聚合内容,Really Simple Syndication)现在用的已经很广啦,最初的RSS要追溯到1995,Ramanathan V. Guha和其他在苹果电脑公司的高级技术组开发了一个测试的内容框架。更多有关RSS的资料可查看这里,下面我们来为我们的JSP网站生成RSS
首先我们来看看最基本的RSS结构:
 
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<rss version="2.0" xmlns:dc="
http://purl.org/dc/elements/1.1/"  
xmlns:trackback="
http://madskills.com/public/xml/rss/module/trackback/"  
xmlns:wfw="
http://wellformedweb.org/CommentAPI/"  
xmlns:slash="
http://purl.org/rss/1.0/modules/slash/">
</rss>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><rss version="2.0" xmlns:dc="
http://purl.org/dc/elements/1.1/"  xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/"  xmlns:wfw="http://wellformedweb.org/CommentAPI/"  xmlns:slash="http://purl.org/rss/1.0/modules/slash/"></rss>
其实就是一个XML文件!在<rss></rss>之间我们可以自由配置自己要发布的RSS的格式。例如此次我们要发布的RSS是这样的:
 
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<rss version="2.0" xmlns:dc="
http://purl.org/dc/elements/1.1/" x
mlns:trackback="
http://madskills.com/public/xml/rss/module/trackback/
xmlns:wfw="
http://wellformedweb.org/CommentAPI/" x
mlns:slash="
http://purl.org/rss/1.0/modules/slash/">
<channel>
<item>
<title>JSP
网站RSS的实现</title>
<author>neeke</author>
<pubDate>2008-10-04</pubDate>
<description>
这是来自尼克技术博客博客的
RSS</description>
<category>J2EE
技术
</category>
</item>
</channel>
</rss>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><rss version="2.0" xmlns:dc="
http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><item><title>JSP
网站RSS的实现</title><author>neeke</author><pubDate>2008-10-04</pubDate><description>这是来自尼克技术博客博客的RSS</description><category>J2EE技术</category></item></channel></rss>
 
了解了它的结构实现起来就容易了。我们创建IO流,并从数据库中获取到我们要发布的RSS资源的集合,然后按照它的格式与结构一行一行的写入到一个RSS.XML文件中即可。

 
public static void publishRss(String rssPath)
    {
        //
获得要发布的RSS数据集合
        ArrayList rssArticle = ArticleManager.getArticlesAll();
        try {
            //
创建输入输出流

            FileWriter fw = new FileWriter(rssPath);
            BufferedWriter bw = new BufferedWriter(fw);
            //
开始按照格式写入数据

            bw.write(
                    "<?xml version=/"1.0/" encoding=/"UTF-8/" standalone=/"yes/"?>/r/n");
            bw.write("<?xml-stylesheet type=/"text/xsl/" href=/"CSS/rss.xslt/"?>");
            bw.write("<rss version=/"2.0/" xmlns:dc=/"
http://purl.org/dc/elements/1.1//" xmlns:trackback=/"http://madskills.com/public/xml/rss/module/trackback//" xmlns:wfw=/"http://wellformedweb.org/CommentAPI//" xmlns:slash=/"http://purl.org/rss/1.0/modules/slash//">/r/n");
            bw.write("<channel>/r/n");
            for (int i = 0; i < rssArticle.size(); i++) {
                ArticleBean article = (ArticleBean) rssArticle.get(i);
                bw.write("<item>/r/n");
                bw.write("<title>" + article.getTitle() + "</title>/r/n");
                bw.write("<author>" + article.getAuthorId() + "</author>/r/n");
                bw.write("<pubDate>" + article.getPostTime() + "</pubDate>/r/n");
                bw.write("<description>" + article.getIntro() +
                         "</description>/r/n");
                bw.write("<category>" + article.getCateId() + "</category>/r/n");
                bw.write("</item>/r/n");
            }
            bw.write("</channel>/r/n");
            bw.write("</rss>");
            //
关闭流,RSS发布完毕。
            bw.close();
            fw.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
public static void publishRss(String rssPath)    {        //
获得要发布的RSS数据集合        ArrayList rssArticle = ArticleManager.getArticlesAll();        try {            //创建输入输出流            FileWriter fw = new FileWriter(rssPath);            BufferedWriter bw = new BufferedWriter(fw);            //开始按照格式写入数据            bw.write(                    "<?xml version=/"1.0/" encoding=/"UTF-8/" standalone=/"yes/"?>/r/n");            bw.write("<?xml-stylesheet type=/"text/xsl/" href=/"CSS/rss.xslt/"?>");            bw.write("<rss version=/"2.0/" xmlns:dc=/"http://purl.org/dc/elements/1.1//" xmlns:trackback=/"http://madskills.com/public/xml/rss/module/trackback//" xmlns:wfw=/"http://wellformedweb.org/CommentAPI//" xmlns:slash=/"http://purl.org/rss/1.0/modules/slash//">/r/n");            bw.write("<channel>/r/n");            for (int i = 0; i < rssArticle.size(); i++) {                ArticleBean article = (ArticleBean) rssArticle.get(i);                bw.write("<item>/r/n");                bw.write("<title>" + article.getTitle() + "</title>/r/n");                bw.write("<author>" + article.getAuthorId() + "</author>/r/n");                bw.write("<pubDate>" + article.getPostTime() + "</pubDate>/r/n");                bw.write("<description>" + article.getIntro() +                         "</description>/r/n");                bw.write("<category>" + article.getCateId() + "</category>/r/n");                bw.write("</item>/r/n");            }            bw.write("</channel>/r/n");            bw.write("</rss>");            //关闭流,RSS发布完毕。
            bw.close();            fw.close();        } catch (IOException ex) {            ex.printStackTrace();        }    }
发布完毕,经过我的测试打开后会提示出错,用记事本打开生成的源文件,然而我们的RSS文件是一点问题都没有的哇,怎么可能呢?接着又用JBuilder打开这个XML文件,晕倒~汉字全是乱码,立刻意识到问题出在了哪里了。在哪呢?其实就是文件的编码问题!将原先

bw.write("<?xml version=/"1.0/" encoding=/"UTF-8/" standalone=/"yes/"?>/r/n");
该行代码中的UTF-8改为GBK,重新跑一次程序,一切OK

I implement this RSS feed generator using Regular Expression, this is really a handy tool to work with. you can specify max amount of feed items, all newly added feed items will be inserted right into the place where the previous first feed item sits, and all this is done with only TWO methods invocation. You just create an RSSEntryFeed object, and pass it as a parameter to the createRSSFeedItem(RSSFeedEntry feedEntry) method to create an XML representation(just a String) of the object, and invoke the addRSSFeedItem(String strFeedItem, int limit) method, and you have your newly created blog entry added to your RSS feed...

package cn.com.kevintse.rss;

/**
* @author Kevin Tse
* @version 0.1
*/
public class RSSFeedEntry {
    private String title;
    private String description;
    private String link;
    private String author;
    private String guid;
    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
    public String getDescription() {
        return description;
    }
    public void setDescription(String description) {
        this.description = description;
    }
    public String getLink() {
        return link;
    }
    public void setLink(String link) {
        this.link = link;
    }
    public String getAuthor() {
        return author;
    }
    public void setAuthor(String author) {
        this.author = author;
    }
    public String getGuid() {
        return guid;
    }
    public void setGuid(String guid) {
        this.guid = guid;
    }
}

package cn.com.kevintse.rss;

import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
* @author Kevin Tse
* @version 0.1
*/
public class RSSFeedGenerator {
    char n = '/n';
    char tab = '/t';
   
    public void createRSSFeedFile()throws Exception {
        File file = new File("feed.rss");
        FileOutputStream fos = new FileOutputStream(file);
        PrintStream ps = new PrintStream(fos, false, "UTF-8");
        StringBuffer sb = new StringBuffer();
        sb.append("<?xml version=/"1.0/" encoding=/"UTF-8/"?>").append(n);
        sb.append("<rss version=/"2.0/">").append(n);
        sb.append(tab).append("<channel>").append(n);
        sb.append(tab).append(tab).append("<title>Energetic Mind</title>").append(n);
        sb.append(tab).append(tab).append("<link>http://kevintse.com.cn</link>").append(n);
        sb.append(tab).append(tab).append("<description><![CDATA[Kevin Tse's blog]]></description>").append(n);
        sb.append(tab).append(tab).append("<pubDate>Thu, 18 Dec 2008 01:44:08 +0800</pubDate>").append(n);
        sb.append(tab).append(tab).append("<language>en</language>").append(n);
        sb.append(tab).append(tab).append("<copyright>Copyright 2008, Kevin Tse</copyright>").append(n);
        sb.append(tab).append("</channel>").append(n);
        sb.append("</rss>");
       
        ps.print(sb.toString());
        ps.close();
    }

    public void addRSSFeedItem(String strFeedItem, int limit)throws Exception {
        File file = new File("feed.rss");
        if(!file.exists()) createRSSFeedFile();
       
        FileInputStream fis = new FileInputStream(file);
        BufferedReader br = new BufferedReader(new InputStreamReader(fis, "UTF-8"));
        StringBuffer sb = new StringBuffer();
        String temp = null;
        while((temp = br.readLine()) != null) {
            sb.append(temp).append(n);
        }
        String fileContent = sb.toString();
        String newFileContent = "";
       
        Pattern pattern = Pattern.compile("//t*+<item>.*?</item>", Pattern.DOTALL);
        Matcher matcher = pattern.matcher(fileContent);
        if(matcher.find()) {
            newFileContent = matcher.replaceFirst(strFeedItem + matcher.group());
        }else {
            matcher.usePattern(Pattern.compile("//t*+</channel>"));
            matcher.reset(fileContent);
            newFileContent = matcher.replaceFirst(strFeedItem + matcher.group());
        }
       
        matcher.usePattern(Pattern.compile("//t*+<item>.*?</item>//n", Pattern.DOTALL));
        matcher.reset(newFileContent);
        int itemCount = 0;
        StringBuffer items = new StringBuffer();
        while(matcher.find())
            if(++itemCount <= limit)
                items.append(matcher.group());
       
        matcher.usePattern(Pattern.compile("//t*+<item>.*</item>//n", Pattern.DOTALL));
        newFileContent = matcher.replaceFirst(items.toString());
       
       
        matcher.usePattern(Pattern.compile("<pubDate>(.*)?</pubDate>"));
        matcher.reset(newFileContent);
       
        //update pubDate of last feed
        Calendar cal = new GregorianCalendar();
        Date pubDate = cal.getTime();
        SimpleDateFormat dateFormat = new SimpleDateFormat("EEE', 'dd' 'MMM' 'yyyy' 'HH:mm:ss' 'Z", Locale.US);
        newFileContent = matcher.replaceFirst("<pubDate>" + dateFormat.format(pubDate) + "</pubDate>");
       
        //regenerate the feed.rss file
        FileOutputStream fos = new FileOutputStream(file);
        PrintStream ps = new PrintStream(fos, false, "UTF-8");
        ps.print(newFileContent);
        ps.close();
    }
   
    public String createRSSFeedItem(RSSFeedEntry feedEntry) {
        StringBuffer sb = new StringBuffer();
        sb.append(tab).append(tab).append("<item>").append(n);
        sb.append(tab).append(tab).append(tab).append("<title><![CDATA[").append(feedEntry.getTitle()).append("]]></title>").append(n);
        sb.append(tab).append(tab).append(tab).append("<description><![CDATA[").append(feedEntry.getDescription()).append("]]></description>").append(n);
        sb.append(tab).append(tab).append(tab).append("<link><![CDATA[").append(feedEntry.getLink()).append("]]></link>").append(n);
        sb.append(tab).append(tab).append(tab).append("<author><![CDATA[").append(feedEntry.getAuthor()).append("]]></author>").append(n);
        sb.append(tab).append(tab).append(tab).append("<guid>").append(feedEntry.getGuid()).append("</guid>").append(n);
        sb.append(tab).append(tab).append("</item>").append(n);

        return sb.toString();
    }
}

package cn.com.kevintse.rss;

public class Test {
    public static void main(String[] args) throws Exception{
        RSSFeedGenerator g = new RSSFeedGenerator();
        RSSFeedEntry rssFeedEntry = new RSSFeedEntry();
        rssFeedEntry.setTitle("this is a test");
        rssFeedEntry.setDescription("this is description.");
        rssFeedEntry.setAuthor("Kevin Tse (kevintse.onjee@gmail.com)");
        rssFeedEntry.setGuid("http://url.of.your.blog.entry/");
        rssFeedEntry.setLink("http://url.of.your.blog.entry/");
        g.addRSSFeedItem(g.createRSSFeedItem(rssFeedEntry), 10);
    }
}

RSS是一个标准的XML文件,Rss阅读器可以读取这个XML文件获得文章的信息,使用户可以通过Rss阅读器

而非浏览器阅读Blog,我们只要动态生成这个XML文件便可以了。RSSLibJ是一个专门读取和生成RSS的小

巧实用的Java库,大小仅25k,可以从http://sourceforge.net/projects/rsslibj/下载rsslibj-

1_0RC2.jar和它需要的EXMLjar两个文件,然后复制到web/WEB-INF/lib/下。

 

rsslibj-1_0RC2.jar下载地址:http://sourceforge.net/project/downloading.php?group_id=71153&use_mirror=nchc&filename=rsslibj-1_0RC2.jar&27763931

 

EXML.jar下载地址:http://rsslibj.cvs.sourceforge.net/rsslibj/rsslibj/lib/EXML.jar?view=log

 

下载下来之后把 扩张名.zip 改为 .jar 就行了。

import com.rsslibj.elements.Channel;public class Writer { public static void main(String[] args) throws InstantiationException, ClassNotFoundException, IllegalAccessException { Channel channel=new Channel(); channel.setDescription("This is my sample channel."); channel.setLink("http://localhost/"); channel.setTitle("My Channel"); channel.setImage("http://localhost/", "The Channel Image", "http://localhost/foo.jpg"); channel.setTextInput("http://localhost/search", "Search The Channel Image", "The Channel Image", "s"); channel.addItem("http://localhost/item1", "The First Item covers details on the first item>", "The First Item") .setDcContributor("Joseph B. Ottinger"); channel.addItem("http://localhost/item2", "The Second Item covers details on the second item", "The Second Item") .setDcCreator("Jason Bell"); System.out.println("The feed in RDF: "+channel.getFeed("rss")); }}

 

 

Channel channel = new Channel();

channel.setDescription(account.getDescription());

baseUrl = baseUrl.substring(0, n);

channel.setLink("http://server-name/home.c?accountId=" + accountId);

channel.setTitle(account.getTitle());

List articles = facade.getArticles(accountId, account.getMaxPerPage(), 1);

Iterator it = articles.iterator();

while(it.hasNext()) {

    Article article = (Article)it.next();

    channel.addItem("http://server-name/article.c?articleId=" + article.getArticleId(),

        article.getSummary(), article.getTitle()

    );

}

// 输出xml:

response.setContentType("text/xml");

PrintWriter pw = response.getWriter();

pw.print(channel.getFeed("rss"));

pw.close();

 

 

  importcom.rsslibj.elements.Channel;

  

  publicclassWriter{

  publicstaticvoidmain(String[]args)

  throwsInstantiationException,ClassNotFoundException,

  IllegalAccessException{

  Channelchannel=newChannel();

  channel.setDescription("Thisismysamplechannel.");

  channel.setLink("/");

 

实现rss

http://wzx20032003.cublog.cn

2006.12.8

:什么是RSS
 RSS(really simple syndication) :
网页内容聚合器。RSS的格式是XML。必须符合XML 1.0规范。
 RSS
的作用:订阅BLOG,订阅新闻
:RSS的历史版本:
 http://blogs.law.harvard.edu/tech/rssVersionHistory
 RSS
的版本有很多个,0.900.910.920.930.941.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>
:表示该频道的 GIFJPEG 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>
dan@spam_me.com (Dan Deletekey)
 <webMaster>
dan@spam_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>
:这是该项的 URLtitle 通常作为一个链接,指向包含在 <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元素对象并赋值。
    3:rsslib4j: 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)有小bug2)功能较弱,只能用来解析RSS,没有聚合和构造RSS功能。
 rsslibj:
 
- 1)简单有效,体积小,25K2)能解析和生成RSS(动态和静态)
 
- 1)有小bug2)版本很久没有更新了,陈旧.

:选择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
提供处理聚合modulesbeans
 com.sun.syndication.feed.rss 
提供实现Rss feeds核心元素的beans
 com.sun.syndication.feed.synd 
我们主要用的就是这个包,SyndFeed and SyndEntryImpl
 com.sun.syndication.io  
提供对读取和分析feeds的输入和输出
:实例:

1:读取远端urlrss,然后输出到控制台:
/**
 *
关键代码:
 * 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类型生成rssatom的实例,
  //SyndFeed
rssatom实现类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());

                }

                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("http://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=/"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 (FeedException 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记录转成20item
           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();
            }
            //
itemdescription
            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"));
   
设置当前websitechannel属性
    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();
    }
}

 

 

原创粉丝点击