Java理论与实践:在没有数据库的情形下举行数据库查询[Java编程]
本文“Java理论与实践:在没有数据库的情形下举行数据库查询[Java编程]”是由七道奇为您精心收集,来源于网络转载,文章版权归文章作者所有,本站不对其观点以及内容做任何评价,请读者自行判断,以下是其具体内容:
我近来细心观察了一个项目,该项目触及相当多的 Web 快速搜索.当爬虫程 序爬过差别的 Web 站点时,它将成立一个数据库,该数据库中包含它所爬过的 站点和网页、每一页所包含的链接、每一页的解析后果等数据.终究后果是一组 报告,具体阐明经过了哪些站点和页面、哪些是一向链接的、哪些链接已经断开 、哪些页面有错误、计算出的页面规格,等等.开始的时刻,没人切当知道需求 什么样的报告,大概该当采取什么样的格局 —— 只知道有一些内容要报告.这 表明报告开辟阶段会是一个反复的阶段,要经过多次反馈、改正,并且大概尝试 利用差别的构造.惟一肯定的报告要求是,报告该当以 XML 情势展示,也大概 以 HTML 情势展示.因此,开辟和改正报告的历程必须是轻量级的,因为报告要 求是“动态发现”的,而不是预先指定的.
不需求数据库
对这个问题的“最显而易见的”办理办法是将全部东西都放入 SQL 数据库中 —— 页面、链接、器量尺度、HTTP 后果代码、计时后果和其他元数据.这个问 题可以借助关系表示来很好地办理,分外是因为这种办法不需求存储已拜候页面 的内容,只需求存储它们的构造和元数据.
到目前为止,这个项目看起来像是一个典型的数据库利用程序,并且它并不 贫乏可供挑选的长期性战略.但是,大概可以避免利用数据库长期存储数据的复 杂性 —— 这个快速搜索工具(crawler)只拜候数万个页面.这个数字不是很 大,因此可以将整个数据库放在内存中,当需求长期存储数据时,可以通过序列 化来实现它.(是的,加载和保存操作要耗费较长的时间,但是这些操作并不经 常履行.)怠惰反而带来了一个好处 —— 不需求处理长期性极大地缩短了开辟 利用程序的时间,因而明显地削减了开辟工作量.构建和操作内存中的数据构造 要比每次增添、提取大概解析数据时都利用数据库简单得多.不管挑选了哪类持 久存储模子,城市限制任何触及到数据的代码的构造.
内存中的数据构造是一种树型构造,如清单 1 所示,它的根是快速搜索过的 各个网站的主页,因此 Visitor 情势是搜索这些主页大概从中提取数据的抱负 情势.(构建一个避免陷入链接循环 —— A 链接到 B、B 链接到 C、C 链接到 A —— 的基本 Visitor 类并非很难.)
清单 1. Web 爬行器的一个简化筹划
public class Site {
Page homepage;
Collection<Page> pages;
Collection<Link> links;
}
public class Page {
String url;
Site site;
PageMetrics metrics;
}
public class Link {
Page linkFrom;
Page linkTo;
String anchorText;
}
这个快速搜索工具的利用程序中有十多个 Visitor,它们所做的事情近似于 挑选页面做进一步解析、挑选不带链接的页面、列出“被链接最多”的页面,等 等.因为全部这些操作都很简单,所以 Visitor 情势(如清单 2 所示)可以工 作得很好,由于数据构造可以放到内存中,因此就算举行完好搜索,耗费也不是 很大:
清单 2. 用于 Web 快速搜索工具数据库的 Visitor 情势
public interface Visitor {
public void visitSite(Site site);
public void visitLink(Link link);
}
噢,忘掉报告了
假如不运行报告的话,Visitor 战略在拜候数据方面会做得非常好.利用数 据库举行长期存储的一个好处是:在生成报告时,SQL 的本领就会大放光彩 — — 几近可以让数据库做任何事情.乃至用 SQL 生成报告原型也很简单 —— 运 行原型报告,假如后果不是所需求的后果,那么可以改正 SQL 查询大概编写新 的查询,然后再试一试.假如改变的只是 SQL 查询的话,那么这个编辑-编译- 运行周期大概很快.假如 SQL 不是存储在程序中,那么您乃至可以跳过这个周 期的编译部份,这样可以快速生成报告的原型.肯定所需求的报告后,将它们构 建到利用程序中就很简单了.
因此,固然关于增添新后果、探求特定的后果和举行特别传输来说,内存中 的数据构造都表现得很不错,但是关于报告来说,这些变成了不利条件.关于所 有其自身构造与数据库构造差别的报告,Visitor 都必须成立一个全新的数据结 构,以包含报告数据.因此,每一种报告范例都需求有自己的、特定于报告的中 间数据构造来存放后果,还需求一个用来填充中间数据构造的拜候者,以及用来 将中间数据构造转换成终究报告的后处理(post-processing)代码.仿佛需求 做很多工作,特别在大大都原型报告将被丢弃时.比方,假定您想要列出全部从 其他网站链接到某个给定网站的页面的报告、全部外部页面的列表报告,以及站 点上链接该页面的那些页面的列表,然后,按照链接的数目对报告举行归类,链 接最多的页面显示在最前面.这个筹划基本上将数据构造从里到外翻了个个儿. 为了用 Visitor 实现这种数据转换,需求得到从某个给定网站可以到达的外部 页面链接的列表,并按照被链接的页面对它们举行分类,如清单 3 所示:
清单 3. Visitor 列出被链接最多的页面,以及链接到它们的页面
public class InvertLinksVisitor {
public Map<Page, Set<Page>> map = ...;
public void visitLink(Link link) {
if (link.linkFrom.site.equals(targetSite)
&& !link.linkTo.site.equals(targetSite)) {
if (!map.containsKey(link.linkTo))
map.put(link.linkTo, new HashSet<Page> ());
map.get(link.linkTo).add(link.linkFrom);
}
}
}
清单 3 中的 Visitor 生成一个映射,将每一个外部页面与链接它的一组内 部页面相关联.为了预备该报告,还必须按照关联页面的大小对这些条目举行分 类,然后成立报告.固然没有任何艰难步骤,但是每一个报告需求的特定于报告 的代码数目却很多,因此快速报告原型就成为一个重要的目标(因为没有提出报 告要求),试验新报告的开销比抱负情形更高.很多报告需求多次传送数据,以 便对数据举行挑选、汇总和分类.
以上是“Java理论与实践:在没有数据库的情形下举行数据库查询[Java编程]”的内容,如果你对以上该文章内容感兴趣,你可以看看七道奇为您推荐以下文章:
本文地址: | 与您的QQ/BBS好友分享! |