Tin's Blog

          You are coming a long way, baby~Thinking, feeling, memory...

            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
            128 隨筆 :: 0 文章 :: 221 評論 :: 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.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

          posted on 2006-06-05 22:25 Tin 閱讀(3389) 評論(7)  編輯  收藏 所屬分類: Webwork相關

          評論

          # re: 使用WebWork和Rome輕松暴露RSS 2006-06-06 08:59 wolfsquare
          不錯,贊一個.
          這樣的文章比整天鼓噪自己的開源項目和團隊還在首頁吵架的文章要好多了.
            回復  更多評論
            

          # re: 使用WebWork和Rome輕松暴露RSS 2006-06-07 00:54 差沙
          寫的很好呀,贊一個。厚厚。  回復  更多評論
            

          # re: 使用WebWork和Rome輕松暴露RSS 2006-07-11 18:50 Border
          怎么解決中文編碼問題,現在已經調試成功,但是當有中文就出現一部分亂碼,不知道怎么解決。不知道你是怎么解決的,能不能給些建議。
          先謝過了

            回復  更多評論
            

          # re: 使用WebWork和Rome輕松暴露RSS 2006-07-11 22:15 Tin
          如果只有部分中文亂碼,可能是使用了GBK編碼,轉換為UTF-8等編碼時會有部分字符無法轉換吧。你從GBK轉到ISO8850-1看看。  回復  更多評論
            

          # re: 使用WebWork和Rome輕松暴露RSS 2006-07-12 09:55 Border
          還是不行,我的原feed文件是utf-8的,也就是你的rss文件,http://www.aygfsteel.com/iamtin/Rss.aspx
          要是我GBK轉到ISO8859-1還是亂碼,我只有通過
          entry.setTitle(new String(entry.getTitle().getBytes("utf-8")));
          來把原feed文件,方到目標文件,不過還是出現部分亂碼。如果方便的話,我把我的代碼給你發過去,你看看。

          borderj#gmail.com

            回復  更多評論
            

          # re: 使用WebWork和Rome輕松暴露RSS 2006-09-25 17:39 feiyi10
          我開始也出現了中文亂碼問題。。跟蹤發現,其實跟set的時候沒關系。
          之所以出現亂碼問題。是因為RomeResult這個類默認編碼為ISO8859-1。
          在ServletActionContext.getResponse().setContentType( " text/xml " );出加一句ServletActionContext.getResponse().setCharacterEncoding("utf-8");//根據需要添寫自己的編碼。希望對大家有所幫助。說的不對。還望見諒。  回復  更多評論
            

          # re: 使用WebWork和Rome輕松暴露RSS 2006-09-25 18:14 Tin
          謝謝feiyi10提醒。估計是response的編碼設置問題,我沒有認真跟蹤。希望遇到問題的朋友嘗試一下。  回復  更多評論
            

          主站蜘蛛池模板: 丹阳市| 洪雅县| 新野县| 东乌珠穆沁旗| 旌德县| 荥经县| 玉林市| 定边县| 遂平县| 惠水县| 株洲市| 新蔡县| 准格尔旗| 方正县| 清水县| 英德市| 楚雄市| 长岛县| 志丹县| 宜州市| 中宁县| 博兴县| 个旧市| 海兴县| 嘉鱼县| 甘泉县| 崇文区| 靖宇县| 余姚市| 桐柏县| 三门峡市| 柳江县| 岳阳市| 南丰县| 井冈山市| 万载县| 镶黄旗| 黑河市| 平和县| 漾濞| 象州县|