温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

lucene+jquery+struts2json插件实现搜索框自动补全

发布时间:2020-06-20 09:27:05 来源:网络 阅读:1198 作者:zbzbzb022 栏目:web开发

看了一堆自动补齐的例子,大多都是只有前台没有后台,有后台也是在后台写死的数据,所以不具有真实的实用性,拿来学习还是可以的,但也是仅仅限于jquery的学习。

接下来我要写一个从后台数据库生成lucene索引文件,在struts2Action中查根据key值查询索引文件,获取到部分符合关键字(key值)的数据,通过json格式返回到前台页面,在使用jquery完成自动补齐的完整例子。

首先第一步从数据库中获取索引文件。

  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.             //如果对海量数据进行创建索引的时候,需要对索引进行优化,以便提高速度  
  74.             writer.optimize();  
  75.             //跟数据库类似,打开一个连接,使用完后,要关闭它  
  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> 

好了,创建索引文件就基本完成了啊。

下面,我们来通过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.             //搜索结果集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中所要返回的数据自动封装成json格式的,本例子中需要返回list,就会讲list中存放的数据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

这样,我们的后台基本就写完了。现在总结一下:后台主要完成的功能就是数据库到索引文件的同步和通过key查询索引文件返回json结果集的这么一个过程。

最后,我们来写前台jquery,这个大部分例子有用了,我就不再详细叙述了,只把代码贴出来。还要说明一点,大多数例子所捕获的键盘信息严重不足,我多加捕获了一些,包括输入汉字时输入法前的数字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插件实现搜索框自动补全

 

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI