使用FreeMarker/Jsp(webwork)生成靜態/動態RSS文件

          scud(飛云小俠)  http://www.jscud.com 轉載請注明作者/來源

          關鍵字:rss,freemarker,rss.xml,webwork2

          RSS在網絡上大行其道,各種網站都加上RSS支持,我最近也研究了一下,給我的文章也加上了RSS訂閱.

          RSS目前用的也有幾個版本,很是混亂,下面以RSS2.0為例來說明.

          網絡上有個rsslibj庫,是用來生成rss支持文件的,不過已經好久沒有更新了,它是用xml的方式生成的.本文的例子不用到任何xml解析器,不過當然要知道最后生成的XML文件的格式才行,關于RSS規范,可以瀏覽一下 http://blogs.law.harvard.edu/tech/rss .

          在計劃生成RSS文件的時候,順便搜索了一下JIRA和Confluence的程序,發現它們分別是用模板方式和JSP動態頁面來展示的.于是我也想到兩種方式:
          1.用FreeMarker生成靜態文件,適用于更新不是很頻繁的內容.
          2.用JSP動態展示,適合更新頻率高,種類繁多的內容.

          還是以本站的新聞舉例,其中的新聞信息類參考 http://www.jscud.com/srun/news/viewhtml/3_2005_8/76.htm ,此處不在列出.

          (一) 先說FreeMarker方式.

          根據RSS的規范,得到模板如下:

          <?xml version="1.0" encoding="UTF-8" ?>
           <rss version="2.0">
           <channel>
            <title>JScud Develop</title>
            <link>http://www.jscud.com/</link>
            <language>zh-cn</language>
            <description >JScud Develop By Scud</description>
            <webMaster>xxx@21cn.com(scud)</webMaster>
            <lastBuildDate>${rssutil.formatRssDate(now)}</lastBuildDate>
             
             <#list newslist as onenews>
            <item>
             <title>${onenews.title?xml}</title>
             <link>http://www.jscud.com/srun/news/viewhtml/${onenews.htmlFilePath}/${onenews.nid}.htm</link>
             <pubDate>${rssutil.formatRssDate(onenews.addtime)}</pubDate>
             <description><![CDATA[
            ${rssutil.formatRssCData(onenews.showContent)}
             ]]>
             </description>
             </item>
           </#list>
            </channel>
           </rss>

          其中的網址和網站名稱可以根據自己的實際情況修改.

          我每次取出最新的20條文章來生成RSS,不過內容比較多,生成的RSS文件比較大,看到有的網站的description只是放了文章摘要的內容,這樣文件就小多了.總之是根據自己的需求設計吧.

          其中用到的RssUtil函數庫的函數如下(日期的函數參考上一篇文章):

              /**
               * 把]]>替換為]]&gt;
               * @param content 內容
               * @return 格式化后的內容
               */
              public static String formatRssCData(String content)
              {
                  String result = StringFunc.replace(content,"\\]\\]>","]]&gt;");
                 
                  return result;
              }
             
              /**
               * 格式化為xml需要的字符串
               * @param field 內容
               * @return 格式化后的串
               */
              public static String formatString2XML(String field)
              {
                  return StringFunc.str2TextXML(field);
              }
             
              public static String getNowDateTime()
              {
                  return formatRssDate(DateTime.getNowTimestamp());
              }

          利用FreeMarker生成靜態文件的代碼如下:

           private Configuration freemarker_cfg = null;
           
              protected Configuration getFreeMarkerCFG()
              {
                  if (null == freemarker_cfg)
                  {
                      // Initialize the FreeMarker configuration;
                      // - Create a configuration instance
                      freemarker_cfg = new Configuration();

                      freemarker_cfg.setClassForTemplateLoading(this.getClass(), "/htmlskin");

                      freemarker_cfg.setDefaultEncoding("GBK");
                  }

                  return freemarker_cfg;
              }

              public boolean geneFileByFreeMarker(String templateFileName, Map propMap, String filePath,
                              String fileName, String encode)
              {
                  try
                  {
                      Template t = getFreeMarkerCFG().getTemplate(templateFileName);

                      File afile = new File(filePath + "/" + fileName);

                      Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(afile),
                                      encode));

                      propMap.put("baseurl", PropSet.getStringProp("url.root"));

                      t.process(propMap, out);
                  }
                  catch (TemplateException e)
                  {
                      LogMan.error("Error while processing FreeMarker template " + templateFileName, e);
                      return false;
                  }
                  catch (IOException e)
                  {
                      LogMan.error("Error while generate File " + fileName, e);
                      return false;
                  }

                  return true;
              }


          新聞系統中調用重新生成RSS文件的代碼如下:

              /**
               * 重新生成RSS文件.
               *
               * @param nid 更新的新聞的id,如果不包含在最新的新聞里,則不更新RSS.nid <1則更新
               *
               * @return 是否成功
               */
              private boolean renewRSS(int nid)
              {
                  List newsList = 裝載新聞的代碼

                  boolean shouldUpdate = false;
                  if (nid > 0)
                  {
                      for (int i = 0; i < newsList.size(); i++)
                      {
                          NewsItem aNews = (NewsItem) newsList.get(i);
                          if (aNews.getNid() == nid)
                          {
                              shouldUpdate = true;
                              break;
                          }
                      }
                  }
                  else
                  {
                      shouldUpdate = true;
                  }

                  //不更新,則返回
                  if (!shouldUpdate)
                  {
                      return true;
                  }

                  Map root = new HashMap();
                 
                  root.put("rssutil",new RSSUtil());

                  root.put("newslist", newsList);
                 
                  root.put("now",DateTime.getNowTimestamp());

                  geneFileByFreeMarker("/news/rss.ftl", root, PropSet.getStringProp("rss.rssdir"), PropSet
                                  .getStringProp("rss.rssfile"), "UTF-8");

                  return true;
              }



          在增加或者更新/刪除新聞的地方需要調用這個renewRSS函數.

          (二)JSP動態方式

          相對靜態方式而言,簡單的多,不過效率上可能就不太好了.

          webwork2的Action代碼如下:

                  newsList = 裝載新聞代碼
                  return SUCCESS; 


          視圖Jsp如下:


          <%@ page contentType="text/xml; charset=UTF-8"%>
          <%@ taglib uri="jscud" prefix="jscud" %>
          <%@ taglib uri="webwork" prefix="ww" %>
          <ww:bean name="’com.jscud.www.util.RSSUtil’" id="rssUtil" />
          <?xml version="1.0" encoding="UTF-8" ?>
           <rss version="2.0">
           <channel>
            <title>JScud Develop</title>
            <link>http://www.jscud.com/</link>
            <language>zh-cn</language>
            <description >JScud Develop By Scud</description>
            <webMaster>xxx@21cn.com(scud)</webMaster>
            <lastBuildDate><ww:property value="#rssUtil.nowDateTime" /></lastBuildDate>
             
             <ww:iterator value="newsList">
            <item>
             <title><ww:property value="#rssUtil.formatString2XML(title)"/></title>
             <link>http://www.jscud.com/srun/news/viewhtml/<ww:property  value="htmlFilePath" />/<ww:property  value="nid" />.htm</link>
             <pubDate><ww:property  value="#rssUtil.formatRssDate(addtime)" /></pubDate>
             <description><![CDATA[
            <ww:property value="#rssUtil.formatRssCData(showContent)"/>
             ]]>
             </description>
             </item>
           </ww:iterator>
            </channel>
           </rss>

          jsp的方式簡單多了,上面的jsp里面還演示了ww:bean的使用 :)


          上面的類里面引用了很多其他的工具類,這里不一一列出,可以自己實現它們,都是很簡單的類. :)

          posted on 2005-08-19 14:11 Scud(飛云小俠) 閱讀(1128) 評論(0)  編輯  收藏 所屬分類: Java

          <2005年8月>
          31123456
          78910111213
          14151617181920
          21222324252627
          28293031123
          45678910

          導航

          統計

          公告

          文章發布許可
          創造共用協議:署名,非商業,保持一致

          我的郵件
          cnscud # gmail


          常用鏈接

          留言簿(15)

          隨筆分類(113)

          隨筆檔案(103)

          相冊

          友情鏈接

          技術網站

          搜索

          積分與排名

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 开鲁县| 东山县| 临武县| 象山县| 朔州市| 青州市| 长岛县| 海林市| 建德市| 尚志市| 高阳县| 罗城| 马边| 赤壁市| 营口市| 牡丹江市| 库尔勒市| 观塘区| 永仁县| 上犹县| 松潘县| 新竹县| 内江市| 无锡市| 南丹县| 辽宁省| 理塘县| 桐梓县| 阿勒泰市| 平乡县| 商河县| 宜都市| 文昌市| 册亨县| 雅江县| 阳西县| 华安县| 固安县| 舟曲县| 寻甸| 平武县|