您的位置:首页 > 编程语言 > PHP开发

PHP中通过 JavaBridge+Lucene实现全文搜索站内搜索

2012-03-21 12:02 696 查看
 

LUCENE实现站内搜索

一、软件需求

  php-java-bridge_6.2.1_documentation.zip:来自于http://php-java-bridge.sourceforge.net
 

JavaBridge.jar:将上面的php-java-bridge_6.2.1_documentation.zip解压得到一个JavaBridge.war,将JavaBridge.war重命名为JavaBridge.jar,再次用WinRAR对JavaBridge.jar解压到JavaBridge目录,在JavaBridge\WEB-INF\LIB里面可以找到JavaBridge.jar。
 

Lucene.jar:将上面的php-java-bridge_6.2.1_documentation.zip解压得到一个JavaBridge.war,将JavaBridge.war重命名为JavaBridge.jar,再次用WinRAR对JavaBridge.jar解压到JavaBridge目录,在JavaBridge\WEB-INF\LIB里面可以找到Lucene.jar。
 

JDK1.1.7:JavaBridge是由Java语言实现的,所以必须安装JDK实现对jar文件执行提供支持。
 

 Eclipse,选装。一般来说,可以使用“javac *.java”命令来编译java文件,可是对于不熟悉JAVA的同学来说,CLASSPATH、JAVA_HOME环境变量配置不对就用不了javac命令,我就是这样的。在Eclipse中,新建一个“Java Project”编译前选中工程名字,右键点击选择“BuildPath..”->“Build configure…”(子菜单的最下面一个),在弹出的对话框里面选中“Add External jar..”,然后选中lucene.jar就行了。
 

WampServer Version 1.7:(PHP Version 5.3.3,Apache 2.2.17)。

二、实现细则

2.1 安装WampServer

此步骤目的只在于建立一个WEB服务器,可以执行PHP脚本,可以其它方法替代。

2.2 安装JDK

安装JDK实现对jar文件执行提供支持。

2.3 运行JavaBridge

双击运行JavaBridge.jar,应该会弹出一个可以选择的对话框,如果没有弹出,是因为没有安装JDK或者文件关联错误,解决方法是安装JDK或者运行“start javaw -jar JavaBridge.jar”(内容保存到*.bat里面,而*.bat与JavaBridge.jar同一个目录)替代双击。弹出对话框后不用选择,直接点击“确定”即可。

2.4 测试JavaBridge

新建一个test.php(*.php全都保存到WEB服务器根目录里面例如C:\wamp\www)文件,内容如下:

<?php
 
       require_once("java/Java.inc");
       // get instance of Java class java.lang.System in PHP
       $system = new Java('java.lang.System');
       $s = new Java("java.lang.String", "php-java-bridge config...<br><br>");
       echo $s;
 
       // demonstrate property access
       print 'Java version='.$system->getProperty('java.version').' <br>';
       print 'Java vendor=' .$system->getProperty('java.vendor').' <br>';
       print 'OS='.$system->getProperty('os.name').' '.
       $system->getProperty('os.version').' on '.
       $system->getProperty('os.arch').' <br>';
 
       // java.util.Date example
       $formatter = new Java('java.text.SimpleDateFormat',
       "EEEE, MMMM dd, yyyy 'at' h:mm:ss a zzzz");
 
       print $formatter->format(new Java('java.util.Date'));
?>
Java.inc应该放到java目录下,而java应该与test.php同目录,解压JavaBridge.jar可以在JavaBridge\META-INF里面找到java目录,完全拷贝java目录与test.php同目录。执行test.php得到如下输出则表现正确:

php-java-bridge config...

 

Java version=1.6.0_10

Java vendor=Sun Microsystems Inc.

OS=Windows Vista 6.0 on x86

星期日, 十一月 23, 2008 at 4:31:49 下午 中国标准时间

 

2.5 在PHP中调用自己创建的JAVA 类

得到上面输出说明JavaBridge安装成功了,PHP可能调用JAVA内部的类,下面使用Java编写自己的类,而PHP则调用自己写的Java类。

为了尽排除错误,先建立一个EchoHello.java进行测试,代码如下:

public class EchoHello

{

       public String test()

       {

              return "conguratulation php can call methods from java";

       }

}

在Eclipse中执行一次EchoHello.java,会在工程目录下的BIN目录下生成EchoHello.class文件,将EchoHello.class拷贝到C:\Program Files\Java\jre7\classes目录下,因为版本号的不同,jre7文件夹名字可能不同。安装JDK时候默认没有C:\Program Files\Java\jre7\classes,需要手动建立。

测试自己的JAVA类,修改test.php代码如下:

<?php

       include_once("java/java.inc");

 

       $eh = new Java("EchoHello");

       echo $eh->test();

?>

需要重新启动JavaBridge.jar再运行test.pp方法是:到任务管理器里面结束java.exe和javaw.exe,重新双击运行javaBridge.jar,不用选择下列列表,直接“确定”即可。

运行test.php得到"conguratulation php can call methods from java"的输出可以进行下一步,否则重复上面的步骤。

2.6 在Java中使用lucene.jar

新建文件TxtFileIndexer.java,代码如下:

import java.io.File;

import java.io.FileReader;

import java.io.Reader;

import java.util.Date;

 

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;

 

/**

* This class demonstrate the process of creating index with Lucene

* for text files

*/

public class TxtFileIndexer

{

    public static void main(String[] args) throws Exception

    {

     //indexDir is the directory that hosts Lucene's index files

     File   indexDir = new File("E:\\luceneIndex");

     //dataDir is the directory that hosts the text files that to be indexed

     File   dataDir  = new File("E:\\luceneData");

     Analyzer luceneAnalyzer = new StandardAnalyzer();

     File[] dataFiles  = dataDir.listFiles();

     System.out.println("123"+dataDir.toString());

     System.out.println(dataFiles.length);

     IndexWriter indexWriter = new IndexWriter(indexDir,luceneAnalyzer,true);

     long startTime = new Date().getTime();

     for(int i = 0; i < dataFiles.length; i++)

     {

          if(dataFiles[i].isFile() && dataFiles[i].getName().endsWith(".txt")){

               System.out.println("Indexing file " + dataFiles[i].getCanonicalPath());

               Document document = new Document();

               Reader txtReader = new FileReader(dataFiles[i]);

 

               document.add(new Field("contents", txtReader));

               document.add(new Field("path",dataFiles[i].getCanonicalPath(),Field.Store.YES,Field.Index.UN_TOKENIZED));

               indexWriter.addDocument(document);

          }

     }

     indexWriter.optimize();

     indexWriter.close();

     long endTime = new Date().getTime();

       

     System.out.println("It takes " + (endTime - startTime)

         + " milliseconds to create index for the files in directory "

         + dataDir.getPath());       

     }

}

编译时候可能会提示找不到lucene包,解决方法是选中工程名字,右键点击选择“BuildPath..”->“Build configure…”(子菜单的最下面一个),在弹出的对话框里面选中“Add External jar..”,然后选中lucene.jar就行了。并且

       //   document.add(Field.Text("path",dataFiles [i].getCanonicalPath()));

       //   document.add(Field.Text ("contents",txtReader));

并且上面两行有删除线,因为这两个方法是已经过时了的。

使用下面的命令进行编译(替代Eclipse的功能)应该也行,没有试过!并且提示…方法已经过期等(等效于Eclipse里面文字上面是删除线的代码)。

Javac –classpath  lucene的路径\lucene.jar TxtFileIndexer.java

测试Java里面使用lucene.jar

在D盘下新建目录luceneData和luceneIndex,在luceneData里面创建一些文本文件(文件名必须以.html结尾因为TxtFileIndexer.java对文件进行了过滤)。如果没有错误的话,Eclipse的Console窗口应该输出一些信息,并且luceneIndex目录下会生成新索引文件。输入下面信息表示成功(X必须大于1):

It takes X  milliseconds to create index for the files in directory…

!上面内容调试成功前不要进行下一步!

2.7 PHP中使用Lucene.jar

修改TxtFileIndexer.java,内容如下:

import java.io.File;

import java.io.FileReader;

import java.io.Reader;

import java.util.Date;

 

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.index.Term;

import org.apache.lucene.search.Hits;

import org.apache.lucene.search.IndexSearcher;

import org.apache.lucene.search.TermQuery;

import org.apache.lucene.store.FSDirectory;

 

public class TxtFileIndexer

{

       public String test()

       {

              return "test is ok hohoho";

       }

 

       public String createIndex(String indexDir_path,String dataDir_path) throws Exception

       {

              String result = "";

              File indexDir = new File(indexDir_path);

              File dataDir = new File (dataDir_path);

              Analyzer luceneAnalyzer = new StandardAnalyzer();

              File[] dataFiles = dataDir.listFiles();

              IndexWriter indexWriter = new IndexWriter(indexDir,luceneAnalyzer,true);

              long startTime = new Date().getTime ();

              for(int i=0; i < dataFiles.length; i++)

              {

                     if(dataFiles [i].isFile() && dataFiles[i].getName().endsWith(".html"))

                     {

                            result += "Indexing file" + dataFiles[i].getCanonicalPath()+"<br />";

                            Document document = new Document();

                            Reader txtReader = new FileReader(dataFiles[i]);

                            //     旧版本的javaBridge里面可以使用被注释的代码

                            //     而新版本(php-java-bridge_6.2.1_documentation.zip)

                            //     中必须使用没有被注释的代码。

                            //   document.add(Field.Text("path",dataFiles [i].getCanonicalPath()));

                            //   document.add(Field.Text ("contents",txtReader));

                            document.add(new Field("contents", txtReader));

                            document.add(new Field("path",dataFiles[i].getCanonicalPath(),

                                   Field.Store.YES,Field.Index.UN_TOKENIZED));

                            indexWriter.addDocument(document);

                     }

              }

 

              indexWriter.optimize();

              indexWriter.close();

              long endTime = new Date().getTime();

 

              result += "It takes"+(endTime- startTime)

              + " milliseconds to create index for the files in directory "

              + dataDir.getPath();

              return result;

       }

 

       public String searchword(String ss,String index_path) throws Exception

       {

              String queryStr = ss;

              String result = "Result:<br />";

              //This is the directory that hosts the Lucene index

              File indexDir = new File (index_path);

              FSDirectory directory = FSDirectory.getDirectory (indexDir,false);

              IndexSearcher searcher = new IndexSearcher(directory);

              if(!indexDir.exists())

              {

                     result = "The Lucene index is not exist";

                     return result;

              }

 

              Term term = new Term ("contents",queryStr.toLowerCase());

              TermQuery luceneQuery = new TermQuery (term);

              Hits hits = searcher.search(luceneQuery);

              for(int i = 0; i < hits.length(); i++)

              {

                     Document document = hits.doc(i);

                     result += "<br /><a href='getfile.php?w="+ss+"&f="

                            +document.get("path") +"'>File: " + document.get("path")+"</a>n";

              }

              return result;

       }

}

编译修改过的TxtFileIndexer.java,将生成的TxtFileIndexer.class拷贝到C:\Program Files\Java\jre7\classes下面,在这个目录下的*.class可以被PHP引用到。建立Create.php对上面的TxtFileIndexer.class进行测试,代码如下:

<?php

       include_once("java/java.inc");

 

       $eh = new Java("EchoHello");

       echo $eh->test();

 

       error_reporting(0);

       $tf = new       Java('TxtFileIndexer');

 

       print"TestLucene.TxtFileIndexer->test()<br/>".$s;

       echo"<hr/>";

       $data_path      = "C:/wamp/www/testBridge/luceneData";

       $index_path    = "C:/wamp/www/testBridge/luceneIndex";

 

       $s = $tf->createIndex($index_path,$data_path);

       echo $s;

?>

得到下面的输出表示正常,如果没有什么输出时,查看JavaBridge.log(跟JavaBridge.jar同一个目录),其中可能会发现类似找不到org.apache.lucene.analysis.Analyzer类的异常,解决方法是将lucene.jar拷贝到C:\Program Files\Java\jre7\classes,并解压lucene.jar到lucene,将解压后lucene目录下的org整个剪切到C:\Program Files\Java\jre7\classes中(最后的剪切步骤不要可能也行,没有测试过)。

asdfasdfasdfsdfasdfasdfTestLucene.TxtFileIndexer->test()

Indexing fileC:\wamp\www\testBridge\luceneData\一.html

Indexing fileC:\wamp\www\testBridge\luceneData\三.html

Indexing fileC:\wamp\www\testBridge\luceneData\二.html

It takes1579 milliseconds to create index for the files in

directory C:\wamp\www\testBridge\luceneData

2.8 在PHP中测试lucene.jar

新建Search.php与Create.php同一个目录,代码如下:

<?php

       include_once("java/java.inc");

       error_reporting(0);

 

       $tf=new  Java('TxtFileIndexer');

 

       print"TestLucene.TxtFileIndexer->test()<br/>".$s;

       echo"<hr/>";

       $data_path      = "C:\\wamp\\www\\testBridge\\luceneData\\";

       $index_path    = "C:\\wamp\\www\\testBridge\\luceneIndex\\";

       if(isset($_GET["w"]))

       {

              echo $_GET["w"]."<br>";

 

              $s=$tf->searchword($_GET["w"] , $index_path);

                     print $s;

       }

       else

       {

              echo"<form method=get><input type='text' name='w' />

                     <input type='submit' value='search' /><br/>";

       }

?>

首次执行Search.php时,会要求输入关键字进行搜索,输入后点击后面的Search按钮,如果匹配发生则将结果输出到浏览器。

三 小结

至此,JavaBridge的使用,通过JavaBridge调用Java内部的类,通过JavaBridge调用自己定义的类,在Java里面使用Lucene.jar,在PHP里面使用Lucene.jar都介绍完毕,知道原理后可以根据自己的需要扩展TxtFileIndexer.java、Create.php和Search.php实现更加复杂的功能了。完!

可惜目前只实现了对英文的搜索,不可以搜索中文,应该改进并将改进内容添加到下面。

如果有问题可以联系507491840@qq.com或者woijal520@163.com

支持原创!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息