创建RSS XML
接下来,要把用户录入的feed内容保存起来。最合适的方式是,保存为RSS XML格式的文档。所以要在FeedService接口中新增一个方法saveFeed()方法。
我们需要使用JDOM 1.1库,操作feed对象,将其转换成XML格式。http://www.jdom.org/downloads/index.html下载jdom-1.1.2.jar包,放入工作空间里。
- 编辑FeedService接口,加入:
void saveFeed(Feed feed);
- GWT在Eclipse中会提示并自动在FeedServiceAsync接口里生成:
void saveFeed(Feed feed, AsyncCallback<Void> callback);
- 在FeedServiceImpl类中,实现saveFeed方法。
@Override
public void saveFeed(Feed feed) {
Element eleRoot = new Element("rss");
eleRoot.setAttribute(new Attribute("version", "2.0"));
// Create a document from the feed object
Document document = new Document(eleRoot);
Element eleChannel = new Element("channel");
Element eleTitle = new Element("title");
Element eleDescription = new Element("description");
Element eleLink = new Element("link");
eleTitle.setText(feed.getTitle());
eleDescription.setText(feed.getDescription());
eleLink.setText(feed.getLink());
eleChannel.addContent(eleTitle);
eleChannel.addContent(eleDescription);
eleChannel.addContent(eleLink);
eleRoot.addContent(eleChannel);
try {
XMLOutputter serializer = new XMLOutputter();
Format prettyFormat = Format.getPrettyFormat();
serializer.setFormat(prettyFormat);
System.out
.println("At this point we would serialize the feed "
+ feed.getTitle()
+ " to a file. For now we are just going to write it to the console.");
serializer.output(document, System.out);
} catch (IOException e) {
System.out.println("Error saving feed");
}
}
- 上面的代码,只是把feed数据,转换成document 。然后将document输出到控制台。
- 编辑FeedForm类的save方法。加入RPC的调用代码。
package com.danielvaughan.rssreader.client.forms;
import com.danielvaughan.rssreader.client.RSSReaderConstants;
import com.danielvaughan.rssreader.client.services.FeedServiceAsync;
import com.danielvaughan.rssreader.shared.model.Feed;
import com.extjs.gxt.ui.client.Registry;
import com.extjs.gxt.ui.client.widget.Info;
import com.extjs.gxt.ui.client.widget.form.FormPanel;
import com.extjs.gxt.ui.client.widget.form.TextArea;
import com.extjs.gxt.ui.client.widget.form.TextField;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.rpc.AsyncCallback;
public class FeedForm extends FormPanel {
private final TextField<String> tfTitle = new TextField<String>();
private final TextArea taDescription = new TextArea();
private final TextField<String> tfLink = new TextField<String>();
public FeedForm() {
setHeaderVisible(false);
}
@Override
protected void onRender(Element parent, int pos) {
super.onRender(parent, pos);
tfTitle.setFieldLabel("Title");
tfTitle.setAllowBlank(false);
tfTitle.getMessages().setBlankText("Title is required");
taDescription.setFieldLabel("Description");
taDescription.setAllowBlank(false);
taDescription.getMessages().setBlankText("Description is required");
tfLink.setFieldLabel("Link");
tfLink.setAllowBlank(false);
tfLink.setRegex("^http\\://[a-zA-Z0-9\\-\\.]+\\.[a-zA-Z]{2,3}(/\\S*)?{1}quot;);
tfLink.getMessages().setBlankText("Link is required");
tfLink.getMessages()
.setRegexText(
"The link field must be a URL e.g. http://www.example.com/rss.xml");
add(tfTitle);
add(taDescription);
add(tfLink);
}
public void save(final Feed feed) {
feed.setTitle(tfTitle.getValue());
feed.setDescription(taDescription.getValue());
feed.setLink(tfLink.getValue());
final FeedServiceAsync feedService = Registry
.get(RSSReaderConstants.FEED_SERVICE);
feedService.saveFeed(feed, new AsyncCallback<Void>() {
@Override
public void onFailure(Throwable caught) {
Info.display("RSS Reader",
"Failed to save feed: " + feed.getTitle());
}
@Override
public void onSuccess(Void result) {
Info.display("RSS Reader", "Feed " + feed.getTitle()
+ " saved sucessfully");
}
});
}
}
- 最后当用户录入数据后,提交到server端处理。就会在控制台显示如下格式的xml内容:
<rss version="2.0">
<channel>
<title>Example Feed</title>
<description>This is an example feed</description>
<link>http://www.example.com/</link>
</channel>
</rss>
优化LinkFeedPopup
还记得LinkFeedPopup窗口,用来提供用户输入URL的页面吗?现在要给他优化一下,加入validation的代码。
package com.danielvaughan.rssreader.client.components;
import com.extjs.gxt.ui.client.Style.LayoutRegion;
import com.extjs.gxt.ui.client.event.ButtonEvent;
import com.extjs.gxt.ui.client.event.ComponentEvent;
import com.extjs.gxt.ui.client.event.KeyListener;
import com.extjs.gxt.ui.client.event.SelectionListener;
import com.extjs.gxt.ui.client.util.Margins;
import com.extjs.gxt.ui.client.widget.Popup;
import com.extjs.gxt.ui.client.widget.Text;
import com.extjs.gxt.ui.client.widget.button.Button;
import com.extjs.gxt.ui.client.widget.form.TextField;
import com.extjs.gxt.ui.client.widget.layout.BorderLayout;
import com.extjs.gxt.ui.client.widget.layout.BorderLayoutData;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Window;
public class LinkFeedPopup extends Popup {
private final TextField<String> tfUrl = new TextField<String>();
public LinkFeedPopup() {
setSize(300, 55);
setBorders(true);
setShadow(true);
setAutoHide(false);
}
public void addFeed(String url) {
Window.alert("We would now attempt to add " + url + " at this point");
}
@Override
protected void onRender(Element parent, int pos) {
super.onRender(parent, pos);
final Text txtExplaination = new Text("Enter a feed url");
final Button btnAdd = new Button("add");
btnAdd.addSelectionListener(new SelectionListener<ButtonEvent>() {
public void componentSelected(ButtonEvent ce) {
if (tfUrl.isValid())
addFeed(tfUrl.getValue());
}
});
tfUrl.addKeyListener(new KeyListener() {
public void componentKeyDown(ComponentEvent event) {
if (event.getKeyCode() == KeyCodes.KEY_ENTER) {
addFeed(tfUrl.getValue());
}
}
});
tfUrl.setAllowBlank(false);
tfUrl.setRegex("^http\\://[a-zA-Z0-9\\-\\.]+\\.[a-zA-Z]{2,3}(/\\S*)?$");
tfUrl.setAllowBlank(false);
tfUrl.getMessages().setBlankText(
"Please enter the URL of an existing feed");
tfUrl.setAutoValidate(true);
tfUrl
.getMessages()
.setRegexText(
"The link field must be a URL e.g. http://www.example.com/rss.xml");
final BorderLayout layout = new BorderLayout();
setLayout(layout);
final BorderLayoutData northData = new BorderLayoutData(
LayoutRegion.NORTH, 20);
northData.setMargins(new Margins(2));
add(txtExplaination, northData);
final BorderLayoutData centerData = new BorderLayoutData(
LayoutRegion.CENTER);
centerData.setMargins(new Margins(2));
add(tfUrl, centerData);
final BorderLayoutData eastData = new BorderLayoutData(
LayoutRegion.EAST, 50);
eastData.setMargins(new Margins(2, 2, 2, 20));
add(btnAdd, eastData);
}
}