Tin's Blog

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

            BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
            128 隨筆 :: 0 文章 :: 221 評(píng)論 :: 0 Trackbacks

          WebWork的result實(shí)現(xiàn)非常實(shí)用,它很好的解決了View渲染的靈活性問(wèn)題。這才是MVC模式的優(yōu)勢(shì)所在,而像JSF那樣幫定JSP的MVC就吃不到這個(gè)甜頭了。說(shuō)WebWork2是Model 2 MVC的巔峰就在這些靈活的地方。
          閑扯這個(gè)不是主要目的。現(xiàn)在Rome是Java下最常用的RSS包,最近消息似乎要轉(zhuǎn)入Apache的Abdera合并變成更強(qiáng)大的聚合引擎。用Rome生成和解析RSS都很方便。今天討論一下使用ROME給網(wǎng)站生成RSS,并通過(guò)WebWork2的Result機(jī)制渲染。
          最初是從WebWork的Cookbook上看到的RomeResult的文章,一看就會(huì),我這里其實(shí)不過(guò)是舉個(gè)詳細(xì)點(diǎn)的例子,注意我使用的是WebWork 2.2.2和Rome 0.8:
          http://wiki.opensymphony.com/display/WW/RomeResult
          參考了和東的這篇Blog,利用rome寫(xiě)rss feed生成程序:
          http://hedong.3322.org/newblog/archives/000051.html

          首先創(chuàng)建RomeResult類(lèi):

          /**
          ?*?
          ?
          */
          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;
          ?}

          }

          程序很簡(jiǎn)單。實(shí)現(xiàn)了Result接口,尋找一個(gè)與feedName參數(shù)匹配的SyndFeed實(shí)例,然后轉(zhuǎn)換為指定的feedType類(lèi)型,然后通過(guò)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配置了一個(gè)叫做feed的result,它就是我們的romeResult。
          然后我們實(shí)現(xiàn)一個(gè)類(lèi),來(lái)測(cè)試一下這個(gè)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(
          " 測(cè)試中的新聞系統(tǒng) " ));
          ????????feed.setDescription(converttoISO(
          " 測(cè)試中的新聞系統(tǒng):測(cè)試Rome?Result " ));
          ????????feed.setAuthor(converttoISO(
          " 測(cè)試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(
          " 測(cè)試標(biāo)題 " ? + ?i);
          ????????????news.setContent(
          ????????????????
          " <p>測(cè)試內(nèi)容測(cè)試內(nèi)容<span?style=\ " color:red\ " >測(cè)試內(nèi)容</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都省略了,使用了內(nèi)部類(lèi),就是圖個(gè)方便
          ??*?本意是模仿我們常常使用的Pojo,大家的實(shí)現(xiàn)都不一樣,我突簡(jiǎn)單,里面其實(shí)可以有復(fù)雜類(lèi)型的
          ??
          */
          ????}
          }

          真是不好意思,Getter/Setter占了大部分地方我省略去了。邏輯很簡(jiǎn)單,就是把我們的POJO影射到Feed的模型上面,過(guò)程很簡(jiǎn)單。我留下了幾個(gè)參數(shù)可以在外面設(shè)置:
          maxEntryNumber顯示的feed的條數(shù),鏈接生成時(shí)使用的SiteUrl,當(dāng)然也可以通過(guò)request獲取。
          下面我們配置我們的Action,注意平時(shí)我們可能使用DAO生成newsList,而不是我這個(gè)寫(xiě)死的getNewsList()方法,此時(shí)可能需要配合Spring進(jìn)行IOC的設(shè)置,我們這里省略掉。
          下面是我們這個(gè)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,對(duì)應(yīng)我們這個(gè)Action中的那個(gè)SyndFeed的實(shí)例的名字feed,別忘記寫(xiě)getter? -->
          ????
          < param? name ="feedName" > feed </ param >
          ????
          <!-- ?制定生成的feed的類(lèi)型,我這里選擇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,配置完畢后訪問(wèn)/news/feed.action就可以訪問(wèn)到這個(gè)feed了。倒入你的feedDeamon,看看,是不是非常簡(jiǎn)單?
          不過(guò)需要考慮兩個(gè)地方,一個(gè)是編碼問(wèn)題,看了和東說(shuō)的中文問(wèn)題,本沒(méi)當(dāng)回事,結(jié)果生成亂碼(我們項(xiàng)目全部使用UTF-8),然后還是轉(zhuǎn)了一下。沒(méi)有研究ROME源代碼,感覺(jué)xml不應(yīng)該有UTF-8還會(huì)亂碼的問(wèn)題呀,也許還需要看看是否是設(shè)置不到位。還有就是對(duì)于feed如果增加了權(quán)限認(rèn)證則訪問(wèn)比較麻煩,用feedDeamon這樣的客戶端就無(wú)法訪問(wèn)到了,因?yàn)樗粫?huì)顯示登陸失敗后顯示的登陸頁(yè)面,也許放feed就要開(kāi)放一點(diǎn)吧(當(dāng)然還是有變通放案的)。
          和動(dòng)例子里面的rome 0.7和現(xiàn)在的rome 0.8相比,Api已經(jīng)發(fā)生了不少變化,唉,開(kāi)源要代碼穩(wěn)定還真難。
          就這些,就到這里,粗陋了:D

          posted on 2006-06-05 22:25 Tin 閱讀(3389) 評(píng)論(7)  編輯  收藏 所屬分類(lèi): Webwork相關(guān)

          評(píng)論

          # re: 使用WebWork和Rome輕松暴露RSS 2006-06-06 08:59 wolfsquare
          不錯(cuò),贊一個(gè).
          這樣的文章比整天鼓噪自己的開(kāi)源項(xiàng)目和團(tuán)隊(duì)還在首頁(yè)吵架的文章要好多了.
            回復(fù)  更多評(píng)論
            

          # re: 使用WebWork和Rome輕松暴露RSS 2006-06-07 00:54 差沙
          寫(xiě)的很好呀,贊一個(gè)。厚厚。  回復(fù)  更多評(píng)論
            

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

            回復(fù)  更多評(píng)論
            

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

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

          borderj#gmail.com

            回復(fù)  更多評(píng)論
            

          # re: 使用WebWork和Rome輕松暴露RSS 2006-09-25 17:39 feiyi10
          我開(kāi)始也出現(xiàn)了中文亂碼問(wèn)題。。跟蹤發(fā)現(xiàn),其實(shí)跟set的時(shí)候沒(méi)關(guān)系。
          之所以出現(xiàn)亂碼問(wèn)題。是因?yàn)镽omeResult這個(gè)類(lèi)默認(rèn)編碼為ISO8859-1。
          在ServletActionContext.getResponse().setContentType( " text/xml " );出加一句ServletActionContext.getResponse().setCharacterEncoding("utf-8");//根據(jù)需要添寫(xiě)自己的編碼。希望對(duì)大家有所幫助。說(shuō)的不對(duì)。還望見(jiàn)諒。  回復(fù)  更多評(píng)論
            

          # re: 使用WebWork和Rome輕松暴露RSS 2006-09-25 18:14 Tin
          謝謝feiyi10提醒。估計(jì)是response的編碼設(shè)置問(wèn)題,我沒(méi)有認(rèn)真跟蹤。希望遇到問(wèn)題的朋友嘗試一下。  回復(fù)  更多評(píng)論
            

          主站蜘蛛池模板: 舟曲县| 日喀则市| 定安县| 三穗县| 禄劝| 黄梅县| 遵义县| 赤水市| 洪江市| 伊川县| 塘沽区| 万荣县| 合山市| 高淳县| 隆子县| 清丰县| 红桥区| 龙门县| 景东| 金坛市| 石渠县| 勃利县| 彝良县| 高台县| 金寨县| 靖远县| 宜黄县| 壤塘县| 涟源市| 绥阳县| 蒙自县| 岚皋县| 山东| 吴堡县| 灵台县| 仪陇县| 古田县| 峨边| 沐川县| 九江县| 石楼县|