读书人

第一回使用compass做全文搜索

发布时间: 2012-11-11 10:07:57 作者: rapoo

第一次使用compass做全文搜索

由于是个资讯类的项目,加上把项目的结构进行了重新部署(基于Annotation spring 2.5 MVC + hibernate),所以也计划把compass也加进来,做个简单的全文搜索。可惜是时间比较紧,前台没有把url-rewrite也加入(考虑到前台经常变化,又不想经常reload,所以用jsp直接读取)。第一次使用compass,基本也上网找找资料,以下总结一下:

?

所需包:compass-2.2.0.jar,lucene-core.jar

?

application-compass.xml

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"     xmlns:context="http://www.springframework.org/schema/context"    xmlns:aop="http://www.springframework.org/schema/aop"    xmlns:tx="http://www.springframework.org/schema/tx"    xsi:schemaLocation="            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">                 <bean id="annotationConfiguration" ref="annotationConfiguration"/><property name="compassSettings"><props><prop key="compass.engine.connection">D:/javaWeb/lib-read/compass</prop> <prop key="compass.transaction.factory">org.compass.spring.transaction.SpringSyncTransactionFactory</prop></props>  </property><property name="transactionManager" ref="transactionManager"/></bean><bean id="hibernateGpsDevice" ref="sessionFactory"/><property name="mirrorDataChanges">              <value>true</value><!-- 同步更新索引 -->          </property>  </bean><bean id="compassGps" init-method="start" destroy-method="stop"><property name="compass" ref="compass"/><property name="gpsDevices"><bean id="hibernateGpsDevice2" value="hibernateDevice"></property>                       <property name="sessionFactory" ref="sessionFactory"></property>                </bean></property></bean><bean id="compassTemplate"  ref="compass" />   </bean> <!-- 定时重建索引(利用quartz)或随 Spring ApplicationContext启动而重建索引 -->     <bean id="compassIndexBuilder"                 lazy-init="false">         <property name="compassGps" ref="compassGps" />         <property name="buildIndex" value="true"/><!--   -->         <property name="lazyTime" value="10" />     </bean>              </beans>

?

CompassIndexBuilder.java

public class CompassIndexBuilder implements InitializingBean {        private static final Logger log = Logger.getLogger(CompassIndexBuilder.class);      // 是否需要建立索引,可被设置为false使本Builder失效.      private boolean buildIndex = true;      // 索引操作线程延时启动的时间,单位为秒      private int lazyTime = 50;       // Compass封装       private CompassGps compassGps;       // 索引线程       private Thread indexThread = new Thread() {               public void run() {                       try {                               Thread.sleep(lazyTime * 1000);                               log.info("begin compass index...");                               long beginTime = System.currentTimeMillis();                               // 重建索引.                               // 如果compass实体中定义的索引文件已存在,索引过程中会建立临时索引,                               // 索引完成后再进行覆盖.                               compassGps.index();                               long costTime = System.currentTimeMillis() - beginTime;                               log.info("compss index finished.");                               log.info("costed " + costTime + " milliseconds");                       } catch (InterruptedException e) {                               // simply proceed                       }               }       };       /**       * 实现<code>InitializingBean</code>接口,在完成注入后调用启动索引线程.       *       * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()       */       public void afterPropertiesSet() throws Exception {               if (buildIndex) {                       Assert.notNull(compassGps, "CompassIndexBuilder not set CompassGps yet.");                       indexThread.setDaemon(true);                       indexThread.setName("Compass Indexer");                       indexThread.start();               }       }       public void setBuildIndex(boolean buildIndex) {               this.buildIndex = buildIndex;       }       public void setLazyTime(int lazyTime) {               this.lazyTime = lazyTime;       }       public void setCompassGps(CompassGps compassGps) {               this.compassGps = compassGps;       }  }  
?

?

CompassSearchController.java

@Controllerpublic class CompassSearchController {@Autowiredprivate Compass compass ;@RequestMapping("/search.do")public ModelAndView list(HttpServletRequest request, HttpServletResponse response) throws UnsupportedEncodingException{ModelAndView mav = new ModelAndView("search");int offsetStart = 0;int maxPageItems = 10;int maxIndexPages = 10;String szOffsetStart = request.getParameter("pager.offset");if (szOffsetStart != null)offsetStart = Integer.valueOf(szOffsetStart).intValue();String keywords = "";if (request.getParameter("keywords") != null){keywords = request.getParameter("keywords");}String keyStr = "";try{keywords = URLDecoder.decode(keywords, "UTF-8");keyStr = URLEncoder.encode(keywords, "UTF-8");}catch (UnsupportedEncodingException e){e.printStackTrace();}       //打开session会话       CompassSession session = compass.openSession();       //开启session事务       CompassTransaction tx = session.beginLocalTransaction();       //用session建立一个查询       CompassQueryBuilder queryBuilder = session.queryBuilder();       //得到查询结果       CompassQuery a = queryBuilder.queryString(keywords).toQuery();       CompassQuery b = queryBuilder.ge("isShow", "1");       CompassBooleanQueryBuilder CQB = queryBuilder.bool().addMust(a).addMust(b);       //按照postTime属性进行排列,默认是升序       //query.addSort(“postTime”,SortDirection.REVERSE);//是降序       //query.addSort("postTime");       //获得结果集       CompassHits hits = query.hits();              int itemCount = hits.length();             //为了防止角标越界,所以在结果集和要取得的内容之间取最小值       int end = Math.min(hits.length(),  offsetStart + maxPageItems);                     List list = new ArrayList();       for (int i = offsetStart; i < end; i++){           //取得每一个结果          list.add(hits.data(i));                     //高亮  返回的是高亮后的字符串           /*String ht = hits.highlighter(i).fragment("content");           if(ht!=null){              aritcle.setContent(ht);           }                     list.add(aritcle);*/       }       tx.commit();       session.close();              int currPage = ((offsetStart-1) + maxPageItems) / maxPageItems;       if((offsetStart-1) % maxPageItems != 0)           currPage++;       int totalPage = itemCount/maxPageItems;       if(itemCount % maxPageItems != 0)           totalPage++;              mav.addObject("itemCount", itemCount);       mav.addObject("maxPageItems", maxPageItems);       mav.addObject("maxIndexPages", maxIndexPages);       mav.addObject("offsetStart", offsetStart);       mav.addObject("currPage", currPage);       mav.addObject("totalPage", totalPage);       mav.addObject("keywords", keywords);       mav.addObject("keyStr", keyStr);       mav.addObject("dataList", list);       return mav;    }  

?

search.jsp

?

<%@page contentType="text/html; charset=utf-8"%><%@include file="header.jsp"%><%@ include file="../common/taglibs.jsp"%><%@include file="menu.jsp"%><div items="${dataList}">                      <c:set var="content" value="${data.content}" />                      <%                        String content = (String)pageContext.getAttribute("content");                      %>                                                  <li>                            <c:choose>                              <c:when test="${fn:contains(data.class, 'Book')}">                              <h5><a href="bookshow.jsp?id=${data.id}" target="_blank">${data.title}</a></h5>                              </c:when>                              <c:when test="${fn:contains(data.class, 'News')}">                              <c:set var="url" value="${data.url}" />                              <c:if test="${empty data.url}">                                <c:set var="url" value="newsshow.jsp?id=${data.id}" />                              </c:if>                              <h5><a href="newsshow.jsp?id=${data.id}" target="_blank">${data.title}</a></h5>                              </c:when>                                               </c:choose>                              <div end="${totalPage - 1}" step="1" varStatus="status">                          <a href="search.do?keywords=${keywords}&pager.offset=${status.index * maxPageItems}" <c:if test="${status.index == (currPage-1)}">maxPageItems="${maxPageItems}" maxIndexPages="${maxIndexPages}" export="offset,currentPageNumber=pageNumber" scope="request" url="search.do"><pg:index><jsp:include page="pager/searchPagerControl.jsp" flush="true"/></pg:index></pg:pager></div>                    </c:if>                    <c:if test="${empty dataList}">                      暂时没有您要查找的信息!                    </c:if></div></div><!-- pagebox_1 --></div><%@include file="footer.jsp"%>

?

searchPageControl.jsp

<%@page contentType="text/html;charset=utf-8"%><%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %><%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %><%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %><%@ page session="false" %><%@ taglib uri="http://jsptags.com/tags/navigation/pager" prefix="pg" %><pg:param name="keywords" value="${keyStr}" /><jsp:useBean id="currentPageNumber" type="java.lang.Integer" scope="request"/><pg:prev export="pageUrl" ifnull="<%= true %>"><c:if test="${not empty pageUrl }"><a href="${pageUrl }">上一页</a></c:if></pg:prev><pg:pages><c:if test="${pageNumber == currentPageNumber }"><a href="#" ifnull="<%= true %>">  <c:if test="${not empty pageUrl }"> <a href="${pageUrl }">下一页</a></c:if></pg:next>
1 楼 wangjianjun852 2012-05-26 请问一下楼主, 用过compass+spring+hibernate的组合吗?

读书人网 >软件架构设计

热点推荐