`
Tin
  • 浏览: 138614 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

使用WebWork和Rome轻松暴露RSS

阅读更多

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类:

/**
 * 
 
*/
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

分享到:
评论

相关推荐

    webwork标签的使用和介绍

    WebWork 是一款基于 Java 的 MVC(Model-View-Controller)框架,它提供了强大的标签库来简化JSP页面的开发。这些标签使得开发者能够更高效地处理业务...使用WebWork,开发者可以创建出结构清晰、易于维护的Web应用。

    使用webwork上传excel并导入数据库

    总之,使用WebWork上传Excel并导入MySQL数据库是一项常见的任务,涉及到前端交互、文件上传处理、Excel解析和数据库操作等多个技术领域。理解并熟练掌握这些知识点对于开发企业级应用至关重要。在实践中,不断优化和...

    webwork+spring整合例子 内带使用说明 以及webwork文档(中文)

    WebWork和Spring是两个在Java Web开发中广泛使用的框架,它们各自有着独特的优点。WebWork以其强大的动作映射和强大的表单验证而著名,而Spring则以其依赖注入和全面的企业级服务支持闻名。将这两个框架整合在一起,...

    webwork-1.4-src.zip_webwork_webwork s_webwork.zip_webwork1.4.zip

    6. **视图渲染**:WebWork使用JSP、FreeMarker或其他模板引擎作为视图技术,通过ActionSupport类和结果类型来决定如何渲染视图,使得视图层与控制层解耦。 7. **标签库**:WebWork提供了一套自定义的JSP标签,如`...

    WEBWORK

    WebWork 提供了强大的动作(Action)处理、类型转换、拦截器(Interceptor)机制和丰富的验证功能,帮助开发者构建可维护、可扩展的 Web 应用程序。 在 WebWork 中,配置是至关重要的,因为它定义了框架如何工作...

    webwork2.17中文使用手册

    webwork2.17中文使用手册

    webwork

    6. **国际化与本地化**:WebWork 支持多语言环境,允许开发者轻松地创建和切换不同语言的资源文件,实现应用的国际化。 7. **标签库**:WebWork 自带一套丰富的标签库,可以方便地在JSP页面中使用,减少硬编码,...

    webwork中上传文件

    在本例中,我们关注的是使用WebWork框架在Java环境中实现文件上传。WebWork是一个轻量级的MVC(Model-View-Controller)框架,它提供了处理HTTP请求和响应的强大工具,包括文件上传。 首先,我们需要了解WebWork的...

    WebWork docs 2 -- webWork 详细的说明文档

    WebWork docs 2 是一套完整的WebWork框架的详细说明文档,包含了开发者在使用WebWork时可能遇到的所有问题的解答。 这套文档涵盖了以下几个主要的知识点: 1. **WebWork基础**:WebWork的核心概念,如Action、...

    WebWork_开发指南

    - **国际化支持**:为了满足不同国家和地区的需求,WebWork 提供了国际化功能,允许开发者轻松地进行多语言切换和管理。 - **WebWork 与 Spring 的集成**:由于 Spring 框架的流行,WebWork 提供了与 Spring 的集成...

    webwork电子书

    这个压缩包包含了两个关于Webwork的重要资源,即"Webwork2 Guide"和"webwork2doc_zh1[1]"电子书,对于学习和使用Webwork的用户来说是宝贵的参考资料。 首先,我们来看"Webwork2 Guide"。这本指南通常会提供Webwork2...

    webwork.pdf

    WebWork 2.0的显著特点是它被拆分为两大部分:WebWork 2.x和XWork 1.x,这种分离不仅提升了框架的灵活性,还增强了其扩展性和性能。 #### 架构创新 WebWork 1.x版本在设计上与Struts框架类似,采用的是紧密耦合的...

    webwork详细讲解.doc

    深入理解`xwork.xml`的结构和标签对于高效使用WebWork至关重要。 #### 实战G-Roller-WW 虽然原文件中没有详细介绍G-Roller-WW的实际应用案例,但这一部分可能涉及如何将WebWork与G-Roller(一个博客平台)结合使用...

    WebWork教程

    WebWork是一个由OpenSymphony组织开发的Java Web框架,它遵循MVC(Model-View-...通过本教程的学习,开发者可以快速掌握WebWork的基本概念和使用方法,并能够利用其提供的多种功能来构建高效、可维护的Web应用。

    Webwork2_guide

    "Webwork2_guide"这个指南,很显然是为了帮助用户更好地理解和掌握Webwork2框架的使用。 Webwork2的核心概念: 1. **模型(Model)**:模型是应用中的业务逻辑,处理数据和业务规则。在Webwork2中,模型通常由...

    webWork

    4. OGNL(Object-Graph Navigation Language):WebWork使用OGNL作为表达式语言,用于在Action和视图之间传递数据。OGNL允许开发者方便地访问和修改对象属性,增强了视图的动态性。 三、主要功能 1. 参数绑定:...

    WebWork 简介

    WebWork的核心目标是提供一个更加灵活、易于理解和使用的MVC(模型-视图-控制器)架构,帮助开发者高效地处理Web请求并管理业务逻辑。 **1. MVC架构** WebWork基于MVC设计模式,将应用程序分为三个主要部分:模型、...

    webwork的jar包

    WebWork 是一个基于Java的MVC(模型-视图-控制器)框架,它在Web应用程序开发中被广泛使用。WebWork 1 和 WebWork 2 都是该框架的不同版本,每个版本都有其特性和改进。 WebWork 1 是早期的版本,提供了基础的MVC...

    webwork中文帮助文档

    本中文帮助文档旨在为使用WebWork框架的开发者提供详尽的指导和支持。 在WebWork框架中,模型(Model)负责处理业务逻辑,视图(View)负责展示数据,控制器(Controller)则协调模型和视图,处理用户的请求。这种...

Global site tag (gtag.js) - Google Analytics