您好,登錄后才能下訂單哦!
看了一堆自動補齊的例子,大多都是只有前臺沒有后臺,有后臺也是在后臺寫死的數據,所以不具有真實的實用性,拿來學習還是可以的,但也是僅僅限于jquery的學習。
接下來我要寫一個從后臺數據庫生成lucene索引文件,在struts2Action中查根據key值查詢索引文件,獲取到部分符合關鍵字(key值)的數據,通過json格式返回到前臺頁面,在使用jquery完成自動補齊的完整例子。
首先第一步從數據庫中獲取索引文件。
- package com.net263.boss.charge.action;
- import java.util.ArrayList;
- import java.util.List;
- import org.apache.log4j.Logger;
- 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.quartz.JobExecutionContext;
- import org.quartz.JobExecutionException;
- import org.springframework.scheduling.quartz.QuartzJobBean;
- import com.net263.boss.business.service.ICustomerService;
- public class CreateSearchIndex extends QuartzJobBean {
- /*
- * (non-Javadoc)
- *
- * @see
- * org.springframework.scheduling.quartz.QuartzJobBean#executeInternal(org
- * .quartz.JobExecutionContext)
- */
- private ICustomerService customerService;
- /**
- * @return the customerService
- */
- public ICustomerService getCustomerService() {
- return customerService;
- }
- /**
- * @param customerService the customerService to set
- */
- public void setCustomerService(ICustomerService customerService) {
- this.customerService = customerService;
- }
- private static Logger logger = Logger.getLogger(CreateSearchIndex.class);
- public void executeInternal(JobExecutionContext context)
- throws JobExecutionException {
- String path = this.getClass().getClassLoader().getResource("").getPath().replace(" ","\" \"")+"index";
- logger.info("begin...");
- //path=path.substring(1).trim();
- logger.info("index path is :"+path);
- List<String> list = new ArrayList<String>();
- IndexWriter writer;
- try {
- list = customerService.queryCustomerName();
- logger.info("get index successfully.");
- } catch (Exception e) {
- e.printStackTrace();
- }
- try {
- writer = new IndexWriter(path,new StandardAnalyzer(),true);
- for(String tempC : list)
- {
- if(tempC==null || "".equals(tempC))
- {
- continue;
- }
- else
- {
- Document docA = new Document();
- Field fieldA = new Field("content",tempC,Field.Store.YES,Field.Index.TOKENIZED);
- docA.add(fieldA);
- writer.addDocument(docA);
- }
- }
- //如果對海量數據進行創建索引的時候,需要對索引進行優化,以便提高速度
- writer.optimize();
- //跟數據庫類似,打開一個連接,使用完后,要關閉它
- writer.close();
- logger.info("end...");
- } catch (Exception e) {
- e.printStackTrace();
- logger.info("error...");
- }
- }
- }
以上代碼是通過Quartz來進行啟動的,每分鐘進行一次索引文件的同步。
配置文件如下:
- <bean id="jobCreateTask" class="org.springframework.scheduling.quartz.JobDetailBean">
- <property name="jobClass" value="com.net263.boss.charge.action.CreateSearchIndex"/>
- <property name="jobDataAsMap">
- <map>
- <entry key="customerService" value-ref="customerService"/>
- </map>
- </property>
- </bean>
- <bean id="CreateTasktrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
- <property name="jobDetail" ref="jobCreateTask"/>
- <property name="cronExpression" value="0 0/1 0-23 * * ?"/>
- </bean>
好了,創建索引文件就基本完成了啊。
下面,我們來通過Action獲取到所需的自動補全信息。
- import java.util.ArrayList;
- import java.util.Date;
- import java.util.List;
- import net.sf.json.JSONArray;
- import org.apache.log4j.Logger;
- import org.apache.lucene.analysis.standard.StandardAnalyzer;
- import org.apache.lucene.queryParser.QueryParser;
- import org.apache.lucene.search.Hits;
- import org.apache.lucene.search.IndexSearcher;
- import org.apache.lucene.search.Query;
- import org.apache.struts2.json.annotations.JSON;
- import com.net263.boss.util.JsonUtils;
- import com.opensymphony.xwork2.ActionSupport;
- public class QueryCustomerNameAction extends ActionSupport {
- String path = this.getClass().getClassLoader().getResource("").getPath().replace(" ","\" \"")+"index";
- private String customerName;
- List<String> list =new ArrayList<String>();
- /**
- * @return the list
- */
- public List<String> getList() {
- return list;
- }
- /**
- * @param list the list to set
- */
- public void setList(List<String> list) {
- this.list = list;
- }
- private static final Logger LOGGER = Logger.getLogger(QueryCustomerNameAction.class);
- public void setKey(String customerName) {
- this.customerName = customerName;
- }
- public Query queryParser(String key){
- //content 為默認搜索的Field列名
- QueryParser queryParser = new QueryParser("content", new StandardAnalyzer());
- try {
- Query query = queryParser.parse(key);
- return query;
- } catch (Exception e) {
- e.printStackTrace();
- }
- return null;
- }
- public String searchName()
- {
- Date startTime,endTime;
- try {
- IndexSearcher search = new IndexSearcher(path);
- startTime = new Date();
- //抽象的查詢對象
- if(customerName!=null && !("".equals(customerName)))
- {
- Query query = queryParser(customerName);
- //搜索結果集Hits
- Hits hits = search.search(query);
- for (int i = 0; i < hits.length(); i++) {
- int beginIndex=hits.doc(i).toString().indexOf(":");
- int endIndex=hits.doc(i).toString().indexOf(">");
- list.add(hits.doc(i).toString().substring(beginIndex+1, endIndex));
- System.out.println(hits.doc(i).toString().substring(beginIndex+1, endIndex));
- if(i>8)
- {
- break;
- }
- }
- }
- endTime = new Date();
- System.out.println("本次搜索用時:" + (endTime.getTime() - startTime.getTime()) + "毫秒");
- LOGGER.info("本次搜索用時:" + (endTime.getTime() - startTime.getTime()) + "毫秒");
- LOGGER.info("list:"+JsonUtils.listToJson(list));
- } catch (Exception e) {
- LOGGER.info("沒有搜索到對應分詞");
- //e.printStackTrace();
- }
- return "success";
- }
- }
這里面用到了struts2的json插件,這個插件很好用,它會把Action中所要返回的數據自動封裝成json格式的,本例子中需要返回list,就會講list中存放的數據json化。
需要特別提示的是:
- <package name="searchname" namespace="/business/customer" extends="json-default">
- <action name="search" class="com.net263.boss.business.action.QueryCustomerNameAction" method="searchName">
- <!-- 返回List對象的-->
- <result name="success" type="json">
- <param name="root">list</param>
- </result>
- </action>
- </package>
需要繼承json-default
這樣,我們的后臺基本就寫完了。現在總結一下:后臺主要完成的功能就是數據庫到索引文件的同步和通過key查詢索引文件返回json結果集的這么一個過程。
最后,我們來寫前臺jquery,這個大部分例子有用了,我就不再詳細敘述了,只把代碼貼出來。還要說明一點,大多數例子所捕獲的鍵盤信息嚴重不足,我多加捕獲了一些,包括輸入漢字時輸入法前的數字1-5,當然可以捕獲更多。
- var highlightindex =-1;
- $(document).ready(function() {
- var wordInput=$("#customerName");
- var wordInputOffset=wordInput.offset();
- var auto=$("#autoComplete").hide().css("border","3px white solid").css("background-color" ,"white")
- .css("position","absolute")
- .css("top",wordInputOffset.top+wordInput.height()+12+"px")
- .css("left",wordInputOffset.left+"px").width(wordInput.width()+6);
- wordInput.keyup(function(event){
- var myEvent =event || window.event;
- var keyCode = myEvent.keyCode;
- var wordText =$("#customerName").val();
- var actionurl="search.action";
- if(keyCode>=65 && keyCode<=90 ||keyCode==8 || keyCode==46 || keyCode==32 || keyCode==49 || keyCode==50 || keyCode==51 || keyCode==52 || keyCode==53)
- {
- if(wordText != ""){
- $.ajax({
- url : actionurl,
- data : {key : wordText},
- type : 'POST',
- dataType : 'json',
- success : function(data) {
- $(auto).empty();
- $.each(data,function(index,term){
- var newDwNode = $("<div>").attr("id",index);
- newDwNode.html(term).appendTo(auto);
- //鼠標移入
- newDwNode.mouseover(function(){
- if (highlightindex != -1) {
- var autoNodes = $(auto).children("div");
- autoNodes.eq(highlightindex).css("background-color" ,"white").css("font-weight","normal");
- }
- highlightindex = $(this).attr("id");
- $(this).css("background-color","#CCCCFF").css("font-weight", "800");
- });
- //鼠標移出
- newDwNode.mouseout(function(){
- $(this).css("background-color" ,"white").css("font-weight","normal");
- });
- //鼠標單擊
- newDwNode.click(function(){
- var dataText = $(this).text();
- wordInput.val(dataText);
- $(auto).hide();
- });
- });
- if(data.length>0)
- {
- $(auto).show();
- }
- else
- {
- $(auto).hide();
- parseInt(highlightindex) =-1;
- }
- }
- });
- }
- else
- {
- $(auto).hide();
- parseInt(highlightindex) =-1;
- }
- }
- else if(keyCode==38 || keyCode==40)
- {
- if(keyCode==38)//向上
- {
- var autoNodes = $(auto).children("div");
- if (highlightindex!= -1) {
- autoNodes.eq(highlightindex).css("background-color" ,"white").css("font-weight","normal");
- highlightindex=highlightindex-1;
- } else {
- parseInt(highlightindex)=autoNodes.length-1;
- }
- if (highlightindex == -1) {
- highlightindex=autoNodes.length-1;
- }
- var dataText = autoNodes.eq(highlightindex).css("background-color","#CCCCFF").css("font-weight", "800").text();
- wordInput.val(dataText);
- }
- if(keyCode==40)//向下
- {
- var autoNodes = $(auto).children("div");
- if (parseInt(highlightindex) != -1) {
- autoNodes.eq(highlightindex).css("background-color" ,"white").css("font-weight","normal");
- }
- highlightindex=parseInt(highlightindex)+1;
- if (highlightindex == autoNodes.length) {
- highlightindex=0;
- }
- var dataText = autoNodes.eq(highlightindex).css("background-color","#CCCCFF").css("font-weight", "800").text();
- wordInput.val(dataText);
- }
- }else if(keyCode==13)//回車
- {
- $(auto).hide();
- highlightindex =-1;
- }
- })
- })
最后顯示效果如下:
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。