由于是个资讯类的项目,加上把项目的结构进行了重新部署(基于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" class="org.compass.annotations.config.CompassAnnotationsConfiguration"></bean>
<bean id="compass" class="org.compass.spring.LocalCompassBean">
<!-- anontaition式设置 -->
<property name="classMappings">
<list>
<value>com.model.Book</value>
<value>com.model.News</value>
</list>
</property>
<property name="compassConfiguration" 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" class="org.compass.spring.device.hibernate.dep.SpringHibernate3GpsDevice">
<property name="name">
<value>hibernateDevice</value>
</property>
<property name="sessionFactory" ref="sessionFactory"/>
<property name="mirrorDataChanges">
<value>true</value><!-- 同步更新索引 -->
</property>
</bean>
<bean id="compassGps" class="org.compass.gps.impl.SingleCompassGps" init-method="start" destroy-method="stop">
<property name="compass" ref="compass"/>
<property name="gpsDevices">
<bean id="hibernateGpsDevice2" class="org.compass.spring.device.hibernate.dep.SpringHibernate3GpsDevice">
<property name="name" value="hibernateDevice"></property>
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
</property>
</bean>
<bean id="compassTemplate" class="org.compass.core.CompassTemplate">
<property name="compass" ref="compass" />
</bean>
<!-- 定时重建索引(利用quartz)或随 Spring ApplicationContext启动而重建索引 -->
<bean id="compassIndexBuilder"
class="com.compass.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
@Controller
public class CompassSearchController {
@Autowired
private 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 class="breadcrumbs">您的位置:<a href="./">首页</a> > <span>搜索结果</span></div>
<div class="content">
<div class="pagebox_1">
<h4 class="boxtitle"><strong>“${keywords}”的搜索结果${keystr},总共${itemCount}条记录</strong></h4>
<div class="boxtext">
<c:if test="${not empty dataList}">
<ul class="newslist_1">
<c:forEach var="data" 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}" class="sort">[ 图书 ]</a><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}" class="sort">[ 资讯与动态 ]</a><a href="${url}" target="_blank">${data.title}</a></h5>
</c:when>
</c:choose>
<div class="text"><%=StringExtract.extractText2(StringUtils.abbreviate(content,150))%></div>
</li>
</c:forEach>
</ul>
<!--<c:if test="${totalPage > 1}">
<div class="turnpage">
<c:forEach begin="0" 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)}">class="cur"</c:if>>${status.index + 1}</a>
</c:forEach>
</div>
</c:if>-->
<div class="turnpage"> <pg:pager items="${itemCount}" 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="#" class="cur">${pageNumber }</a></c:if>
<c:if test="${pageNumber != currentPageNumber }"><a href="${pageUrl }">${pageNumber }</a></c:if>
</pg:pages>
<pg:next export="pageUrl" ifnull="<%= true %>">
<c:if test="${not empty pageUrl }"> <a href="${pageUrl }">下一页</a></c:if>
</pg:next>
本文介绍了一个基于Compass的全文检索系统集成方案,包括配置详解、索引重建机制及搜索控制器实现。
1083

被折叠的 条评论
为什么被折叠?



