<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    coolfiry

    認認真真做人,兢兢業業做事!
    posts - 39, comments - 17, trackbacks - 0, articles - 0

    周 登朋 (zhoudengpeng@yahoo.com.cn), 軟件工程師, 上海交通大學

    2006 年 9 月 06 日?

    在本篇文章中,你會學習到如何利用 Lucene 實現高級搜索功能以及如何利用 Lucene 來創建 Web 搜索應用程序。通過這些學習,你就可以利用 Lucene 來創建自己的搜索應用程序。

    架構概覽

    通常一個 Web 搜索引擎的架構分為前端和后端兩部分,就像圖一中 所示。在前端流程中,用戶在搜索引擎提供的界面中輸入要搜索的關鍵詞,這里提到的用戶界面一般是一個帶有輸入框的 Web 頁面,然后應用程序將搜索的關鍵詞解析成搜索引擎可以理解的形式,并在索引文件上進行搜索操作。在排序后,搜索引擎返回搜索結果給用戶。在后端流程中,網 絡爬蟲或者機器人從因特網上獲取 Web 頁面,然后索引子系統解析這些 Web 頁面并存入索引文件中。如果你想利用 Lucene 來創建一個 Web 搜索應用程序,那么它的架構也和上面所描述的類似,就如圖一中所示。


    Figure 1. Web 搜索引擎架構
    Web搜索引擎架構

    利用 Lucene 實現高級搜索

    Lucene 支持多種形式的高級搜索,我們在這一部分中會進行探討,然后我會使用 Lucene 的 API 來演示如何實現這些高級搜索功能。

    布爾操作符

    大多數的搜索引擎都會提供布爾操作符讓用戶可以組合查詢,典型的布爾操作符有 AND, OR, NOT。Lucene 支持 5 種布爾操作符,分別是 AND, OR, NOT, 加(+), 減(-)。接下來我會講述每個操作符的用法。

    • OR: 如果你要搜索含有字符 A 或者 B 的文檔,那么就需要使用 OR 操作符。需要記住的是,如果你只是簡單的用空格將兩個關鍵詞分割開,其實在搜索的時候搜索引擎會自動在兩個關鍵詞之間加上 OR 操作符。例如,“Java OR Lucene” 和 “Java Lucene” 都是搜索含有 Java 或者含有 Lucene 的文檔。
    • AND: 如果你需要搜索包含一個以上關鍵詞的文檔,那么就需要使用 AND 操作符。例如,“Java AND Lucene” 返回所有既包含 Java 又包含 Lucene 的文檔。
    • NOT: Not 操作符使得包含緊跟在 NOT 后面的關鍵詞的文檔不會被返回。例如,如果你想搜索所有含有 Java 但不含有 Lucene 的文檔,你可以使用查詢語句 “Java NOT Lucene”。但是你不能只對一個搜索詞使用這個操作符,比如,查詢語句 “NOT Java” 不會返回任何結果。
    • 加號(+): 這個操作符的作用和 AND 差不多,但它只對緊跟著它的一個搜索詞起作用。例如,如果你想搜索一定包含 Java,但不一定包含 Lucene 的文檔,就可以使用查詢語句“+Java Lucene”。
    • 減號(-): 這個操作符的功能和 NOT 一樣,查詢語句 “Java -Lucene” 返回所有包含 Java 但不包含 Lucene 的文檔。

    接下來我們看一下如何利用 Lucene 提供的 API 來實現布爾查詢。清單1 顯示了如果利用布爾操作符進行查詢的過程。


    清單1:使用布爾操作符

    ?? // Test?boolean?operator
    public ? void ?testOperator(String?indexDirectory)? throws ?Exception {
    ???Directory?dir?
    = ?FSDirectory.getDirectory(indexDirectory, false );
    ???IndexSearcher?indexSearcher?
    = ? new ?IndexSearcher(dir);
    ???String[]?searchWords?
    = ? { " Java?AND?Lucene " ,? " Java?NOT?Lucene " ,? " Java?OR?Lucene " ,?
    ????????????????????
    " +Java?+Lucene " ,? " +Java?-Lucene " }
    ;
    ???Analyzer?language?
    = ? new ?StandardAnalyzer();
    ???Query?query;
    ???
    for ( int ?i? = ? 0 ;?i? < ?searchWords.length;?i ++ ) {
    ??????query?
    = ?QueryParser.parse(searchWords[i],? " title " ,?language);
    ??????Hits?results?
    = ?indexSearcher.search(query);
    ??????System.out.println(results.length()?
    + ? " search?results?for?query? " ? + ?searchWords[i]);
    ???}

    }


    域搜索(Field Search)

    Lucene 支持域搜索,你可以指定一次查詢是在哪些域(Field)上進行。例如,如果索引的文檔包含兩個域,TitleContent,你就可以使用查詢 “Title: Lucene AND Content: Java” 來返回所有在 Title 域上包含 Lucene 并且在 Content 域上包含 Java 的文檔。清單 2 顯示了如何利用 Lucene 的 API 來實現域搜索。


    清單2:實現域搜索

    // Test?field?search
    public ? void ?testFieldSearch(String?indexDirectory)? throws ?Exception {
    ????Directory?dir?
    = ?FSDirectory.getDirectory(indexDirectory, false );
    ????IndexSearcher?indexSearcher?
    = ? new ?IndexSearcher(dir);
    ????String?searchWords?
    = ? " title:Lucene?AND?content:Java " ;
    ????Analyzer?language?
    = ? new ?StandardAnalyzer();
    ????Query?query?
    = ?QueryParser.parse(searchWords,? " title " ,?language);
    ????Hits?results?
    = ?indexSearcher.search(query);
    ????System.out.println(results.length()?
    + ? " search?results?for?query? " ? + ?searchWords);
    }


    通配符搜索(Wildcard Search)

    Lucene 支持兩種通配符:問號(?)和星號(*)。你可以使用問號(?)來進行單字符的通配符查詢,或者利用星號(*)進行多字符的通配符查詢。例如,如果你想搜 索 tiny 或者 tony,你就可以使用查詢語句 “t?ny”;如果你想查詢 Teach, Teacher 和 Teaching,你就可以使用查詢語句 “Teach*”。清單3 顯示了通配符查詢的過程。


    清單3:進行通配符查詢

    // Test?wildcard?search
    public ? void ?testWildcardSearch(String?indexDirectory) throws ?Exception {
    ???Directory?dir?
    = ?FSDirectory.getDirectory(indexDirectory, false );
    ???IndexSearcher?indexSearcher?
    = ? new ?IndexSearcher(dir);
    ???String[]?searchWords?
    = ? { " tex* " ,? " tex? " ,? " ?ex* " } ;
    ???Query?query;
    ???
    for ( int ?i? = ? 0 ;?i? < ?searchWords.length;?i ++ ) {
    ??????query?
    = ? new ?WildcardQuery( new ?Term( " title " ,searchWords[i]));
    ??????Hits?results?
    = ?indexSearcher.search(query);
    ??????System.out.println(results.length()?
    + ? " search?results?for?query? " ? + ?searchWords[i]);
    ???}

    }


    模糊查詢

    Lucene 提供的模糊查詢基于編輯距離算法(Edit distance algorithm)。你可以在搜索詞的尾部加上字符 ~ 來進行模糊查詢。例如,查詢語句 “think~” 返回所有包含和 think 類似的關鍵詞的文檔。清單 4 顯示了如果利用 Lucene 的 API 進行模糊查詢的代碼。


    清單4:實現模糊查詢

    // Test?fuzzy?search
    public ? void ?testFuzzySearch(String?indexDirectory) throws ?Exception {
    ???Directory?dir?
    = ?FSDirectory.getDirectory(indexDirectory, false );
    ???IndexSearcher?indexSearcher?
    = ? new ?IndexSearcher(dir);
    ???String[]?searchWords?
    = ? { " text " ,? " funny " } ;
    ???Query?query;
    ???
    for ( int ?i? = ? 0 ;?i? < ?searchWords.length;?i ++ ) {
    ??????query?
    = ? new ?FuzzyQuery( new ?Term( " title " ,searchWords[i]));
    ??????Hits?results?
    = ?indexSearcher.search(query);
    ??????System.out.println(results.length()?
    + ? " search?results?for?query? " ? + ?searchWords[i]);
    ???}

    }


    范圍搜索(Range Search)

    范圍搜索匹配某個域上的值在一定范圍的文檔。例如,查詢 “age:[18 TO 35]” 返回所有 age 域上的值在 18 到 35 之間的文檔。清單5顯示了利用 Lucene 的 API 進行返回搜索的過程。


    清單5:測試范圍搜索

    // Test?range?search
    public ? void ?testRangeSearch(String?indexDirectory) throws ?Exception {
    ????Directory?dir?
    = ?FSDirectory.getDirectory(indexDirectory, false );
    ????IndexSearcher?indexSearcher?
    = ? new ?IndexSearcher(dir);
    ????Term?begin?
    = ? new ?Term( " birthDay " , " 20000101 " );
    ????Term?end???
    = ? new ?Term( " birthDay " , " 20060606 " );
    ????Query?query?
    = ? new ?RangeQuery(begin,end, true );
    ????Hits?results?
    = ?indexSearcher.search(query);
    ????System.out.println(results.length()?
    + ? " search?results?is?returned " );
    }


    在 Web 應用程序中集成 Lucene

    接下來我們開發一個 Web 應用程序利用 Lucene 來檢索存放在文件服務器上的 HTML 文檔。在開始之前,需要準備如下環境:

    1. Eclipse 集成開發環境
    2. Tomcat 5.0
    3. Lucene Library
    4. JDK 1.5

    這個例子使用 Eclipse 進行 Web 應用程序的開發,最終這個 Web 應用程序跑在 Tomcat 5.0 上面。在準備好開發所必需的環境之后,我們接下來進行 Web 應用程序的開發。

    1、創建一個動態 Web 項目

    1. 在 Eclipse 里面,選擇 File > New > Project,然后再彈出的窗口中選擇動態 Web 項目,如圖二所示。


    圖二:創建動態Web項目
    創建動態Web項目

    1. 在創建好動態 Web 項目之后,你會看到創建好的項目的結構,如圖三所示,項目的名稱為 sample.dw.paper.lucene。


    圖三:動態 Web 項目的結構
    動態 Web 項目的結構

    2. 設計 Web 項目的架構

    在我們的設計中,把該系統分成如下四個子系統:

    1. 用戶接口: 這個子系統提供用戶界面使用戶可以向 Web 應用程序服務器提交搜索請求,然后搜索結果通過用戶接口來顯示出來。我們用一個名為 search.jsp 的頁面來實現該子系統。
    2. 請求管理器: 這個子系統管理從客戶端發送過來的搜索請求并把搜索請求分發到搜索子系統中。最后搜索結果從搜索子系統返回并最終發送到用戶接口子系統。我們使用一個 Servlet 來實現這個子系統。
    3. 搜索子系統: 這個子系統負責在索引文件上進行搜索并把搜索結構傳遞給請求管理器。我們使用 Lucene 提供的 API 來實現該子系統。
    4. 索引子系統: 這個子系統用來為 HTML 頁面來創建索引。我們使用 Lucene 的 API 以及 Lucene 提供的一個 HTML 解析器來創建該子系統。

    圖4 顯示了我們設計的詳細信息,我們將用戶接口子系統放到 webContent 目錄下面。你會看到一個名為 search.jsp 的頁面在這個文件夾里面。請求管理子系統在包 sample.dw.paper.lucene.servlet 下面,類 SearchController 負責功能的實現。搜索子系統放在包 sample.dw.paper.lucene.search 當中,它包含了兩個類,SearchManagerSearchResultBean,第一個類用來實現搜索功能,第二個類用來描述搜索結果的結構。索引子系統放在包 sample.dw.paper.lucene.index 當中。類 IndexManager 負責為 HTML 文件創建索引。該子系統利用包 sample.dw.paper.lucene.util 里面的類 HTMLDocParser 提供的方法 getTitlegetContent 來對 HTML 頁面進行解析。


    圖四:項目的架構設計
    項目的架構設計

    3. 子系統的實現

    在分析了系統的架構設計之后,我們接下來看系統實現的詳細信息。

    1. 用戶接口: 這個子系統有一個名為 search.jsp 的 JSP 文件來實現,這個 JSP 頁面包含兩個部分。第一部分提供了一個用戶接口去向 Web 應用程序服務器提交搜索請求,如圖5所示。注意到這里的搜索請求發送到了一個名為 SearchController 的 Servlet 上面。Servlet 的名字和具體實現的類的對應關系在 web.xml 里面指定。


    圖5:向Web服務器提交搜索請求
    向Web服務器提交搜索請求

    這個JSP的第二部分負責顯示搜索結果給用戶,如圖6所示:


    圖6:顯示搜索結果
    顯示搜索結果

    1. 請求管理器: 一個名為 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 會被調用。最后搜索結果被返回到客戶端。

    1. 搜索子系統: 在這個子系統中,我們定義了兩個類:SearchManagerSearchResultBean。第一個類用來實現搜索功能,第二個類是個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 中,含有兩個屬性,分別是 htmlPathhtmlTitle,以及這個兩個屬性的 get 和 set 方法。這也意味著我們的搜索結果包含兩個屬性:htmlPathhtmlTitle,其中 htmlPath 代表了 HTML 文件的路徑,htmlTitle 代表了 HTML 文件的標題。

    1. 索引子系統: 類 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;
    ????}


    }


    這個類包含兩個私有屬性,分別是 dataDirindexDirdataDir 代表存放等待進行索引的 HTML 頁面的路徑,indexDir 代表了存放 Lucene 索引文件的路徑。類 IndexManager 提供了三個方法,分別是 createIndex, addDocumentifIndexExist。如果索引不存在的話,你可以使用方法 createIndex 去創建一個新的索引,用方法 addDocument 去向一個索引上添加文檔。在我們的場景中,一個文檔就是一個 HTML 頁面。方法 addDocument 會調用由類 HTMLDocParser 提供的方法對 HTML 文檔進行解析。你可以使用最后一個方法 ifIndexExist 來判斷 Lucene 的索引是否已經存在。

    現在我們來看一下放在包 sample.dw.paper.lucene.util 里面的類 HTMLDocParser。這個類用來從 HTML 文件中提取出文本信息。這個類包含三個方法,分別是 getContentgetTitlegetPath。第一個方法返回去除了 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 上運行開發好的應用程序。

    1. 右鍵單擊 search.jsp,然后選擇 Run as > Run on Server,如圖7所示。


    圖7:配置 Tomcat 5.0
    配置 Tomcat 5.0

    1. 在彈出的窗口中,選擇 Tomcat v5.0 Server 作為目標 Web 應用程序服務器,然后點擊 Next,如圖8 所示:


    圖8:選擇 Tomcat 5.0
    選擇 Tomcat 5.0

    1. 現在需要指定用來運行 Web 應用程序的 Apache Tomcat 5.0 以及 JRE 的路徑。這里你所選擇的 JRE 的版本必須和你用來編譯 Java 文件的 JRE 的版本一致。配置好之后,點擊 Finish。如 圖9 所示。


    圖9:完成Tomcat 5.0的配置
    完成Tomcat 5.0的配置

    1. 配置好之后,Tomcat 會自動運行,并且會對 search.jsp 進行編譯并顯示給用戶。如 圖10 所示。


    圖10:用戶界面
    用戶界面

    1. 在輸入框中輸入關鍵詞 “information” 然后單擊 Search 按鈕。然后這個頁面上會顯示出搜索結果來,如 圖11 所示。


    圖11:搜索結果
    搜索結果

    1. 單擊搜索結果的第一個鏈接,頁面上就會顯示出所鏈接到的頁面的內容。如 圖12 所示.


    圖12:詳細信息
    詳細信息

    現在我們已經成功的完成了示例項目的開發,并成功的用Lucene實現了搜索和索引功能。你可以下載這個項目的源代碼。

    總結

    Lucene 提供了靈活的接口使我們更加方便的設計我們的 Web 搜索應用程序。如果你想在你的應用程序中加入搜索功能,那么 Lucene 是一個很好的選擇。在設計你的下一個帶有搜索功能的應用程序的時候可以考慮使用 Lucene 來提供搜索功能。

    下載

    描述 名字 大小 下載方法
    Lucene Web 應用程序示例 wa-lucene2_source_code.zip 504KB HTTP


    Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1215172

    Feedback

    # re: 用 Lucene 加速 Web 搜索應用程序的開發  回復  更多評論   

    2011-07-27 15:59 by johnhsr
    源碼下載 發布 查詢的時候 輸入information也不報錯 是怎么回事 數據源 和索引庫需要數據源里面有東西嗎

    只有注冊用戶登錄后才能發表評論。


    網站導航:
     
    主站蜘蛛池模板: 欧洲精品成人免费视频在线观看| 亚洲无线码在线一区观看| 13小箩利洗澡无码视频网站免费| 亚洲AV无码一区二区三区在线| 国产亚洲精久久久久久无码AV| 欧洲美熟女乱又伦免费视频 | 国产精品另类激情久久久免费| 免费A级毛片在线播放| 中文字幕av免费专区| 亚洲人成电影网站色www| 亚洲黄色网站视频| 亚洲精品少妇30p| 狠狠色婷婷狠狠狠亚洲综合 | 亚洲中文字幕无码久久| 久久精品a亚洲国产v高清不卡| 国产亚洲3p无码一区二区| 久久99亚洲综合精品首页| 亚洲第一区精品日韩在线播放| 国产无遮挡又黄又爽免费视频 | 亚洲经典千人经典日产| 亚洲日日做天天做日日谢| fc2免费人成在线视频| 亚洲一本一道一区二区三区| 亚洲国产精品成人精品软件| 亚洲视频一区二区三区| 亚洲视频在线观看地址| 亚洲视频精品在线观看| 久久精品亚洲精品国产色婷| 666精品国产精品亚洲| 亚洲精品福利网站| 亚洲人成网网址在线看| 亚洲一区二区三区在线| 亚洲中文无码av永久| 亚洲最大的成人网站| 国产AV旡码专区亚洲AV苍井空| 亚洲熟妇AV乱码在线观看| 亚洲精品无码专区在线播放| 最新亚洲人成网站在线观看 | 国产精品成人无码免费| 免费日韩在线视频| 亚洲午夜av影院|