GXT之旅:第四章:Data与Components(3)——Server端的持久化(1)

来源:互联网 发布:net和java哪个容易学 编辑:程序博客网 时间:2024/05/16 02:36

小妹大年初四上班,发博啦害羞害羞害羞害羞可怜可怜可怜可怜

Server端的持久化

到目前为止,在RSSReader项目里,还没有任何持久化的操作。为了让我们项目更具有真实性,现在我们要添加持久化的代码。但是为了让我们更专注于client-side,持久化的逻辑仅仅是最基本的操作——实现真实的持久化逻辑之前先加入持久化的接口,这样就可以为了需要,可以在不改变接口调用的基础上,改用另外一种持久化操作的内容既可(比如hibernate)。

目前,实现最初的持久化版本,步骤如下:

  • 当添加新的feed实体时候,在server-side使用xml文件来存储。
  • xml文件只有一个,我们会在这个文件里维护feed的列表。

持久化的代码不属于GXT的犯愁,因此我们可以把他以一个黑盒对待。在我们RSSReader项目里,要加入Persistence接口和实现此接口的FilePersistence类,他们的功能就是负责存储和获得RSS feed信息的。


持久化一个存在的Feed

在第二章,我们新建一个Link feed button,目的是用来从internet里导入一个已经存在的RSS feed网络地址。接下来我们要在FeedService接口里,定义addExistingFeed方法,用作持久层存储RSS feed的URL地址。此功能要被绑定到LinkFeedPopup的add button上。

  • 在FeedService接口里,定义addExistingFeed方法,当然要传入一个URL 参数

void addExistingFeed(String feedUrl);

  • 同样的会在FeedServiceAsync接口里,定义与之相关的异步回调方法

void addExistingFeed(String feedUrl, AsyncCallback<Void>callback);

  • 修改LinkFeedPopup的addFeed方法,加入addExistingFeed回调方法的调用,具体逻辑一看便知

public void addFeed(final String feedUrl) {final FeedServiceAsync feedService = Registry.get(RSSReaderConstants.FEED_SERVICE);feedService.addExistingFeed(feedUrl, new AsyncCallback<Void>() {@Overridepublic void onFailure(Throwable caught) {Info.display("RSS Reader", "Failed to add feed at: " + feedUrl);}@Overridepublic void onSuccess(Void result) {tfUrl.clear();Info.display("RSS Reader", "Feed at " + feedUrl+ " added successfully");hide();}});}


  • FeedServiceImpl类里,我们要加入日志,这里用简单的java.util.logging.Logger

private final static Logger LOGGER = Logger.getLogger(FeedServiceImpl.class.getName());

  • 在FeedServiceImpl类里,加入private的方法loadFeed,用来根据feed的URL,在JDOM规范下,从internet里获得RSS的XML内容,返回Feed实体bean

private Feed loadFeed(String feedUrl) {Feed feed = new Feed(feedUrl);try {SAXBuilder parser = new SAXBuilder();Document document = parser.build(new URL(feedUrl));Element eleRoot = document.getRootElement();Element eleChannel = eleRoot.getChild("channel");feed.setTitle(eleChannel.getChildText("title"));feed.setDescription(eleChannel.getChildText("description"));feed.setLink(eleChannel.getChildText("link"));return feed;} catch (IOException e) {LOGGER.log(Level.SEVERE, "IO Error loading feed", e);return feed;} catch (JDOMException e) {LOGGER.log(Level.SEVERE, "Error parsing feed", e);return feed;}}

  • 在FeedServiceImpl类里,加入HashMap的属性,用来存储Feed对象

private Map<String, Feed> feeds = new HashMap<String, Feed>();

  • 我们目前的持久化功能是依赖与jdom-1.1.2.jar包功能的实现,具体的持久化代码如下,全部贴出来
持久化的配置文件:rssreader.properties(放在src\下)feed.file=feeds.txtdata.folder=database.url=http://127.0.0.1:8888


package com.danielvaughan.rssreader.server.utils;import java.util.Set;import org.jdom.Document;public interface Persistence {public Set<String> loadFeedList();public void saveFeedList(Set<String> feedUrls);public void saveFeedXml(String uuid, Document document);public String getUrl(String uuid);}

package com.danielvaughan.rssreader.server.utils;import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.DataInputStream;import java.io.File;import java.io.FileInputStream;import java.io.FileWriter;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.util.HashSet;import java.util.Properties;import java.util.Set;import java.util.logging.Logger;import org.jdom.Document;import org.jdom.output.Format;import org.jdom.output.XMLOutputter;public class FilePersistence implements Persistence {private final static Logger LOGGER = Logger.getLogger(FilePersistence.class.getName());private String dataFolder;private String feedFilePath;private String baseUrl;private final Properties properties = new Properties();public FilePersistence() {// Read properties file.try {ClassLoader loader = ClassLoader.getSystemClassLoader();InputStream in = loader.getResourceAsStream("rssreader.properties");properties.load(in);dataFolder = (String) properties.get("data.folder");String feedFile = (String) properties.get("feed.file");feedFilePath = dataFolder + "\\" + feedFile;baseUrl = (String) properties.get("base.url");initDataFolder();} catch (IOException e) {LOGGER.severe("Unable to load properties file");}}private void initDataFolder() {try {File dataFolderFile = new File(dataFolder);if (!dataFolderFile.exists()) {dataFolderFile.mkdir();}File feedFile = new File(feedFilePath);if (!feedFile.exists()) {feedFile.createNewFile();}} catch (IOException e) {LOGGER.severe("Error initialising data folder");}}@Overridepublic void saveFeedList(Set<String> feedUrls) {try {FileWriter fileWriter = new FileWriter(feedFilePath);BufferedWriter out = new BufferedWriter(fileWriter);for (String feedUrl : feedUrls) {String line = feedUrl.concat("\n");out.write(line);}out.close();} catch (Exception e) {LOGGER.severe("Error: " + e.getMessage());}}@Overridepublic Set<String> loadFeedList() {Set<String> feedUrls = new HashSet<String>();try {FileInputStream fstream = new FileInputStream(feedFilePath);DataInputStream in = new DataInputStream(fstream);BufferedReader br = new BufferedReader(new InputStreamReader(in));String strLine;while ((strLine = br.readLine()) != null) {feedUrls.add(strLine);}in.close();return feedUrls;} catch (Exception e) {LOGGER.severe("Error: " + e.getMessage());return feedUrls;}}@Overridepublic void saveFeedXml(String feedId, Document document) {try {File file = new File(generateFilePath(feedId));XMLOutputter serializer = new XMLOutputter();Format prettyFormat = Format.getPrettyFormat();serializer.setFormat(prettyFormat);FileWriter writer = new FileWriter(file);serializer.output(document, writer);writer.close();} catch (IOException e) {LOGGER.severe("Error: " + e.getMessage());}}private String generateFilePath(String feedId) {return dataFolder + "/" + feedId + ".xml";}@Overridepublic String getUrl(String feedId) {String fileName = generateFilePath(feedId);return baseUrl + "/" + fileName;}}


  • 最后在FeedServiceImpl类里,实现addExistingFeed方法,调用刚才创建的loadFeed方法,根据feedUrl返回Feed对象,再调用上面持久化类的saveFeedList方法,完成持久化操作

@Overridepublic void addExistingFeed(String feedUrl) {Feed loadResult = loadFeed(feedUrl);if (loadResult.getTitle() != null) {feeds.put(feedUrl, loadFeed(feedUrl));persistence.saveFeedList(feeds.keySet());}}

  • 创建本地的RSS xml文件用来读取:http://127.0.0.1:8888/rss2sample.xml。在WebContent\下创建rss2sample.xml,内容如下:
<?xml version="1.0"?><rss version="2.0">   <channel>      <title>Liftoff News</title>      <link>http://liftoff.msfc.nasa.gov/</link>      <description>Liftoff to Space Exploration.</description>      <language>en-us</language>      <pubDate>Tue, 10 Jun 2003 04:00:00 GMT</pubDate>      <lastBuildDate>Tue, 10 Jun 2003 09:41:01 GMT</lastBuildDate>      <docs>http://blogs.law.harvard.edu/tech/rss</docs>      <generator>Weblog Editor 2.0</generator>      <managingEditor>editor@example.com</managingEditor>      <webMaster>webmaster@example.com</webMaster>      <item>         <title>Star City</title>         <link>http://liftoff.msfc.nasa.gov/news/2003/news-starcity.asp</link>         <description>How do Americans get ready to work with Russians aboard the International Space Station? They take a crash course in culture, language and protocol at Russia's <a href="http://howe.iki.rssi.ru/GCTC/gctc_e.htm">Star City</a>.</description>         <pubDate>Tue, 03 Jun 2003 09:39:21 GMT</pubDate>         <guid>http://liftoff.msfc.nasa.gov/2003/06/03.html#item573</guid>      </item>      <item>         <description>Sky watchers in Europe, Asia, and parts of Alaska and Canada will experience a <a href="http://science.nasa.gov/headlines/y2003/30may_solareclipse.htm">partial eclipse of the Sun</a> on Saturday, May 31st.</description>         <pubDate>Fri, 30 May 2003 11:06:42 GMT</pubDate>         <guid>http://liftoff.msfc.nasa.gov/2003/05/30.html#item572</guid>      </item>      <item>         <title>The Engine That Does More</title>         <link>http://liftoff.msfc.nasa.gov/news/2003/news-VASIMR.asp</link>         <description>Before man travels to Mars, NASA hopes to design new engines that will let us fly through the Solar System more quickly.  The proposed VASIMR engine would do that.</description>         <pubDate>Tue, 27 May 2003 08:37:32 GMT</pubDate>         <guid>http://liftoff.msfc.nasa.gov/2003/05/27.html#item571</guid>      </item>      <item>         <title>Astronauts' Dirty Laundry</title>         <link>http://liftoff.msfc.nasa.gov/news/2003/news-laundry.asp</link>         <description>Compared to earlier spacecraft, the International Space Station has many luxuries, but laundry facilities are not one of them.  Instead, astronauts have other options.</description>         <pubDate>Tue, 20 May 2003 08:56:02 GMT</pubDate>         <guid>http://liftoff.msfc.nasa.gov/2003/05/20.html#item570</guid>      </item>   </channel></rss>



  • 运行程序,会读取rssreader.properties配置文件初始化持久化的配置。当你通过Link feed button 成功添加一个真实的URL link(http://127.0.0.1:8888/rss2sample.xml)的时候,会在项目WebContent\data\feeds.txt文件里存储一行内容http://127.0.0.1:8888/rss2sample.xml