溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

lucene+jquery+struts2json插件實現(xiàn)搜索框自動補全

發(fā)布時間:2020-06-20 09:27:05 來源:網(wǎng)絡 閱讀:1209 作者:zbzbzb022 欄目:web開發(fā)

看了一堆自動補齊的例子,大多都是只有前臺沒有后臺,有后臺也是在后臺寫死的數(shù)據(jù),所以不具有真實的實用性,拿來學習還是可以的,但也是僅僅限于jquery的學習。

接下來我要寫一個從后臺數(shù)據(jù)庫生成lucene索引文件,在struts2Action中查根據(jù)key值查詢索引文件,獲取到部分符合關鍵字(key值)的數(shù)據(jù),通過json格式返回到前臺頁面,在使用jquery完成自動補齊的完整例子。

首先第一步從數(shù)據(jù)庫中獲取索引文件。

  1. package com.net263.boss.charge.action;  
  2.  
  3. import java.util.ArrayList;  
  4. import java.util.List;  
  5. import org.apache.log4j.Logger;  
  6. import org.apache.lucene.analysis.standard.StandardAnalyzer;  
  7. import org.apache.lucene.document.Document;  
  8. import org.apache.lucene.document.Field;  
  9.  
  10. import org.apache.lucene.index.IndexWriter;  
  11.  
  12. import org.quartz.JobExecutionContext;  
  13. import org.quartz.JobExecutionException;  
  14. import org.springframework.scheduling.quartz.QuartzJobBean;  
  15.  
  16. import com.net263.boss.business.service.ICustomerService;  
  17. public class CreateSearchIndex extends QuartzJobBean {  
  18.  
  19.     /*  
  20.      * (non-Javadoc)  
  21.      *   
  22.      * @see  
  23.      * org.springframework.scheduling.quartz.QuartzJobBean#executeInternal(org  
  24.      * .quartz.JobExecutionContext)  
  25.      */ 
  26.     private ICustomerService customerService;  
  27.  
  28.  
  29.     /**  
  30.      * @return the customerService  
  31.      */ 
  32.     public ICustomerService getCustomerService() {  
  33.         return customerService;  
  34.     }  
  35.     /**  
  36.      * @param customerService the customerService to set  
  37.      */ 
  38.     public void setCustomerService(ICustomerService customerService) {  
  39.         this.customerService = customerService;  
  40.     }  
  41.     private static Logger logger = Logger.getLogger(CreateSearchIndex.class);  
  42.     public void executeInternal(JobExecutionContext context)  
  43.             throws JobExecutionException {  
  44.         String path = this.getClass().getClassLoader().getResource("").getPath().replace(" ","\" \"")+"index";  
  45.         logger.info("begin...");  
  46.         //path=path.substring(1).trim();  
  47.         logger.info("index path is :"+path);  
  48.         List<String> list = new ArrayList<String>();  
  49.         IndexWriter writer;  
  50.         try {  
  51.             list = customerService.queryCustomerName();  
  52.             logger.info("get index successfully.");  
  53.         } catch (Exception e) {  
  54.             e.printStackTrace();  
  55.         }  
  56.         try {  
  57.             writer = new IndexWriter(path,new StandardAnalyzer(),true);  
  58.             for(String tempC : list)  
  59.             {  
  60.                 if(tempC==null || "".equals(tempC))  
  61.                     {  
  62.                     continue;  
  63.                     }  
  64.                 else 
  65.                 {  
  66.                     Document docA = new Document();  
  67.                     Field fieldA = new Field("content",tempC,Field.Store.YES,Field.Index.TOKENIZED);  
  68.                     docA.add(fieldA);  
  69.                     writer.addDocument(docA);  
  70.                 }  
  71.                   
  72.             }  
  73.             //如果對海量數(shù)據(jù)進行創(chuàng)建索引的時候,需要對索引進行優(yōu)化,以便提高速度  
  74.             writer.optimize();  
  75.             //跟數(shù)據(jù)庫類似,打開一個連接,使用完后,要關閉它  
  76.             writer.close();  
  77.             logger.info("end...");  
  78.         } catch (Exception e) {  
  79.             e.printStackTrace();  
  80.             logger.info("error...");  
  81.         }   
  82.     }  
  83.  
  84. }  

以上代碼是通過Quartz來進行啟動的,每分鐘進行一次索引文件的同步。

配置文件如下:

 

  1.  <bean id="jobCreateTask" class="org.springframework.scheduling.quartz.JobDetailBean">    
  2.         
  3.      <property name="jobClass" value="com.net263.boss.charge.action.CreateSearchIndex"/> 
  4.        
  5.      
  6.       <property name="jobDataAsMap"> 
  7.     <map> 
  8.         <entry key="customerService" value-ref="customerService"/> 
  9.     </map> 
  10. </property> 
  11.   </bean>    
  12.   <bean id="CreateTasktrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">    
  13.       <property name="jobDetail" ref="jobCreateTask"/> 
  14.        <property name="cronExpression" value="0 0/1 0-23 * * ?"/>    
  15.   </bean> 

好了,創(chuàng)建索引文件就基本完成了啊。

下面,我們來通過Action獲取到所需的自動補全信息。

 

  1. import java.util.ArrayList;  
  2. import java.util.Date;  
  3. import java.util.List;  
  4.  
  5. import net.sf.json.JSONArray;  
  6.  
  7. import org.apache.log4j.Logger;  
  8. import org.apache.lucene.analysis.standard.StandardAnalyzer;  
  9. import org.apache.lucene.queryParser.QueryParser;  
  10. import org.apache.lucene.search.Hits;  
  11. import org.apache.lucene.search.IndexSearcher;  
  12. import org.apache.lucene.search.Query;  
  13. import org.apache.struts2.json.annotations.JSON;  
  14.  
  15. import com.net263.boss.util.JsonUtils;  
  16. import com.opensymphony.xwork2.ActionSupport;  
  17.  
  18. public class QueryCustomerNameAction extends ActionSupport {  
  19.     String path = this.getClass().getClassLoader().getResource("").getPath().replace(" ","\" \"")+"index";  
  20.     private String customerName;  
  21.     List<String> list =new ArrayList<String>();  
  22.     /**  
  23.      * @return the list  
  24.      */ 
  25.     public List<String> getList() {  
  26.         return list;  
  27.     }  
  28.  
  29.     /**  
  30.      * @param list the list to set  
  31.      */ 
  32.     public void setList(List<String> list) {  
  33.         this.list = list;  
  34.     }  
  35.  
  36.     private static final Logger LOGGER = Logger.getLogger(QueryCustomerNameAction.class);  
  37.  
  38.     public void setKey(String customerName) {  
  39.         this.customerName = customerName;  
  40.     }  
  41.  
  42.     public Query queryParser(String key){  
  43.         //content 為默認搜索的Field列名  
  44.         QueryParser queryParser = new QueryParser("content"new StandardAnalyzer());  
  45.         try {  
  46.             Query query =  queryParser.parse(key);  
  47.             return query;  
  48.         } catch (Exception e) {  
  49.             e.printStackTrace();  
  50.         }  
  51.         return null;  
  52.     }  
  53.       
  54.     public String searchName()  
  55.     {  
  56.         Date startTime,endTime;  
  57.         try {  
  58.               
  59.             IndexSearcher search = new IndexSearcher(path);  
  60.             startTime = new Date();  
  61.             //抽象的查詢對象  
  62.             if(customerName!=null && !("".equals(customerName)))  
  63.             {  
  64.                 Query query = queryParser(customerName);  
  65.             //搜索結(jié)果集Hits  
  66.             Hits hits = search.search(query);  
  67.             for (int i = 0; i < hits.length(); i++) {  
  68.                 int beginIndex=hits.doc(i).toString().indexOf(":");  
  69.                 int endIndex=hits.doc(i).toString().indexOf(">");  
  70.                 list.add(hits.doc(i).toString().substring(beginIndex+1, endIndex));  
  71.                 System.out.println(hits.doc(i).toString().substring(beginIndex+1, endIndex));  
  72.                 if(i>8)  
  73.                 {  
  74.                     break;  
  75.                 }  
  76.             }  
  77.             }  
  78.             endTime = new Date();  
  79.             System.out.println("本次搜索用時:" + (endTime.getTime() - startTime.getTime()) + "毫秒");  
  80.             LOGGER.info("本次搜索用時:" + (endTime.getTime() - startTime.getTime()) + "毫秒");  
  81.             LOGGER.info("list:"+JsonUtils.listToJson(list));  
  82.         } catch (Exception e) {  
  83.             LOGGER.info("沒有搜索到對應分詞");  
  84.             //e.printStackTrace();  
  85.         }  
  86.         return "success";  
  87.     }  
  88.  

這里面用到了struts2的json插件,這個插件很好用,它會把Action中所要返回的數(shù)據(jù)自動封裝成json格式的,本例子中需要返回list,就會講list中存放的數(shù)據(jù)json化。

需要特別提示的是:

 

  1. <package name="searchname" namespace="/business/customer" extends="json-default">   
  2.     <action name="search" class="com.net263.boss.business.action.QueryCustomerNameAction" method="searchName">   
  3.         <!-- 返回List對象的--> 
  4.         <result name="success" type="json"> 
  5.         <param name="root">list</param> 
  6.         </result>   
  7.     </action> 
  8. </package>  

需要繼承json-default

這樣,我們的后臺基本就寫完了。現(xiàn)在總結(jié)一下:后臺主要完成的功能就是數(shù)據(jù)庫到索引文件的同步和通過key查詢索引文件返回json結(jié)果集的這么一個過程。

最后,我們來寫前臺jquery,這個大部分例子有用了,我就不再詳細敘述了,只把代碼貼出來。還要說明一點,大多數(shù)例子所捕獲的鍵盤信息嚴重不足,我多加捕獲了一些,包括輸入漢字時輸入法前的數(shù)字1-5,當然可以捕獲更多。

 

  1. var highlightindex =-1;  
  2. $(document).ready(function() {  
  3.     var wordInput=$("#customerName");  
  4.     var wordInputOffset=wordInput.offset();  
  5.     var auto=$("#autoComplete").hide().css("border","3px white solid").css("background-color" ,"white")  
  6.     .css("position","absolute")  
  7.     .css("top",wordInputOffset.top+wordInput.height()+12+"px")  
  8.     .css("left",wordInputOffset.left+"px").width(wordInput.width()+6);  
  9.     wordInput.keyup(function(event){  
  10.         var myEvent =event || window.event;  
  11.         var keyCode = myEvent.keyCode;  
  12.         var wordText =$("#customerName").val();  
  13.         var actionurl="search.action";  
  14.         if(keyCode>=65 && keyCode<=90 ||keyCode==8 || keyCode==46 || keyCode==32 || keyCode==49 || keyCode==50 || keyCode==51 || keyCode==52 || keyCode==53)  
  15.         {  
  16.         if(wordText != ""){  
  17.                 $.ajax({    
  18.                     url : actionurl,    
  19.                     data : {key : wordText},    
  20.                     type : 'POST',    
  21.                     dataType : 'json',    
  22.                     success : function(data) {  
  23.                         $(auto).empty();  
  24.                                 $.each(data,function(index,term){  
  25.                                     var newDwNode = $("<div>").attr("id",index);  
  26.                                     newDwNode.html(term).appendTo(auto);  
  27.                                     //鼠標移入  
  28.                                     newDwNode.mouseover(function(){  
  29.                                         if (highlightindex != -1) {  
  30.                                             var autoNodes = $(auto).children("div");  
  31.                                             autoNodes.eq(highlightindex).css("background-color" ,"white").css("font-weight","normal");  
  32.                                         }  
  33.                                         highlightindex = $(this).attr("id");  
  34.                                         $(this).css("background-color","#CCCCFF").css("font-weight""800");  
  35.                                     });  
  36.                                     //鼠標移出  
  37.                                     newDwNode.mouseout(function(){  
  38.                                         $(this).css("background-color" ,"white").css("font-weight","normal");  
  39.                                     });  
  40.                                     //鼠標單擊  
  41.                                     newDwNode.click(function(){  
  42.                                         var dataText = $(this).text();  
  43.                                         wordInput.val(dataText);  
  44.                                         $(auto).hide();  
  45.                                     });  
  46.                                 });  
  47.                                 if(data.length>0)  
  48.                                 {  
  49.                                     $(auto).show();  
  50.                                 }  
  51.                                 else 
  52.                                 {  
  53.                                     $(auto).hide();  
  54.                                     parseInt(highlightindex) =-1;  
  55.                                 }  
  56.                     }    
  57.                 });   
  58.             }  
  59.         else 
  60.         {  
  61.             $(auto).hide();  
  62.             parseInt(highlightindex) =-1;  
  63.         }  
  64.         }  
  65.         else if(keyCode==38 || keyCode==40)  
  66.         {  
  67.             if(keyCode==38)//向上  
  68.             {  
  69.                 var autoNodes = $(auto).children("div");  
  70.                 if (highlightindex!= -1) {  
  71.                             autoNodes.eq(highlightindex).css("background-color" ,"white").css("font-weight","normal");  
  72.                             highlightindex=highlightindex-1;  
  73.                         } else {  
  74.                             parseInt(highlightindex)=autoNodes.length-1;  
  75.                         }  
  76.                 if (highlightindex == -1) {  
  77.                     highlightindex=autoNodes.length-1;  
  78.                 }  
  79.                 var dataText = autoNodes.eq(highlightindex).css("background-color","#CCCCFF").css("font-weight""800").text();  
  80.                 wordInput.val(dataText);  
  81.             }  
  82.             if(keyCode==40)//向下  
  83.             {  
  84.                 var autoNodes = $(auto).children("div");  
  85.                 if (parseInt(highlightindex) != -1) {  
  86.                             autoNodes.eq(highlightindex).css("background-color" ,"white").css("font-weight","normal");  
  87.                         }   
  88.                 highlightindex=parseInt(highlightindex)+1;  
  89.                 if (highlightindex == autoNodes.length) {  
  90.                     highlightindex=0;  
  91.                 }  
  92.                 var dataText = autoNodes.eq(highlightindex).css("background-color","#CCCCFF").css("font-weight""800").text();  
  93.                 wordInput.val(dataText);  
  94.             }  
  95.               
  96.         }else if(keyCode==13)//回車  
  97.         {  
  98.             $(auto).hide();   
  99.             highlightindex =-1;  
  100.         }  
  101.     })  
  102. }) 

最后顯示效果如下:

 

lucene+jquery+struts2json插件實現(xiàn)搜索框自動補全

 

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。

AI