备注学院

LuLu

  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  5 随笔 :: 50 文章 :: 16 评论 :: 0 Trackbacks

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.2Rome 0.8
http://wiki.opensymphony.com/display/WW/RomeResult
参考了和东的这篇Blog,利用rome写rss feed生成程序:
http://hedong.3322.org/newblog/archives/000051.html

首先创建RomeResult类:

代码
  1. /**  
  2.  *   
  3.  */  
  4. package com.goldnet.framework.webwork.result;   
  5.   
  6. import java.io.Writer;   
  7.   
  8. import org.apache.log4j.Logger;   
  9.   
  10. import com.opensymphony.webwork.ServletActionContext;   
  11. import com.opensymphony.xwork.ActionInvocation;   
  12. import com.opensymphony.xwork.Result;   
  13. import com.sun.syndication.feed.synd.SyndFeed;   
  14. import com.sun.syndication.io.SyndFeedOutput;   
  15.   
  16. /**  
  17.  * A simple Result to output a Rome SyndFeed object into a newsfeed.  
  18.  * @author Philip Luppens  
  19.  *   
  20.  */  
  21. public class RomeResult implements Result {   
  22.     private static final long serialVersionUID = -6089389751322858939L;   
  23.   
  24.     private String feedName;   
  25.   
  26.     private String feedType;   
  27.   
  28.     private final static Logger logger = Logger.getLogger(RomeResult.class);   
  29.   
  30.     /*  
  31.      * (non-Javadoc)  
  32.      *   
  33.      * @see com.opensymphony.xwork.Result#execute(com.opensymphony.xwork.ActionInvocation)  
  34.      */  
  35.     public void execute(ActionInvocation ai) throws Exception {   
  36.         if (feedName == null) {   
  37.             // ack, we need this to find the feed on the stack   
  38.             logger   
  39.                     .error("Required parameter 'feedName' not found. "  
  40.                             + "Make sure you have the param tag set and "  
  41.                             + "the static-parameters interceptor enabled in your interceptor stack.");   
  42.             // no point in continuing ..   
  43.             return;   
  44.         }   
  45.   
  46.         // don't forget to set the content to the correct mimetype   
  47.         ServletActionContext.getResponse().setContentType("text/xml");   
  48.         // get the feed from the stack that can be found by the feedName   
  49.         SyndFeed feed = (SyndFeed) ai.getStack().findValue(feedName);   
  50.   
  51.         if (logger.isDebugEnabled()) {   
  52.             logger.debug("Found object on stack with name '" + feedName + "': "  
  53.                     + feed);   
  54.         }   
  55.         if (feed != null) {   
  56.   
  57.             if (feedType != null) {   
  58.                 // Accepted types are: rss_0.90 - rss_2.0 and atom_0.3   
  59.                 // There is a bug though in the rss 2.0 generator when it checks   
  60.                 // for the type attribute in the description element. It's has a   
  61.                 // big 'FIXME' next to it (v. 0.7beta).   
  62.                 feed.setFeedType(feedType);   
  63.             }   
  64.             SyndFeedOutput output = new SyndFeedOutput();   
  65.             //we'll need the writer since Rome doesn't support writing to an outputStream yet   
  66.             Writer out = null;   
  67.             try {   
  68.                 out = ServletActionContext.getResponse().getWriter();   
  69.                 output.output(feed, out);   
  70.             } catch (Exception e) {   
  71.                 // Woops, couldn't write the feed ?   
  72.                 logger.error("Could not write the feed", e);   
  73.             } finally {   
  74.                 //close the output writer (will flush automatically)   
  75.                 if (out != null) {   
  76.                     out.close();   
  77.                 }   
  78.             }   
  79.   
  80.         } else {   
  81.             // woops .. no object found on the stack with that name ?   
  82.             logger.error("Did not find object on stack with name '" + feedName   
  83.                     + "'");   
  84.         }   
  85.     }   
  86.   
  87.     public void setFeedName(String feedName) {   
  88.         this.feedName = feedName;   
  89.     }   
  90.   
  91.     public void setFeedType(String feedType) {   
  92.         this.feedType = feedType;   
  93.     }   
  94.   
  95. }  

 

程序很简单。实现了Result接口,寻找一个与feedName参数匹配的SyndFeed实例,然后转换为指定的feedType类型,然后通过rome的SyndFeedOutput输出到Response去。
然后我们给我们的WebWork配置romeResult。
在xwork.xml中配置:

代码
  1. <package name="default" extends="webwork-default">  
  2.         <result-types>  
  3.             <result-type name="feed" class="com.goldnet.framework.webwork.result.RomeResult"/>  
  4.         </result-types>  
  5.         <interceptors>  
  6.         <!-- 然后是你的那些inteceptor配置等 -->  
这样我们就给xwork配置了一个叫做feed的result,它就是我们的romeResult。
然后我们实现一个类,来测试一下这个romeResult。
代码
  1. /**   
  2.  *   
  3.  */   
  4. package com.goldnet.webwork.action.news;   
  5.   
  6. import com.opensymphony.xwork.ActionSupport;   
  7.   
  8. import com.sun.syndication.feed.synd.SyndCategory;   
  9. import com.sun.syndication.feed.synd.SyndCategoryImpl;   
  10. import com.sun.syndication.feed.synd.SyndContent;   
  11. import com.sun.syndication.feed.synd.SyndContentImpl;   
  12. import com.sun.syndication.feed.synd.SyndEntry;   
  13. import com.sun.syndication.feed.synd.SyndEntryImpl;   
  14. import com.sun.syndication.feed.synd.SyndFeed;   
  15. import com.sun.syndication.feed.synd.SyndFeedImpl;   
  16.   
  17. import org.apache.commons.logging.Log;   
  18. import org.apache.commons.logging.LogFactory;   
  19.   
  20. import java.util.ArrayList;   
  21. import java.util.Date;   
  22. import java.util.List;   
  23.   
  24. /**   
  25.  * @author Tin   
  26.  *   
  27.  */   
  28. public class TestFeedCreateAction extends ActionSupport {   
  29.     private static final long serialVersionUID = -2207516408313865979L;   
  30.     private transient final Log log = LogFactory.getLog(TestFeedCreateAction.class);   
  31.     private int maxEntryNumber = 25;   
  32.     private String siteUrl = "http://127.0.0.1";   
  33.     private SyndFeed feed = null;   
  34.   
  35.     public TestFeedCreateAction() {   
  36.         super();   
  37.     }   
  38.   
  39.     @Override   
  40.     public String execute() {   
  41.         List<News> newsList = getNewsList();   
  42.   
  43.         if (log.isDebugEnabled()) {   
  44.             log.debug("Geting feed! and got news " + newsList.size() +   
  45.                 " pieces.");   
  46.         }   
  47.   
  48.         feed = new SyndFeedImpl();   
  49.   
  50.         feed.setTitle(converttoISO("测试中的新闻系统"));   
  51.         feed.setDescription(converttoISO("测试中的新闻系统:测试Rome Result"));   
  52.         feed.setAuthor(converttoISO("测试Tin"));   
  53.         feed.setLink("http://www.justatest.cn");   
  54.   
  55.         List<SyndEntry> entries = new ArrayList<SyndEntry>();   
  56.         feed.setEntries(entries);   
  57.   
  58.         for (News news : newsList) {   
  59.             SyndEntry entry = new SyndEntryImpl();   
  60.             entry.setAuthor(converttoISO(news.getAuthor()));   
  61.   
  62.             SyndCategory cat = new SyndCategoryImpl();   
  63.             cat.setName(converttoISO(news.getCategory()));   
  64.   
  65.             List<SyndCategory> cats = new ArrayList<SyndCategory>();   
  66.             cats.add(cat);   
  67.             entry.setCategories(cats);   
  68.   
  69.             SyndContent content = new SyndContentImpl();   
  70.             content.setValue(converttoISO(news.getContent()));   
  71.   
  72.             List<SyndContent> contents = new ArrayList<SyndContent>();   
  73.             contents.add(content);   
  74.             entry.setContents(contents);   
  75.             entry.setDescription(content);   
  76.             entry.setLink(siteUrl + "/common/news/displayNews.action?id=" +   
  77.                 news.getId());   
  78.             entry.setTitle(converttoISO(news.getTitle()));   
  79.             entry.setPublishedDate(news.getPublishDate());   
  80.             entries.add(entry);   
  81.         }   
  82.   
  83.         return SUCCESS;   
  84.     }   
  85.   
  86.     private static String converttoISO(String s) {   
  87.         try {   
  88.             byte[] abyte0 = s.getBytes("UTF-8");   
  89.   
  90.             return new String(abyte0, "ISO-8859-1");   
  91.         } catch (Exception exception) {   
  92.             return s;   
  93.         }   
  94.     }   
  95.   
  96.     private List<News> getNewsList() {   
  97.         List<News> newnewsList = new ArrayList<News>();   
  98.   
  99.         for (int i = 0; i < maxEntryNumber; i++) {   
  100.             News newnews = new News();   
  101.             news.setTitle("测试标题" + i);   
  102.             news.setContent(   
  103.                 "<p>测试内容测试内容<span style=\"color:red\">测试内容</span></p>");   
  104.             news.setPublishDate(new Date());   
  105.             news.setId(new Long(i));   
  106.             news.setAuthor("Tin");   
  107.             newsList.add(news);   
  108.         }   
  109.   
  110.         return newsList;   
  111.     }   
  112.   
  113.     /**   
  114.      * @return Returns the maxEntryNumber.   
  115.      */   
  116.     public long getMaxEntryNumber() {   
  117.         return maxEntryNumber;   
  118.     }   
  119.   
  120.     /**   
  121.      * @param maxEntryNumber The maxEntryNumber to set.   
  122.      */   
  123.     public void setMaxEntryNumber(int maxEntryNumber) {   
  124.         this.maxEntryNumber = maxEntryNumber;   
  125.     }   
  126.   
  127.     /**   
  128.      * @param siteUrl The siteUrl to set.   
  129.      */   
  130.     public void setSiteUrl(String siteUrl) {   
  131.         this.siteUrl = siteUrl;   
  132.     }   
  133.   
  134.     /**   
  135.      * @return Returns the feed.   
  136.      */   
  137.     public SyndFeed getFeed() {   
  138.         return feed;   
  139.     }   
  140.   
  141.     private class News {   
  142.         private Long id;   
  143.         private String title;   
  144.         private String content;   
  145.         private Date publishDate;   
  146.         private String author;   
  147.         private String category;   
  148.   
  149.         /**   
  150.      * Getter/Setter都省略了,使用了内部类,就是图个方便   
  151.      * 本意是模仿我们常常使用的Pojo,大家的实现都不一样,我突简单,里面其实可以有复杂类型的     
  152.   
  153. */   
  154.     }   
  155. }  

 

真是不好意思,Getter/Setter占了大部分地方我省略去了。逻辑很简单,就是把我们的POJO影射到Feed的模型上面,过程很简单。我留下了几个参数可以在外面设置:
maxEntryNumber显示的feed的条数,链接生成时使用的SiteUrl,当然也可以通过request获取。
下面我们配置我们的Action,注意平时我们可能使用DAO生成newsList,而不是我这个写死的getNewsList()方法,此时可能需要配合Spring进行IOC的设置,我们这里省略掉。
下面是我们这个Action的xwork配置:

代码
  1. <package name="news" extends="default" namespace="/news">  
  2.         <action name="feed" class="com.goldnet.webwork.action.news.TestFeedCreateAction">  
  3.             <!-- 每次生成15条rss feed -->  
  4.             <param name="maxEntryNumber">15</param>  
  5.             <!-- 链接的前缀,我们使用Weblogic是7001,也许你的是8080 -->  
  6.             <param name="siteUrl">http://127.0.0.1:7001</param>  
  7.             <!-- result是feed -->  
  8.             <result name="success" type="feed">  
  9.                 <!-- feed名字是feed,对应我们这个Action中的那个SyndFeed的实例的名字feed,别忘记写getter -->  
  10.                 <param name="feedName">feed</param>  
  11.                 <!-- 制定生成的feed的类型,我这里选择rss_2.0 -->  
  12.                 <!-- 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 -->  
  13.                 <param name="feedType">rss_2.0</param>  
  14.             </result>  
  15.         </action>  
  16. </package>  

OK,配置完毕后访问/news/feed.action就可以访问到这个feed了。倒入你的feedDeamon,看看,是不是非常简单?
不过需要考虑两个地方,一个是编码问题,看了和东说的中文问题,本没当回事,结果生成乱码(我们项目全部使用UTF-8),然后还是转了一下。没有研究ROME源代码,感觉xml不应该有UTF-8还会乱码的问题呀,也许还需要看看是否是设置不到位。还有就是对于feed如果增加了权限认证则访问比较麻烦,用feedDeamon这样的客户端就无法访问到了,因为它不会显示登陆失败后显示的登陆页面,也许放feed就要开放一点吧(当然还是有变通放案的)。
和动例子里面的rome 0.7和现在的rome 0.8相比,Api已经发生了不少变化,唉,开源要代码稳定还真难。
就这些,就到这里,粗陋了:D

摘自:http://www.javaeye.com/post/125096
posted on 2007-11-18 12:08 smildlzj 阅读(268) 评论(0)  编辑  收藏 所属分类: Web开发

只有注册用户登录后才能发表评论。


网站导航: