在 Web 应用程序中集成 Lucene
接下来我们开发一个 Web 应用程序利用 Lucene 来检索存放在文件服务器上的 HTML 文档。在开始之前,需要准备如下环境:
- Eclipse 集成开发环境
- Tomcat 5.0
- Lucene Library
- JDK 1.5
这个例子使用 Eclipse 进行 Web 应用程序的开发,最终这个 Web 应用程序跑在 Tomcat 5.0 上面。在准备好开发所必需的环境之后,我们接下来进行 Web 应用程序的开发。
1、创建一个动态 Web 项目
- 在 Eclipse 里面,选择 File > New > Project,然后再弹出的窗口中选择动态 Web 项目,如图二所示。
创建动态Web项目
- 在创建好动态 Web 项目之后,你会看到创建好的项目的结构,如图三所示,项目的名称为 sample.dw.paper.lucene。
图三:动态 Web 项目的结构2. 设计 Web 项目的架构
在我们的设计中,把该系统分成如下四个子系统:
-
用户接口: 这个子系统提供用户界面使用户可以向 Web 应用程序服务器提交搜索请求,然后搜索结果通过用户接口来显示出来。我们用一个名为 search.jsp 的页面来实现该子系统。
-
请求管理器: 这个子系统管理从客户端发送过来的搜索请求并把搜索请求分发到搜索子系统中。最后搜索结果从搜索子系统返回并最终发送到用户接口子系统。我们使用一个 Servlet 来实现这个子系统。
-
搜索子系统: 这个子系统负责在索引文件上进行搜索并把搜索结构传递给请求管理器。我们使用 Lucene 提供的 API 来实现该子系统。
-
索引子系统: 这个子系统用来为 HTML 页面来创建索引。我们使用 Lucene 的 API 以及 Lucene 提供的一个 HTML 解析器来创建该子系统。
图4 显示了我们设计的详细信息,我们将用户接口子系统放到 webContent 目录下面。你会看到一个名为 search.jsp 的页面在这个文件夹里面。请求管理子系统在包 sample.dw.paper.lucene.servlet
下面,类 SearchController
负责功能的实现。搜索子系统放在包 sample.dw.paper.lucene.search
当中,它包含了两个类,SearchManager
和 SearchResultBean
,第一个类用来实现搜索功能,第二个类用来描述搜索结果的结构。索引子系统放在包 sample.dw.paper.lucene.index
当中。类 IndexManager
负责为 HTML 文件创建索引。该子系统利用包 sample.dw.paper.lucene.util
里面的类 HTMLDocParser
提供的方法 getTitle
和 getContent
来对 HTML 页面进行解析。
图四:项目的架构设计3. 子系统的实现
在分析了系统的架构设计之后,我们接下来看系统实现的详细信息。
-
用户接口: 这个子系统有一个名为 search.jsp 的 JSP 文件来实现,这个 JSP 页面包含两个部分。第一部分提供了一个用户接口去向 Web 应用程序服务器提交搜索请求,如图5所示。注意到这里的搜索请求发送到了一个名为 SearchController 的 Servlet 上面。Servlet 的名字和具体实现的类的对应关系在 web.xml 里面指定。
图5:向Web服务器提交搜索请求这个JSP的第二部分负责显示搜索结果给用户,如图6所示:
图6:显示搜索结果
-
请求管理器: 一个名为
SearchController
的 servlet 用来实现该子系统。清单6给出了这个类的源代码。
清单6:请求管理器的实现
package sample.dw.paper.lucene.servlet;
import java.io.IOException;
import java.util.List;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import sample.dw.paper.lucene.search.SearchManager;
/**
* This servlet is used to deal with the search request
* and return the search results to the client
*/
public class SearchController extends HttpServlet{
private static final long serialVersionUID = 1L;
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException{
String searchWord = request.getParameter("searchWord");
SearchManager searchManager = new SearchManager(searchWord);
List searchResult = null;
searchResult = searchManager.search();
RequestDispatcher dispatcher = request.getRequestDispatcher("search.jsp");
request.setAttribute("searchResult",searchResult);
dispatcher.forward(request, response);
}
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException{
doPost(request, response);
}
}
|
在清单6中,doPost
方法从客户端获取搜索词并创建类 SearchManager
的一个实例,其中类 SearchManager
在搜索子系统中进行了定义。然后,SearchManager
的方法 search 会被调用。最后搜索结果被返回到客户端。
-
搜索子系统: 在这个子系统中,我们定义了两个类:
SearchManager
和 SearchResultBean
。第一个类用来实现搜索功能,第二个类是个JavaBean,用来描述搜索结果的结构。清单7给出了类 SearchManager
的源代码。
清单7:搜索功能的实现
package sample.dw.paper.lucene.search;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.Hits;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import sample.dw.paper.lucene.index.IndexManager;
/**
* This class is used to search the
* Lucene index and return search results
*/
public class SearchManager {
private String searchWord;
private IndexManager indexManager;
private Analyzer analyzer;
public SearchManager(String searchWord){
this.searchWord = searchWord;
this.indexManager = new IndexManager();
this.analyzer = new StandardAnalyzer();
}
/**
* do search
*/
public List search(){
List searchResult = new ArrayList();
if(false == indexManager.ifIndexExist()){
try {
if(false == indexManager.createIndex()){
return searchResult;
}
} catch (IOException e) {
e.printStackTrace();
return searchResult;
}
}
IndexSearcher indexSearcher = null;
try{
indexSearcher = new IndexSearcher(indexManager.getIndexDir());
}catch(IOException ioe){
ioe.printStackTrace();
}
QueryParser queryParser = new QueryParser("content",analyzer);
Query query = null;
try {
query = queryParser.parse(searchWord);
} catch (ParseException e) {
e.printStackTrace();
}
if(null != query >> null != indexSearcher){
try {
Hits hits = indexSearcher.search(query);
for(int i = 0; i < hits.length(); i ++){
SearchResultBean resultBean = new SearchResultBean();
resultBean.setHtmlPath(hits.doc(i).get("path"));
resultBean.setHtmlTitle(hits.doc(i).get("title"));
searchResult.add(resultBean);
}
} catch (IOException e) {
e.printStackTrace();
}
}
return searchResult;
}
}
|
在清单7中,注意到在这个类里面有三个私有属性。第一个是 searchWord
,代表了来自客户端的搜索词。第二个是 indexManager
,代表了在索引子系统中定义的类 IndexManager
的一个实例。第三个是 analyzer
,代表了用来解析搜索词的解析器。现在我们把注意力放在方法 search
上面。这个方法首先检查索引文件是否已经存在,如果已经存在,那么就在已经存在的索引上进行检索,如果不存在,那么首先调用类 IndexManager
提供的方法来创建索引,然后在新创建的索引上进行检索。搜索结果返回后,这个方法从搜索结果中提取出需要的属性并为每个搜索结果生成类 SearchResultBean
的一个实例。最后这些 SearchResultBean
的实例被放到一个列表里面并返回给请求管理器。
在类 SearchResultBean
中,含有两个属性,分别是 htmlPath
和 htmlTitle
,以及这个两个属性的 get 和 set 方法。这也意味着我们的搜索结果包含两个属性:htmlPath
和 htmlTitle
,其中 htmlPath
代表了 HTML 文件的路径,htmlTitle
代表了 HTML 文件的标题。
-
索引子系统: 类
IndexManager
用来实现这个子系统。清单8 给出了这个类的源代码。
清单8:索引子系统的实现
package sample.dw.paper.lucene.index;
import java.io.File;
import java.io.IOException;
import java.io.Reader;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import sample.dw.paper.lucene.util.HTMLDocParser;
/**
* This class is used to create an index for HTML files
*
*/
public class IndexManager {
//the directory that stores HTML files
private final String dataDir = "c:\\dataDir";
//the directory that is used to store a Lucene index
private final String indexDir = "c:\\indexDir";
/**
* create index
*/
public boolean createIndex() throws IOException{
if(true == ifIndexExist()){
return true;
}
File dir = new File(dataDir);
if(!dir.exists()){
return false;
}
File[] htmls = dir.listFiles();
Directory fsDirectory = FSDirectory.getDirectory(indexDir, true);
Analyzer analyzer = new StandardAnalyzer();
IndexWriter indexWriter = new IndexWriter(fsDirectory, analyzer, true);
for(int i = 0; i < htmls.length; i++){
String htmlPath = htmls[i].getAbsolutePath();
if(htmlPath.endsWith(".html") || htmlPath.endsWith(".htm")){
addDocument(htmlPath, indexWriter);
}
}
indexWriter.optimize();
indexWriter.close();
return true;
}
/**
* Add one document to the Lucene index
*/
public void addDocument(String htmlPath, IndexWriter indexWriter){
HTMLDocParser htmlParser = new HTMLDocParser(htmlPath);
String path = htmlParser.getPath();
String title = htmlParser.getTitle();
Reader content = htmlParser.getContent();
Document document = new Document();
document.add(new Field("path",path,Field.Store.YES,Field.Index.NO));
document.add(new Field("title",title,Field.Store.YES,Field.Index.TOKENIZED));
document.add(new Field("content",content));
try {
indexWriter.addDocument(document);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* judge if the index exists already
*/
public boolean ifIndexExist(){
File directory = new File(indexDir);
if(0 < directory.listFiles().length){
return true;
}else{
return false;
}
}
public String getDataDir(){
return this.dataDir;
}
public String getIndexDir(){
return this.indexDir;
}
}
|
这个类包含两个私有属性,分别是 dataDir
和 indexDir
。dataDir
代表存放等待进行索引的 HTML 页面的路径,indexDir
代表了存放 Lucene 索引文件的路径。类 IndexManager
提供了三个方法,分别是 createIndex
, addDocument
和 ifIndexExist
。如果索引不存在的话,你可以使用方法 createIndex
去创建一个新的索引,用方法 addDocument
去向一个索引上添加文档。在我们的场景中,一个文档就是一个 HTML 页面。方法 addDocument
会调用由类 HTMLDocParser
提供的方法对 HTML 文档进行解析。你可以使用最后一个方法 ifIndexExist
来判断 Lucene 的索引是否已经存在。
现在我们来看一下放在包 sample.dw.paper.lucene.util
里面的类 HTMLDocParser
。这个类用来从 HTML 文件中提取出文本信息。这个类包含三个方法,分别是 getContent
,getTitle
和 getPath
。第一个方法返回去除了 HTML 标记的文本内容,第二个方法返回 HTML 文件的标题,最后一个方法返回 HTML 文件的路径。清单9 给出了这个类的源代码。
清单9:HTML 解析器
package sample.dw.paper.lucene.util;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import org.apache.lucene.demo.html.HTMLParser;
public class HTMLDocParser {
private String htmlPath;
private HTMLParser htmlParser;
public HTMLDocParser(String htmlPath){
this.htmlPath = htmlPath;
initHtmlParser();
}
private void initHtmlParser(){
InputStream inputStream = null;
try {
inputStream = new FileInputStream(htmlPath);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
if(null != inputStream){
try {
htmlParser = new HTMLParser(new InputStreamReader(inputStream, "utf-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
}
public String getTitle(){
if(null != htmlParser){
try {
return htmlParser.getTitle();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return "";
}
public Reader getContent(){
if(null != htmlParser){
try {
return htmlParser.getReader();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
public String getPath(){
return this.htmlPath;
}
}
|
5.在 Tomcat 5.0 上运行应用程序
现在我们可以在 Tomcat 5.0 上运行开发好的应用程序。
- 右键单击 search.jsp,然后选择 Run as > Run on Server,如图7所示。
图7:配置 Tomcat 5.0
- 在弹出的窗口中,选择 Tomcat v5.0 Server 作为目标 Web 应用程序服务器,然后点击 Next,如图8 所示:
图8:选择 Tomcat 5.0
- 现在需要指定用来运行 Web 应用程序的 Apache Tomcat 5.0 以及 JRE 的路径。这里你所选择的 JRE 的版本必须和你用来编译 Java 文件的 JRE 的版本一致。配置好之后,点击 Finish。如 图9 所示。
图9:完成Tomcat 5.0的配置
- 配置好之后,Tomcat 会自动运行,并且会对 search.jsp 进行编译并显示给用户。如 图10 所示。
图10:用户界面
- 在输入框中输入关键词 “information” 然后单击 Search 按钮。然后这个页面上会显示出搜索结果来,如 图11 所示。
图11:搜索结果
- 单击搜索结果的第一个链接,页面上就会显示出所链接到的页面的内容。如 图12 所示.
图12:详细信息现在我们已经成功的完成了示例项目的开发,并成功的用Lucene实现了搜索和索引功能。你可以下载这个项目的源代码(下载)。
总结
Lucene 提供了灵活的接口使我们更加方便的设计我们的 Web 搜索应用程序。如果你想在你的应用程序中加入搜索功能,那么 Lucene 是一个很好的选择。在设计你的下一个带有搜索功能的应用程序的时候可以考虑使用 Lucene 来提供搜索功能。
分享到:
相关推荐
在现代Web应用开发中,Spring MVC作为主流的Java Web框架,常常被用来构建高效、可扩展的后端系统。而Lucene是Apache软件基金会的一个开放源代码全文搜索引擎库,能够帮助开发者实现强大的搜索功能。本篇文章将深入...
这通常意味着我们将有机会看到如何在Web应用中集成Lucene,以及如何编写和运行代码来构建和执行搜索查询。 **标签关键词:** "用 Lucene 加速 Web 搜索应用程序的开发" 重复了标题,进一步强调了这次讨论的核心内容...
在Web环境下,Lucene可以集成到Web应用程序中,为用户提供动态、实时的搜索体验。 “lucene_web”项目是Lucene与Web服务器的结合,它通过Servlet或者Spring MVC等Web开发框架来接收用户请求,处理搜索查询,并返回...
WebLucene是一款开源的、基于Java开发的...理解并掌握这些步骤,你就能顺利地在你的Web应用中集成这个强大的全文搜索引擎。在实际使用过程中,可能会遇到各种问题,查阅官方文档和社区资源通常能帮助你找到解决方案。
在IT行业中,SSH(Struts2、Spring、Hibernate)是一个常见的企业级应用开发框架组合,用于构建高效、可扩展的Web应用程序。在这个“ssh集成Lucene4.7demo”项目中,开发者将SSH框架与Lucene 4.7版本的全文搜索引擎...
在这个“Lucene WEB搜索程序”项目中,我们将探讨如何使用Java和Lucene来构建一个简单的Web应用程序,实现对网页内容的检索。 **一、Lucene简介** Lucene最初由Doug Cutting创建,现在是Apache软件基金会的一个顶级...
2. **Web应用集成**:在Web环境中使用Lucene,通常意味着将Lucene的索引和搜索功能集成到一个Web应用程序中,如基于Servlet或Spring Boot的应用。这可能涉及到在HTTP请求处理中构建查询、解析用户输入、执行搜索、...
SpringMVC是Spring框架的一个模块,专门用于构建Web应用程序。它遵循Model-View-Controller(MVC)设计模式,将业务逻辑、数据和用户界面分离。SpringMVC通过DispatcherServlet接收请求,通过HandlerMapping找到对应...
在现代Web应用程序中,强大的全文搜索引擎功能是不可或缺的,而Apache Lucene正是这样一个高效的、可扩展的开源全文检索库。在这个SpringBoot+Lucene的Demo中,我们将深入探讨如何在Spring Boot框架下集成Lucene,并...
在Struts中集成Lucene,可以通过控制器(Controller)接收用户的查询请求,调用Lucene的搜索模块执行检索操作,最后由视图(View)呈现搜索结果。这种架构下,模型(Model)负责管理索引和文档数据,控制器负责处理...
在这个场景中,它可能被用来增强网站或Web应用程序的搜索体验。 描述中提到的博文链接指向了一位名为“01jiangwei01”的作者在iteye博客上发表的文章。虽然具体的博文内容无法在当前环境中获取,但通常这样的文章会...
1. **Web应用程序集成**:将Lucene与Java Servlets、Spring、Struts等Web框架结合,构建搜索引擎功能。 2. **RESTful API**:创建一个基于HTTP的接口,允许通过JSON或XML交换数据,使得其他Web服务或客户端可以与...
2. **创建索引**:在应用程序启动时,初始化索引写入器,将数据源中的信息转换为 Lucene 文档,并添加到索引中。 3. **索引更新**:当数据源有新增、修改或删除操作时,同步更新 Lucene 索引。 4. **实现搜索接口*...
Lucene的设计允许开发者轻松集成全文检索功能到各种应用程序中,或以此为基础构建更复杂的信息检索系统。 #### 二、Lucene工作原理与关键组件 ##### 1. 索引构建 索引构建是Lucene的核心操作之一,涉及将原始文档...
Doug Cutting 创建 Lucene 的初衷是为了简化在各种中小型应用程序中实现全文检索的难度。起初,Lucene 在 Doug 的个人网站上发布,后来移至 SourceForge,并最终在 2001 年底成为 Apache 基金会 Jakarta 项目的一...
Struts是一种经典的MVC(模型-视图-控制器)框架,用于构建Java Web应用程序,而Lucene则是一个强大的全文搜索引擎库,常用于实现网站的高效检索功能。 首先,Apache Struts是Java企业级开发中的一个关键组件,它...
Java的跨平台特性使其成为构建Web应用程序的理想选择。 3. **Web搜索界面**:由于标签提到了“lucene__web”,我们可以推断系统有一个Web界面,用户可以通过浏览器进行公交信息的搜索。 4. **公交数据处理**:系统...
Compass作为Lucene的一个高级封装,简化了在应用程序中集成搜索引擎的操作;而Ajax(Asynchronous JavaScript and XML)则通过异步通信提升了用户体验。本文将围绕这三个技术展开深入的探讨。 首先,我们来了解...
- **文档(Document)**:在Lucene中,文档是被搜索的基本单位,可以包含多个字段(Field),如标题、内容、作者等。 - **查询(Query)**:用户通过查询字符串发起搜索,Lucene支持多种查询语法,如布尔查询、...