浏览 10556 次
锁定老帖子 主题:使用WebWork和Rome轻松暴露RSS
该帖已经被评为精华帖
|
|
---|---|
作者 | 正文 |
发表时间:2006-06-05
闲扯这个不是主要目的。现在Rome是Java下最常用的RSS包,最近消息似乎要转入Apache的Abdera合并变成更强大的聚合引擎。用Rome生成和解析RSS都很方便。今天讨论一下使用ROME给网站生成RSS,并通过WebWork2的Result机制渲染。 最初是从WebWork的Cookbook上看到的RomeResult的文章,一看就会,我这里其实不过是举个详细点的例子,注意我使用的是WebWork 2.2.2和Rome 0.8: http://wiki.opensymphony.com/display/WW/RomeResult 参考了和东的这篇Blog,利用rome写rss feed生成程序: http://hedong.3322.org/newblog/archives/000051.html 首先创建RomeResult类: /** * */ package com.goldnet.framework.webwork.result; import java.io.Writer; import org.apache.log4j.Logger; import com.opensymphony.webwork.ServletActionContext; import com.opensymphony.xwork.ActionInvocation; import com.opensymphony.xwork.Result; import com.sun.syndication.feed.synd.SyndFeed; import com.sun.syndication.io.SyndFeedOutput; /** * A simple Result to output a Rome SyndFeed object into a newsfeed. * @author Philip Luppens * */ public class RomeResult implements Result { private static final long serialVersionUID = -6089389751322858939L; private String feedName; private String feedType; private final static Logger logger = Logger.getLogger(RomeResult.class);; /* * (non-Javadoc); * * @see com.opensymphony.xwork.Result#execute(com.opensymphony.xwork.ActionInvocation); */ public void execute(ActionInvocation ai); throws Exception { if (feedName == null); { // ack, we need this to find the feed on the stack logger .error("Required parameter 'feedName' not found. " + "Make sure you have the param tag set and " + "the static-parameters interceptor enabled in your interceptor stack.");; // no point in continuing .. return; } // don't forget to set the content to the correct mimetype ServletActionContext.getResponse();.setContentType("text/xml");; // get the feed from the stack that can be found by the feedName SyndFeed feed = (SyndFeed); ai.getStack();.findValue(feedName);; if (logger.isDebugEnabled();); { logger.debug("Found object on stack with name '" + feedName + "': " + feed);; } if (feed != null); { if (feedType != null); { // Accepted types are: rss_0.90 - rss_2.0 and atom_0.3 // There is a bug though in the rss 2.0 generator when it checks // for the type attribute in the description element. It's has a // big 'FIXME' next to it (v. 0.7beta);. feed.setFeedType(feedType);; } SyndFeedOutput output = new SyndFeedOutput();; //we'll need the writer since Rome doesn't support writing to an outputStream yet Writer out = null; try { out = ServletActionContext.getResponse();.getWriter();; output.output(feed, out);; } catch (Exception e); { // Woops, couldn't write the feed ? logger.error("Could not write the feed", e);; } finally { //close the output writer (will flush automatically); if (out != null); { out.close();; } } } else { // woops .. no object found on the stack with that name ? logger.error("Did not find object on stack with name '" + feedName + "'");; } } public void setFeedName(String feedName); { this.feedName = feedName; } public void setFeedType(String feedType); { this.feedType = feedType; } } 程序很简单。实现了Result接口,寻找一个与feedName参数匹配的SyndFeed实例,然后转换为指定的feedType类型,然后通过rome的SyndFeedOutput输出到Response去。 然后我们给我们的WebWork配置romeResult。 在xwork.xml中配置: <package name="default" extends="webwork-default"> <result-types> <result-type name="feed" class="com.goldnet.framework.webwork.result.RomeResult"/> </result-types> <interceptors> <!-- 然后是你的那些inteceptor配置等 -->这样我们就给xwork配置了一个叫做feed的result,它就是我们的romeResult。 然后我们实现一个类,来测试一下这个romeResult。 /** * */ package com.goldnet.webwork.action.news; import com.opensymphony.xwork.ActionSupport; import com.sun.syndication.feed.synd.SyndCategory; import com.sun.syndication.feed.synd.SyndCategoryImpl; 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 org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.util.ArrayList; import java.util.Date; import java.util.List; /** * @author Tin * */ public class TestFeedCreateAction extends ActionSupport { private static final long serialVersionUID = -2207516408313865979L; private transient final Log log = LogFactory.getLog(TestFeedCreateAction.class);; private int maxEntryNumber = 25; private String siteUrl = "http://127.0.0.1"; private SyndFeed feed = null; public TestFeedCreateAction(); { super();; } @Override public String execute(); { List<News> newsList = getNewsList();; if (log.isDebugEnabled();); { log.debug("Geting feed! and got news " + newsList.size(); + " pieces.");; } feed = new SyndFeedImpl();; feed.setTitle(converttoISO("测试中的新闻系统"););; feed.setDescription(converttoISO("测试中的新闻系统:测试Rome Result"););; feed.setAuthor(converttoISO("测试Tin"););; feed.setLink("http://www.justatest.cn");; List<SyndEntry> entries = new ArrayList<SyndEntry>();; feed.setEntries(entries);; for (News news : newsList); { SyndEntry entry = new SyndEntryImpl();; entry.setAuthor(converttoISO(news.getAuthor();););; SyndCategory cat = new SyndCategoryImpl();; cat.setName(converttoISO(news.getCategory();););; List<SyndCategory> cats = new ArrayList<SyndCategory>();; cats.add(cat);; entry.setCategories(cats);; SyndContent content = new SyndContentImpl();; content.setValue(converttoISO(news.getContent();););; List<SyndContent> contents = new ArrayList<SyndContent>();; contents.add(content);; entry.setContents(contents);; entry.setDescription(content);; entry.setLink(siteUrl + "/common/news/displayNews.action?id=" + news.getId(););; entry.setTitle(converttoISO(news.getTitle();););; entry.setPublishedDate(news.getPublishDate(););; entries.add(entry);; } return SUCCESS; } private static String converttoISO(String s); { try { byte[] abyte0 = s.getBytes("UTF-8");; return new String(abyte0, "ISO-8859-1");; } catch (Exception exception); { return s; } } private List<News> getNewsList(); { List<News> newsList = new ArrayList<News>();; for (int i = 0; i < maxEntryNumber; i++); { News news = new News();; news.setTitle("测试标题" + i);; news.setContent( "<p>测试内容测试内容<span style=\"color:red\">测试内容</span></p>");; news.setPublishDate(new Date(););; news.setId(new Long(i););; news.setAuthor("Tin");; newsList.add(news);; } return newsList; } /** * @return Returns the maxEntryNumber. */ public long getMaxEntryNumber(); { return maxEntryNumber; } /** * @param maxEntryNumber The maxEntryNumber to set. */ public void setMaxEntryNumber(int maxEntryNumber); { this.maxEntryNumber = maxEntryNumber; } /** * @param siteUrl The siteUrl to set. */ public void setSiteUrl(String siteUrl); { this.siteUrl = siteUrl; } /** * @return Returns the feed. */ public SyndFeed getFeed(); { return feed; } private class News { private Long id; private String title; private String content; private Date publishDate; private String author; private String category; /** * Getter/Setter都省略了,使用了内部类,就是图个方便 * 本意是模仿我们常常使用的Pojo,大家的实现都不一样,我突简单,里面其实可以有复杂类型的 */ } } 真是不好意思,Getter/Setter占了大部分地方我省略去了。逻辑很简单,就是把我们的POJO影射到Feed的模型上面,过程很简单。我留下了几个参数可以在外面设置: maxEntryNumber显示的feed的条数,链接生成时使用的SiteUrl,当然也可以通过request获取。 下面我们配置我们的Action,注意平时我们可能使用DAO生成newsList,而不是我这个写死的getNewsList()方法,此时可能需要配合Spring进行IOC的设置,我们这里省略掉。 下面是我们这个Action的xwork配置: <package name="news" extends="default" namespace="/news"> <action name="feed" class="com.goldnet.webwork.action.news.TestFeedCreateAction"> <!-- 每次生成15条rss feed --> <param name="maxEntryNumber">15</param> <!-- 链接的前缀,我们使用Weblogic是7001,也许你的是8080 --> <param name="siteUrl">http://127.0.0.1:7001</param> <!-- result是feed --> <result name="success" type="feed"> <!-- feed名字是feed,对应我们这个Action中的那个SyndFeed的实例的名字feed,别忘记写getter --> <param name="feedName">feed</param> <!-- 制定生成的feed的类型,我这里选择rss_2.0 --> <!-- rome 0.8支持atom_0.3、atom_1.0、rss_1.0、rss_2.0、rss_0.90、rss_0.91、rss_0.91、rss_0.91U、rss_0.92、rss_0.93、rss_0.94 --> <param name="feedType">rss_2.0</param> </result> </action> </package> OK,配置完毕后访问/news/feed.action就可以访问到这个feed了。倒入你的feedDeamon,看看,是不是非常简单? 不过需要考虑两个地方,一个是编码问题,看了和东说的中文问题,本没当回事,结果生成乱码(我们项目全部使用UTF-8),然后还是转了一下。没有研究ROME源代码,感觉xml不应该有UTF-8还会乱码的问题呀,也许还需要看看是否是设置不到位。还有就是对于feed如果增加了权限认证则访问比较麻烦,用feedDeamon这样的客户端就无法访问到了,因为它不会显示登陆失败后显示的登陆页面,也许放feed就要开放一点吧(当然还是有变通放案的)。 和动例子里面的rome 0.7和现在的rome 0.8相比,Api已经发生了不少变化,唉,开源要代码稳定还真难。 就这些,就到这里,粗陋了:D 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2006-06-06
very good!
谢谢楼主! 我正想做这方面的工作,你已经把路都铺好了。 再次感谢! |
|
返回顶楼 | |
发表时间:2007-06-06
好东西 用你的东西调了一下 发现在RomeResult中设置feed.setEncoding("iso-8859-1");就行了 不用转换也能看到中文。
|
|
返回顶楼 | |
发表时间:2007-06-06
我这里试验的时候,在这行会出错:
SyndFeedOutput output = new SyndFeedOutput(); Rome 0.9 和webwork2.24. --------------------------------------------------------- 可以了,原来是rome需要jdom包的支持,只是出错的时候没有任何提示,感觉很不爽啊。 一开始试的时候也有乱码,按照楼上的说的改了后,果然是立竿见影, 中文可以显示了, 只是不明白为什么用iso-8859-1编码的。 |
|
返回顶楼 | |
发表时间:2007-06-11
请问想让这个生成的rss在ie中正常显示要怎么做 rome好像不能写入xsl的引用 这样ie是无法浏览的
|
|
返回顶楼 | |