使用WebWork和Rome轻松暴露RSS
来源:互联网 发布:深圳潮流网络怎么样 编辑:程序博客网 时间:2024/05/12 22:28
WebWork的result实现非常实用,它很好的解决了View渲染的灵活性问题。这才是MVC模式的优势所在,而像JSF那样帮定JSP的MVC就吃不到这个甜头了。说WebWork2是Model 2 MVC的巅峰就在这些灵活的地方。
闲扯这个不是主要目的。现在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类:
程序很简单。实现了Result接口,寻找一个与feedName参数匹配的SyndFeed实例,然后转换为指定的feedType类型,然后通过rome的SyndFeedOutput输出到Response去。
然后我们给我们的WebWork配置romeResult。
在xwork.xml中配置:
然后我们实现一个类,来测试一下这个romeResult。
真是不好意思,Getter/Setter占了大部分地方我省略去了。逻辑很简单,就是把我们的POJO影射到Feed的模型上面,过程很简单。我留下了几个参数可以在外面设置:
maxEntryNumber显示的feed的条数,链接生成时使用的SiteUrl,当然也可以通过request获取。
下面我们配置我们的Action,注意平时我们可能使用DAO生成newsList,而不是我这个写死的getNewsList()方法,此时可能需要配合Spring进行IOC的设置,我们这里省略掉。
下面是我们这个Action的xwork配置:
OK,配置完毕后访问/news/feed.action就可以访问到这个feed了。倒入你的feedDeamon,看看,是不是非常简单?
不过需要考虑两个地方,一个是编码问题,看了和东说的中文问题,本没当回事,结果生成乱码(我们项目全部使用UTF-8),然后还是转了一下。没有研究ROME源代码,感觉xml不应该有UTF-8还会乱码的问题呀,也许还需要看看是否是设置不到位。还有就是对于feed如果增加了权限认证则访问比较麻烦,用feedDeamon这样的客户端就无法访问到了,因为它不会显示登陆失败后显示的登陆页面,也许放feed就要开放一点吧(当然还是有变通放案的)。
和动例子里面的rome 0.7和现在的rome 0.8相比,Api已经发生了不少变化,唉,开源要代码稳定还真难。
就这些,就到这里,粗陋了
闲扯这个不是主要目的。现在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;
- }
- }
/** * */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 stacklogger.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 mimetypeServletActionContext.getResponse();.setContentType("text/xml");;// get the feed from the stack that can be found by the feedNameSyndFeed 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 yetWriter 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配置等 -->
<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,大家的实现都不一样,我突简单,里面其实可以有复杂类型的
- */
- }
- }
/** * */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>
<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已经发生了不少变化,唉,开源要代码稳定还真难。
就这些,就到这里,粗陋了
- 使用WebWork和Rome轻松暴露RSS
- 使用Rome 生成RSS
- 使用Rome解析RSS Feed
- 使用rome解析rss xml
- 使用Rome解析百度RSS
- webwork+freemarker轻松实现Rss,Atom
- rome-rss
- 使用rome创建RSS格式的xml
- WEB中使用ROME实现RSS服务
- java使用Rome解析Rss的实例
- rss reader 解析和创建(Rome rss lib)
- ROME解析RSS(代码)
- ROME解析 百度 RSS
- Rome自动生成Rss
- Rome读取RSS
- 用Rome解析RSS
- 使用Rome实现网站RSS发布的简单步骤
- 使用Rome实现网站RSS发布的简单步骤
- java解惑之移位操作
- 股东
- 关于用户角色权限的一点想法(RBAC)
- ROME解析RSS(代码)
- java解惑之无穷大和NaN
- 使用WebWork和Rome轻松暴露RSS
- MOSS新增item , Folder 并各种字段初始化加载
- ROME解析 百度 RSS
- '用户 'sa' 登录失败。该用户与可信 SQL Server 连接无关联,做JSP项目连接数据库
- SQL Server BUG集之自定义函数与group by
- Hibernate中的数据库连接池配置
- Rome使用简单说明一(基本应用)
- 好吃的湖南米粉
- 开放式文档同构引擎研究