通过最近两天的优化,已经解决了上次的全部Bug。
【新增模块及特性如下】:
1、手动输入URL,输入次数限制在5次(各自由更改)。
2、CheckURL类:判断URL是否有效。
3、CURD类:新增一次查询20条的功能。
4、Blog类:获取博客相关信息。
5、每次根据数据保存的文章数量,对插入的文章设置ID。
6、容错性能明显提高。
代码参考如下:
一 、判断输入的URL是否有效
/**
* 检查URL是否有效
* @author yyp
*
*/
public class CheckURL {
public static HttpURLConnection feedconn = null;
public static boolean isConnected(String URL_PATH){
if((URL_PATH!=null)&&(URL_PATH.length()>0)){
try {
URL url = new URL(URL_PATH);
feedconn = (HttpURLConnection) url.openConnection();
feedconn.setReadTimeout(3000);
feedconn.setDoInput(true);
feedconn.setRequestMethod("GET");
int responsecode = feedconn.getResponseCode();
if(responsecode==200){
return true;
}
}catch(Exception ex){
//ex.printStackTrace();
}
finally{
//手动选择关闭连接
}
}
return false;
}
}
二 、关于MongoDB数据库操作
1、连接MongoDB数据库(单例模式)。(参考上次代码,未做优化)
2、设计DAO层接口(新增一次查询20条的功能)
/**
* 基本操作接口
*
* @author yyp
*
*/
public interface DAO {
// 插入一条
public boolean add(String collectionName, Document doc);
// 删除一条
public boolean delete(String collectionName, Document doc);
// 查询全部
public FindIterable<Document> queryAll(String collectionName);
// 查询20条
public FindIterable<Document> queryTwenty(String collectionName);
// 查询一条
public FindIterable<Document> query(String collectionName, Document doc);
// 更新一条
public boolean update(String collectionName, Bson bson, Document newdoc);
}
3、实现CURD操作(增、改、查、删)。(实现一次查询20条的功能)
/**
* 实现CURD操作
*
* @author yyp
*
*/
public class CURD implements DAO {
public CURD() {
}
// 插入一条
@Override
public boolean add(String collectionName, Document doc) {
// TODO Auto-generated method stub
MongoDatabase mydb = MongoDBUtil.getDB();
mydb.getCollection(collectionName).insertOne(doc);
return false;
}
// 删除一条
@Override
public boolean delete(String collectionName, Document doc) {
// TODO Auto-generated method stub
MongoDatabase mydb = MongoDBUtil.getDB();
mydb.getCollection(collectionName).deleteMany(doc);
return false;
}
// 查询全部
@Override
public FindIterable<Document> queryAll(String collectionName) {
// TODO Auto-generated method stub
MongoDatabase mydb = MongoDBUtil.getDB();
// 找到表的数据项列表
FindIterable<Document> blogs = mydb.getCollection(collectionName).find();
return blogs;
}
//查询20条
@Override
public FindIterable<Document> queryTwenty(String collectionName) {
// TODO Auto-generated method stub
MongoDatabase mydb = MongoDBUtil.getDB();
// 找到表的数据项列表
FindIterable<Document> blogs = mydb.getCollection(collectionName).find().limit(20);
return blogs;
}
// 查询一条
@Override
public FindIterable<Document> query(String collectionName, Document doc) {
// TODO Auto-generated method stub
MongoDatabase mydb = MongoDBUtil.getDB();
// 找到表的数据项
FindIterable<Document> blogs = mydb.getCollection(collectionName).find(doc);
if (blogs != null) {
return blogs;
}
return null;
}
// 更新一条
@Override
public boolean update(String collectionName, Bson bson, Document newdoc) {
// TODO Auto-generated method stub
MongoDatabase mydb = MongoDBUtil.getDB();
// 找到表的数据项列表
mydb.getCollection(collectionName).replaceOne(bson, newdoc);
return false;
}
}
三 、Blog数据实体类
/**
* 博客实体类
* @author yyp
*
*/
public class Blog {
//private String id; //插入数据库时进行赋值
private String title;
private String author;
private String publishedDate;
private String content;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getPublishedDate() {
return publishedDate;
}
public void setPublishedDate(String publishedDate) {
this.publishedDate = publishedDate;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
四 、下载Feed源并逐条保存
/**
* 下载保存Feed
*
* @author yyp
*
* 下载的content可能只有一部分
*/
public class GetFeed {
private boolean isFinished = false; // 下载是否完成
int ID = 0;
public void download(String URL_PATH) {
if(CheckURL.isConnected(URL_PATH)){
try{
// 实例化feed输入流
SyndFeedInput input = new SyndFeedInput();
// 读取feed
XmlReader reader = new XmlReader(CheckURL.feedconn);
SyndFeed feed = input.build(reader);
// 获取entry数量
int entriesSize = feed.getEntries().size();
SyndEntry entry;
SyndContent content;
//SyndImage img;
for (int index = 0; index < entriesSize; index++) {
// 实例化entry
entry = new SyndEntryImpl();
// 获取第i个entry
entry = (SyndEntry) (feed.getEntries()).get(index);
//实例化content
content = new SyndContentImpl();
content = (SyndContent) entry.getContents().get(0);
//实例化img
//img = new SyndImageImpl();
//img = entry.getContents();
//获取blog数据
Blog blog = new Blog();
blog.setTitle(entry.getTitle().trim());
blog.setAuthor(entry.getAuthor().trim());
//设置日期格式
Format formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String date = (entry.getPublishedDate() != null ? formatter.format(entry.getPublishedDate())
: "");
blog.setPublishedDate(date.trim());
blog.setContent(content.getValue().trim());
//打印文章
/*System.out.println("----------------------");
System.out.println(blog.getTitle());
System.out.println(blog.getAuthor());
System.out.println(blog.getPublishedDate());
System.out.println(blog.getContent());
System.out.println("----------------------");*/
MongoDatabase mydb = MongoDBUtil.getDB();
//获取数据库保存的文章数量
long blogcount = mydb.getCollection("blogs").count();
//根据数据库的保存数量来设置ID
ID = (int)blogcount+1;
//当前文章与数据库的文章对比,不重复则插入
CURD curd = new CURD();
Document data = new Document();
MongoCollection<Document> collection = mydb.getCollection("blogs");
if(collection.count()==0){
System.out.println("正在同步第1篇......");
data.append("id", Integer.toString(ID))
.append("title", blog.getTitle().trim())
.append("author", blog.getAuthor().trim())
.append("publishedDate", blog.getPublishedDate().trim())
.append("content", blog.getContent().trim());
// 保存数据
curd.add("blogs",data);
}
else{
int count = 0; // 统计当前标题与数据库已有标题不重复的次数
FindIterable<Document> docs = curd.queryAll("blogs");
for(Document doc : docs){
if(!(blog.getTitle().equals(doc.get("title")))){
++count;
if(count==blogcount){
data.append("id", Integer.toString(ID))
.append("title", blog.getTitle().trim())
.append("author", blog.getAuthor().trim())
.append("publishedDate", blog.getPublishedDate().trim())
.append("content", blog.getContent().trim());
// 保存数据
curd.add("blogs",data);
System.out.println("正在同步第"+ID+"篇......");
}
}else{
++flag;
break;
}
}
}
}
isFinished = true;
}catch(Exception ex){
}
finally{
//同步完关闭连接
CheckURL.feedconn.disconnect();
}
}else {
System.out.println("请求失败!");
}
if (!isFinished) {
System.out.println("同步Feed失败!");
}else{
System.out.println("----------------");
System.out.println("同步Feed成功!");
}
}
}
五 、实现小功能的命令行操作
/**
* 命令行模式
* @author yyp
*
*/
public class Cmd {
private static String URL_PATH = ""; //http://www.ruanyifeng.com/blog/atom.xml
private static GetFeed getFeed = new GetFeed();
private static CURD curd = new CURD();
// 命令清单
public static void showHelp() {
System.out.println("------------------------------------");
System.out.println(
"sync \t\t同步Feed。\n"
+ "list \t\t列出最近的20篇文章。\n"
+ "show number \t查看文章ID为number的内容。\n"
+ "help \t\t显示全部命令。\n"
+ "quit \t\t退出命令行。");
System.out.println("------------------------------------");
}
// 列出最近的20篇文章
public static void list() {
MongoDatabase mydb = MongoDBUtil.getDB();
long blogcount = mydb.getCollection("blogs").count();
if(blogcount==0){
System.out.println("最新文章:0篇");
}else{
System.out.println("最新文章:"+blogcount+"篇");
System.out.println("--------------------------------------");
//对publidhedDate进行降序排序,把最近的文章排到最上面,方便一次性顺序输出
Document sortcode = new Document();
sortcode.put("publishedDate", -1);
MongoDatabase db = MongoDBUtil.getDB();
//System.out.println(db.getCollection("blogs").count());
db.getCollection("blogs").find().sort(sortcode);
// 只列20篇
FindIterable<Document> blogs = curd.queryTwenty("blogs");
blogs.forEach(new Block<Document>() {
@Override
public void apply(Document blog) {
// TODO Auto-generated method stub
System.out.println("标题:" + blog.get("title"));
System.out.print("作者:" + blog.get("author") + "\t");
System.out.println("发布时间:" + blog.get("publishedDate"));
System.out.println("内容:" + blog.get("content"));
System.out.println("--------------------------------------");
}
});
}
}
public static void main(String[] args) {
String cmd;
Scanner in = new Scanner(System.in);
//方便测试,每次开始先把数据全删除
curd.delete("blogs", new Document());
//手动输入网址,错误5次自动退出
System.out.print("请输入Feed源网址:");
URL_PATH = in.nextLine().trim();
if(CheckURL.isConnected(URL_PATH)){
System.out.println("网址有效!即将进入命令行模式...");
System.out.println();
//判断完网址,关闭连接
CheckURL.feedconn.disconnect();
}else{
int input_num = 5;
while(input_num>0){
if(CheckURL.isConnected(URL_PATH)){
System.out.println("网址有效!即将进入命令行模式...");
System.out.println();
//判断完网址,关闭连接
CheckURL.feedconn.disconnect();
break;
}
System.out.print("网址无效!请重新输入Feed源网址:");
URL_PATH = in.nextLine().trim();
--input_num;
if(input_num==0){
System.out.print("系统已经退出!");
System.exit(0);
}
}
}
System.out.print("User>");
// 会以空格为分割符,不建议使用
// cmd = in.next();
// 以enter键为分割键;删除命令首尾的空白,便于比较
cmd = in.nextLine().trim();
while (true) {
if (cmd.length() == 4) {
switch (cmd) {
case "sync":
getFeed.download(URL_PATH);
break;
case "list":
try {
list();
} catch (Exception e) {
e.printStackTrace();
}
break;
case "show":
System.out.println("请输入完整命令,如:show 32\n或者 输入help,查看全部命令");
break;
case "quit":
System.exit(0);
break;
case "help":
Cmd.showHelp();
break;
default:
break;
}
} else if (cmd.length() > 4 && cmd.substring(0, 4).equals("show")) {
String[] arr = cmd.split("\\s+");
Pattern pattern = Pattern.compile("[0-9]*");
// 判断命令的参数是否为数字字符串
if (arr.length == 2 && pattern.matcher(arr[1]).matches()) {
// 设置查询条件
Document querycode = new Document();
querycode.put("id", arr[1]);
// 查询一条
FindIterable<Document> blogs = curd.query("blogs", querycode);
Document blog = blogs.first();
if(blog!=null){
System.out.println("--------------------------------------");
System.out.println("标题:" + blog.get("title"));
System.out.print("作者:" + blog.get("author") + "\t");
System.out.println("发布时间:" + blog.get("publishedDate"));
System.out.println("内容:" + blog.get("content"));
System.out.println("--------------------------------------");
}else{
MongoDatabase mydb = MongoDBUtil.getDB();
long blogcount = mydb.getCollection("blogs").count();
System.out.println("温馨提示:只保存了"+blogcount+"篇文章!");
System.out.println("很抱歉!找不到相应编号的文章,请重新查找!");
}
} else {
System.out.println("命令格式错误!标准格式:show number(number必须是正整数)\n或者 输入help,查看全部命令");
}
} else {
System.out.println("请输入help,查看全部命令");
}
System.out.print("User>");
cmd = in.nextLine().trim();
}
}
}
至此,命令行模式的RSS阅读器已经完成。
有兴趣的话,再把它做成 ★Web前端★ 的模式,那就更漂亮了!!!