[lucene系列笔记3]用socket把lucene做成一个web服务
上一篇介绍了用lucene建立索引和搜索,但是那些都只是在本机上运行的,如果希望在服务器上做成web服务该怎么办呢?
一个有效的方法就是用socket通信,这样可以实现后端与前端的独立,也就是不管前端用什么(比如PHP)都可以Lucene只提供检索功能。
简单来说,socket就是实现不同的进程之间通讯的一个通道。socket由两部分组成:服务端和客户端。有两种:单进程和多进程。
所以认识socket的阶梯大概是这样的:
1.用java本地做服务端和客户端,实现不同程序之间的单进程通讯;
2.用java在web服务器做服务端,用java本地做客户端,实现不同机器之间的单进程通讯;
3.用java在web服务器做服务端,用PHP在服务器做客户端,实现外网通过PHP网页使用服务(单进程);
4.用java在web服务器做服务端,用PHP在服务器做客户端,实现外网通过PHP网页使用服务(多进程);
下面,这篇文章先介绍第一个:用java本地做服务端和客户端,实现不同程序之间的单进程通讯。
继续上一篇的LuceneTools工程,在里面new一个class命名为LocalSocketServer。
然后在里面加入如下代码(服务端):
import java.nio.file.Paths; import java.io.*; import java.net.*; import org.apache.lucene.analysis.standard.StandardAnalyzer; import org.apache.lucene.document.Document; import org.apache.lucene.index.DirectoryReader; import org.apache.lucene.queryparser.classic.QueryParser; import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.Query; import org.apache.lucene.search.ScoreDoc; import org.apache.lucene.search.TopDocs; import org.apache.lucene.store.Directory; import org.apache.lucene.store.FSDirectory; import org.apache.lucene.util.Version; /** * @author song * @description: * 依赖jar:Lucene-core,lucene-analyzers-common,lucene-queryparser * 作用:使用索引搜索文件 */ public class LocalSocketServer { public static Version luceneVersion = Version.LATEST; /** * 查询内容 */ public static String indexSearch(String keywords){ String res = ""; DirectoryReader reader = null; try{ // 1、创建Directory Directory directory = FSDirectory.open(Paths.get("D:/lucenetest/index"));//在硬盘上生成Directory // 2、创建IndexReader reader = DirectoryReader.open(directory); // 3、根据IndexWriter创建IndexSearcher IndexSearcher searcher = new IndexSearcher(reader); // 4、创建搜索的query // 创建parse用来确定搜索的内容,第二个参数表示搜索的域 QueryParser parser = new QueryParser("content",new StandardAnalyzer());//content表示搜索的域或者说字段 Query query = parser.parse(keywords);//被搜索的内容 // 5、根据Searcher返回TopDocs TopDocs tds = searcher.search(query, 20);//查询20条记录 // 6、根据TopDocs获取ScoreDoc ScoreDoc[] sds = tds.scoreDocs; // 7、根据Searcher和ScoreDoc获取搜索到的document对象 int cou=0; for(ScoreDoc sd:sds){ cou++; Document d = searcher.doc(sd.doc); // 8、根据document对象获取查询的字段值 /** 查询结果中content为空,是因为索引中没有存储content的内容,需要根据索引path和name从原文件中获取content**/ res+=cou+". "+d.get("path")+" "+d.get("name")+" "+d.get("content")+"\n"; } }catch(Exception e){ e.printStackTrace(); }finally{ //9、关闭reader try { reader.close(); } catch (IOException e) { e.printStackTrace(); } } return res+"hehehehe"; } public static void main(String[] args) throws IOException { ServerSocket server=new ServerSocket(5678); while (true) { Socket client=server.accept(); BufferedReader in=new BufferedReader(new InputStreamReader(client.getInputStream())); PrintWriter out=new PrintWriter(client.getOutputStream()); String str=in.readLine(); System.out.println(str); out.println(indexSearch(str)); out.flush(); client.close(); } } }
我们就用上一篇做好的索引来提供服务。
然后客户端我们也用java。在工程里new一个class命名为LocalSocketClient。加入如下代码:
import java.net.*; import java.io.*; public class LocalSocketClient { static Socket server; public static void main(String[] args)throws Exception { //如果127.0.0.1不行可以换成InetAddress.getLocalHost() server=new Socket("127.0.0.1",5678); BufferedReader in=new BufferedReader(new InputStreamReader(server.getInputStream())); PrintWriter out=new PrintWriter(server.getOutputStream()); BufferedReader wt=new BufferedReader(new InputStreamReader(System.in)); String str=wt.readLine(); out.println(str); out.flush(); String res=in.readLine(); while (!res.equals("hehehehe")) { System.out.println(res); res=in.readLine(); } out.flush(); server.close(); } }
然后先运行起服务端程序,然后跑起来以后再运行客户端程序,在客户端输入查询即可得到反馈结果。
至此,我们学会了单进程,本地socket+Lucene提供服务。(提示:由于上面的服务端程序设置的是无限循环,所以一定要手动结束程序!)