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函數庫的函數如下(日期的函數參考上一篇文章):
/** * 把]]>替換為]]> * @param content 內容 * @return 格式化後的內容 */ public static String formatRssCData(String content) { String result = StringFunc.replace(content,"//]//]>","]]>"); 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的使用
上面的類裡面引用了很多其他的工具類,這裡不一一列出,可以自己實現它們,都是很簡單的類.