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
- GXT之旅:第四章:Data与Components(3)——Server端的持久化(1)
- GXT之旅:第四章:Data与Components(3)——Server端的持久化(2)
- GXT之旅:第四章:Data与Components(1)——ModelData
- GXT之旅:第四章:Data与Components(4)——远程数据(remote data)
- GXT之旅:第四章:Data与Components(2)——Stroes
- GXT之旅:第四章:Data与Components(5)——Grid
- GXT之旅:第四章:Data与Components(6)——GridCellRenderer
- GXT之旅:第五章:高级Components(2)——Grid的高级应用
- GXT之旅:第五章:高级Components(1)——Trees和TreeGrid(1)
- GXT之旅:第五章:高级Components(3)——Paging
- GXT之旅:第五章:高级Components(1)——Trees和TreeGrid(2)
- GXT之旅:第七章:MVC——标准的MVC与GXT MVC
- GXT之旅:第五章:高级Components(4)——Menus
- GXT之旅:第五章:高级Components(5)——ToolBar
- GXT之旅:第五章:高级Components(6)——TabPanel,Status大概介绍
- GXT之旅:第三章:表单和窗口(1)——POJO在client和server之间的共享
- GXT之旅:第二章:GXT组件(4)——容器的布局
- GXT之旅:第七章:MVC——GXT MVC的相关类
- [技术分享]用户密码安全存储建议
- error C2784处理方法
- 旋转的星星(优化版)
- scrum review meeting
- BW中使用abap
- GXT之旅:第四章:Data与Components(3)——Server端的持久化(1)
- 苹果推送通知服务(APNs)编程
- rsync 服务器架设方法 v0.1b
- 为什么你应该(从现在开始就)写博客?
- 批处理备份oracle
- jQuery首页轮播效果
- 基于JSON的全站式网站设计(Javascript/Web/NoSQL)
- Linux下Sed命令的用法
- Linux系统调用列表