1.1 30分鐘實現的搜索引擎
首先從一個簡單的搜索引擎入手,實現一個簡單的指定目錄文件的搜索引擎。實現之前需要讀者具有Java開發方面的基礎知識。
1.1.1 準備工作環境(10分鐘)
首先要準備一個Java的開發環境。當前可以使用JDK 1.6。JDK 1.6可以從Sun的官方網站java.sun.com下載得到。使用默認方式安裝即可。
然后要使用的是一個用來管理搜索引擎索引庫的jar包,叫做Lucene。目前可以從http://lucene.apache.org/java/docs/index.html下載到最新的Lucene,當前的版本是2.3。另外,使用集成開發環境Eclipse,其開發界面如圖1-1所示。

圖1-1 Java開發界面
如果需要用Web界面搜索,還要下載Tomcat,當前可以從http://tomcat.apache.org/下載到,推薦使用Tomcat 5.5以上的版本。
然后增加Tomcat的內存使用量,防止內存溢出。
如果是在Linux下,可以用vi編輯器修改./catalina.sh文件,增加行:
JAVA_OPTS=-Xmx600m
如果是在Windows下,可以用文本編輯器“記事本”修改./catalina.bat文件,增加行:
set JAVA_OPTS=-Xmx600m
【作者提示】如果不增加內存使用量,運行時可能會出現java.lang.OutOfMemoryError異常。
1.1.2 編寫代碼(15分鐘)
搜索引擎的基礎在于對全文索引庫的管理,在Lucene中,通過IndexWriter來寫入索引庫。偽代碼如下:
1.創建IndexWriter,準備寫索引;
2.遍歷要索引的路徑;
3.優化索引。
下面是主要的實現代碼:
public void go() throws Exception { long start = System.currentTimeMillis(); if (verbose) { System.out.println("Creating index in: " + indexDir); //創建索引目錄或者建立增量索引 if (incremental) System.out.println("- using incremental mode"); } Index = new IndexWriter(new File(indexDir), new StandardAnalyzer(), !incremental);//打開或創建索引庫,indexDir是索引存放的路徑 File dir = new File(sSourceDir);//待索引的文件存放的路徑 indexDir(dir);//索引路徑 index.optimize();//索引優化 index.close();//關閉索引庫 if(verbose) System.out.println("index complete in :"+(System. currentTime Millis() - start)/1000); }
下面這段代碼把文件內容加到索引庫:
private void indexFile(File item) { if (verbose) System.out.println("Adding FILE: " + item); News news = loadFile(item);//把文件中的內容加載到news對象 if ( news!= null && news.body != null) { Document doc = new Document(); //創建網址列 Field f = new Field("url", news.URL , Field.Store.YES, Field.Index.UN_TOKENIZED, Field.TermVector.NO); doc.add(f); //創建標題列 f = new Field("title", news.title , Field.Store.YES, Field.Index.TOKENIZED, Field.TermVector.WITH_POSITIONS_OFFSETS); doc.add(f); //創建內容列 f = new Field("body", news.body.toString() , Field.Store.YES, Field.Index.TOKENIZED, Field.TermVector.WITH_POSITIONS_OFFSETS); doc.add(f); try{ //文檔增加到索引庫 index.addDocument(doc); } catch(Exception e) { e.printStackTrace(); System.exit(-1); } } }
完整的代碼可以在本書附帶的光盤中找到。
運行以后,一般會生成以下三個索引文件:
● _0.cfs
● segments.gen
● segments_2
其中任何索引庫都會包括的一個文件是:segments.gen。可以通過判斷一個路徑下是否包括這個文件來判斷一個路徑下是否已經存在Lucene索引。
1.1.3 發布運行(5分鐘)
把搜索頁面index.jsp放到Tomcat中。
<% if (!query.equals("")) { %> <jsp:useBean id="search" class="com.bitmechanic.spindle.Search" scope="application"> <!-- Specify the directory that stores our Lucene index created by the spindle spider --> <% search.init("d:/index"); %> </jsp:useBean> <jsp:setProperty name="search" property="query"/> <list:init name="customers" listCreator="search" max="10"> <hr> <list:hasResults> <list:iterate> <TABLE width="65%"> <TR> <TD> <a href="<list:iterateProp property="url"/>"> <B><FONT style="FONT-SIZE: 14px"><list: iterateProp property="title"/></FONT></B></a> <FONT size=-1 color=#6f6f6f> (<list:iterateProp property="source"/>) <list:iterateProp property="accessDate"/></FONT> </TD> </TR> <TR> <TD> <FONT size=-1><list:iterateProp property="desc"/></FONT> </TD> </TR> </TABLE> </list:iterate> <pg:pager url="/index.jsp" items="<%=Integer.parseInt(listSize)%>" maxPageItems="10" maxIndexPages="10" export="currentPageNumber=pageNumber" scope="request"> <pg:param name="query" value="<%=query%>"/> <pg:index export="totalItems=itemCount"> <pg:page export="firstItem, lastItem"> <div class="resultInfo"> 當前顯示結果 <strong><%= firstItem %>-<%= lastItem %></strong> 找 到相關文檔 <strong><%=listSize%></strong> 篇 </div> </pg:page> <div class="rnav"> <table border=0 cellpadding=0 width=1% cellspacing=0 align= center><tr align=center valign=top> <td valign=bottom nowrap><font size=-1>結果頁碼: <pg:first unless="current"> <td nowrap><a href="<%= pageUrl %>" class="rnavLink"> <nobr>首頁</nobr></a> </pg:first> <pg:prev export="pageUrl"> <td nowrap><a href="<%= pageUrl %>" class="rnavLink">&# 171; 上一頁</a> </pg:prev> <pg:pages><% if (pageNumber.intValue() < 10) { %> <% } if (pageNumber == currentPageNumber) { %><b><%= pageNumber %></b><% } else { %><td nowrap> <a href="<%= pageUrl %>"><%= pageNumber %></a> <% } %> </pg:pages> <pg:next export="pageUrl"> <td nowrap><a href="<%= pageUrl %>" class= "rnavLink">下一頁 »</a> </pg:next> <pg:last unless="current"> <td nowrap><a href="<%= pageUrl %>" class= "rnavLink"><nobr>末頁</nobr></a> </pg:last> </table> </div> </pg:index> </pg:pager> </list:hasResults> <list:hasNoResults> 對不起,沒有結果返回。<p>建議你換用更少的文字查詢以擴大搜索范圍。 </list:hasNoResults> </list:init> <% } %>
需要使用Tomcat的版本為5.5.X或6.0。為了讓Tomcat支持中文,要修改server.xml文件。設置值URIEncoding:
<Connector port="8080" maxThreads="150" minSpareThreads="25" maxSpareThreads="75" enableLookups="false" redirectPort="8443" acceptCount="100" debug="0" connectionTimeout="20000" disableUploadTimeout="true" URIEncoding="UTF-8" useBodyEncodingForURI= "true" />
同時修改WEB-INF目錄下的web.xml文件,設置Filter:
<filter> <filter-name>Set Character Encoding</filter-name> <filter-class>filters.SetCharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>utf-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>Set Character Encoding</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
本節通過使用Lucene實現了一個可以在互聯網上發布的搜索引擎,而世界上最大的互聯網搜索引擎來自Google。
- Mastering NetBeans
- 數據結構(C語言)
- 微服務從小白到專家:Spring Cloud和Kubernetes實戰
- MongoDB,Express,Angular,and Node.js Fundamentals
- HTML5秘籍(第2版)
- Unity 3D/2D移動開發實戰教程
- Learning Material Design
- OpenCV with Python Blueprints
- Java Web應用開發給力起飛
- Appcelerator Titanium:Patterns and Best Practices
- 你好!Python
- 基于JavaScript的WebGIS開發
- 趣學數據結構
- Instant AppFog
- Learning Android Application Development