在上一篇文章中主要講了,配置要索引的表和compass與spring整合時的配置。接下來我把餘下的兩部分寫出來。
第三步:配置手動建立索引的功能。
這個其實隻需在第一次生成索引的時候用,當系統正常運作時,compass中的hibernateGps會自動檢測資料的變動,同時同步索引檔案的。
首先在applicationContext.xml中配置bean.
<!-- 手工生成索引 -->
<bean id="buildIndexController"
class="org.compass.spring.web.mvc.CompassIndexController">
<property name="compassGps" ref="hibernateGps" />
<property name="indexView" value="/ftl/create.ftl" />
<property name="indexResultsView" value="/ftl/create.ftl" />
</bean>
同時我們也要配置與之相應的請求映射。
<bean id="urlHandlerMapping"
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/buildindex.htm">buildIndexController</prop>
</props>
</property>
最後就是自動生成索引的頁面了,這裡我用的是freemarker.用什麼都一樣,你可以用jsp,html.
create.ftl(在WebRoot下的ftl檔案夾下)
<html>
<head>
<title>builderIndex</title>
</head>
<body>
<h1>
手工重建索引
</h1>
<p>
<form name="keyword" action="/buildindex.htm" method="post">
<INPUT type="hidden" name="doIndex" value="true">
<input type="submit" value="手工重建索引" />
</form>
<#if indexResults?exists>
本次索引耗時${indexResults.indexTime}毫秒!
</#if>
<p>
</body>
</html>
當我們點選手工重建索引按鈕時,會在我們指定的索引目錄下<prop key="compass.engine.connection">E:/video</prop>也就先在E:/video下生成gpsindex/video-index當索引生成完以後,會傳回生成索引所用的毫秒數。這時就會把gpsindex檔案夾下的video-index覆寫到E:/video/index/下的video-index檔案夾。這時gpsindex/video-index也消失了。這就是簡單的生成索引的過程。接下來我們要說最後一步了。索引我們已建好了,怎麼去搜尋我們想要的資料了。
第四步:建立搜尋功能。
首先寫一個controller.即searchController.java
public class SearchController extends AbstractCompassCommandController {
private String searchView;
private String searchResultsView;
private String searchResultsName = "searchResults";
private Integer pageSize;
private Integer sectionSize;
private CompassSearchHelper searchHelper;
public CompassSearchHelper getSearchHelper() {
return searchHelper;
}
public SearchController() {
setCommandClass(CompassSearchCommand.class);
public void afterPropertiesSet() throws Exception {
super.afterPropertiesSet();
if (searchView == null) {
throw new IllegalArgumentException(
"Must set the searchView property");
}
if (searchResultsView == null) {
"Must set the serachResultsView property");
if (searchHelper == null) {
searchHelper = new CompassSearchHelper(getCompass(), getPageSize());
protected ModelAndView handle(HttpServletRequest request,
HttpServletResponse response, Object command, BindException errors)
throws Exception {
Log log4j = LogFactory.getLog("video");
log4j.info("SearchController say: hello");
final CompassSearchCommand searchCommand = (CompassSearchCommand) command;
String query = searchCommand.getQuery();
searchCommand.setQuery(query);
if (!StringUtils.hasText(searchCommand.getQuery())) {
return new ModelAndView(getSearchView(), getCommandName(),
searchCommand);
CompassSearchResults searchResults = searchHelper.search(searchCommand);
log4j.info("searchResults.getHits().length = "
+ searchResults.getHits().length);
CompassPage page = new CompassPage(searchResults.getHits(),
pageSize.intValue(),
searchCommand.getPage().intValue() + 1,
searchResults.getTotalHits(),
sectionSize.intValue(),
searchCommand.getQuery(),
searchResults.getSearchTime());
return new ModelAndView(getSearchResultsView(), "data", page);
/**
* Returns the view that holds the screen which the user will initiate the
* search operation.
*/
public String getSearchView() {
return searchView;
* Sets the view that holds the screen which the user will initiate the
public void setSearchView(String searchView) {
this.searchView = searchView;
* Returns the name of the results that the
* saved under. Defaults to "searchResults".
public String getSearchResultsName() {
return searchResultsName;
* Sets the name of the results that the
public void setSearchResultsName(String searchResultsName) {
this.searchResultsName = searchResultsName;
* Returns the view which will show the results of the search operation.
public String getSearchResultsView() {
return searchResultsView;
* Sets the view which will show the results of the search operation.
public void setSearchResultsView(String resultsView) {
this.searchResultsView = resultsView;
* Sets the page size for the pagination of the results. If not set, not
* pagination will be used.
public Integer getPageSize() {
return pageSize;
* Returns the page size for the pagination of the results. If not set, not
*
* @param pageSize
* The page size when using paginated results
public void setPageSize(Integer pageSize) {
this.pageSize = pageSize;
* <p>
* The search helper is used to execute teh actual search. By default (if
* not set) the search controller will create a new search helper. If
* provided, the search controller will use it to perform the search.
* Mainly used to extend the search helper and execute additional operation
* within specific calbacks the search helper exposes.
* @param searchHelper
* A specific search helper to use
public void setSearchHelper(CompassSearchHelper searchHelper) {
this.searchHelper = searchHelper;
public Integer getSectionSize() {
return sectionSize;
public void setSectionSize(Integer sectionSize) {
this.sectionSize = sectionSize;
}
還需要一個CompassPage.java主要來實作分頁的。
public class CompassPage implements Page {
private CompassHit[] elements;
private int pageSize;
private int pageNumber;
private int totalElements = 0;
private int sectionSize;
private String query;
private long searchTime;
public long getSearchTime() {
return searchTime;
public void setSearchTime(long searchTime) {
this.searchTime = searchTime;
* @param pageNumber
* 目前頁編碼,從1開始,如果傳的值為Integer.MAX_VALUE表示擷取最後一頁。
* 如果你不知道最後一頁編碼,傳Integer.MAX_VALUE即可。如果目前頁超過總頁數,也表示最後一頁。
* 這兩種情況将重新更改目前頁的頁碼為最後一頁編碼。
* 每一頁顯示的條目數
* @param sectionSize
* 每一節顯示的頁數.
public CompassPage(CompassHit[] elements, int pageSize, int pageNumber, int totalElements, int sectionSize, String query, long searchTime) {
super();
this.elements = elements;
this.pageNumber = pageNumber;
this.totalElements = totalElements;
this.query = query;
if (Integer.MAX_VALUE == this.pageNumber
|| this.pageNumber > getLastPageNumber()) // last page
{
this.pageNumber = getLastPageNumber();
}
public String getQuery() {
return query;
public void setQuery(String query) {
public CompassHit[] getElements() {
return elements;
public void setElements(CompassHit[] elements) {
public int getPageNumber() {
return pageNumber;
public void setPageNumber(int pageNumber) {
public int getSectionSize() {
public void setSectionSize(int sectionSize) {
public int getTotalElements() {
return totalElements;
public void setTotalElements(int totalElements) {
public void setPageSize(int pageSize) {
public int getLastPageNumber() {
return totalElements % this.pageSize == 0 ? totalElements
/ this.pageSize : totalElements / this.pageSize + 1;
public int getNextPageNumber() {
return getThisPageNumber() + 1;
public int getNextSectionFirstPageNumber() {
return (pageNumber / sectionSize + 1) * sectionSize + 1;
public int getPageSize() {
public int getPreviousPageNumber() {
return (getThisPageNumber() == 1) ? 1 : getThisPageNumber() - 1;
public int getPreviousSectionFirstPageNumber() {
return (pageNumber / sectionSize - 1) * sectionSize + 1;
public Object getThisPageElements() {
public int getThisPageFirstElementNumber() {
return (getThisPageNumber() - 1) * getPageSize() + 1;
public int getThisPageLastElementNumber() {
int fullPage = getThisPageFirstElementNumber() + getPageSize() - 1;
return getTotalNumberOfElements() < fullPage ? getTotalNumberOfElements()
: fullPage;
public int getThisPageNumber() {
public int getThisSectionFirstPageNumber() {
return (getThisPageNumber() % sectionSize == 0) ? getThisPageNumber()
/ sectionSize * sectionSize : getThisPageNumber() / sectionSize
* sectionSize + 1;
public int getThisSectionLastPageNumber() {
int fullSection = (getThisPageNumber() / sectionSize + 1) * sectionSize;
return getLastPageNumber() < fullSection ? getLastPageNumber()
: fullSection;
public List getThisSectionPagesBar() {
// 翻頁 頁碼條
List pagesBar = new ArrayList();
if (hasPreviousSection()) { // 不是第一捆
if (hasNextSection()) {// 不是最後一捆
for (int j = getPreviousSectionFirstPageNumber() + sectionSize; j <= getNextSectionFirstPageNumber() - 1; j++) {
pagesBar.add(new Integer(j));
}
} else { // 是最後一捆
for (int j = getPreviousSectionFirstPageNumber() + sectionSize; j <= (getLastPageNumber()); j++) {
}
} else { // 是第一捆
// log4j.info("是第一捆 getLastPageNumber()=" + getLastPageNumber());
for (int j = 1; j <= (getLastPageNumber() < sectionSize ? getLastPageNumber()
: sectionSize); j++) {
// log4j.info("j=" + j);
pagesBar.add(new Integer(j));
return pagesBar;
public int getTotalNumberOfElements() {
public boolean hasNextPage() {
return getLastPageNumber() > getThisPageNumber();
public boolean hasNextSection() {
return getLastPageNumber() > (pageNumber / sectionSize + 1)
* sectionSize;
public boolean hasPreviousPage() {
return getThisPageNumber() > 1;
public boolean hasPreviousSection() {
return pageNumber / sectionSize * sectionSize > 1;
public boolean isFirstPage() {
return getThisPageNumber() == 1;
public boolean isLastPage() {
return getThisPageNumber() >= getLastPageNumber();
在定義一個分頁接口Page.java。
/**
* 分頁資訊接口
*/
public interface Page
{
/**
* 是否是首頁(第一頁),第一頁頁碼為1
*
* @return 首頁辨別
*/
public boolean isFirstPage();
* 是否是最後一頁
* @return 末頁辨別
public boolean isLastPage();
* 是否有下一頁
* @return 下一頁辨別
public boolean hasNextPage();
* 是否有上一頁
* @return 上一頁辨別
public boolean hasPreviousPage();
是否有下一個頁面單元
*/
public boolean hasNextSection();
/**是否有前一個頁面單元*/
public boolean hasPreviousSection();
* 擷取最後一頁頁碼,也就是總頁數
* @return 最後一頁頁碼
public int getLastPageNumber();
* 目前頁包含的資料,不同的情況可能傳回的資料類型不一樣,如List,RowSet等,請參考具體的實作
* @return 目前頁資料源
public Object getThisPageElements();
* 總的資料條目數量,0表示沒有資料
* @return 總數量
public int getTotalNumberOfElements();
* 擷取目前頁的首條資料的行編碼
* @return 目前頁的首條資料的行編碼
public int getThisPageFirstElementNumber();
* 擷取目前頁的末條資料的行編碼
* @return 目前頁的末條資料的行編碼
public int getThisPageLastElementNumber();
* 擷取下一頁編碼
* @return 下一頁編碼
public int getNextPageNumber();
* 擷取上一頁編碼
* @return 上一頁編碼
public int getPreviousPageNumber();
/* 擷取下一個頁面單元的第一頁 */
public int getNextSectionFirstPageNumber();
/* 擷取前一個頁面單元的第一頁 */
public int getPreviousSectionFirstPageNumber();
* 每一頁顯示的條目數
* @return 每一頁顯示的條目數
public int getPageSize();
* 目前頁的頁碼
* @return 目前頁的頁碼
public int getThisPageNumber();
/*
目前片斷第一頁頁碼
public int getThisSectionFirstPageNumber();
public int getThisSectionLastPageNumber();
/*
*目前片斷 頁碼表
public List getThisSectionPagesBar();
最後要配置一下bean和請求映射了。
<bean id="urlHandlerMapping"
<prop key="/search.htm">searchController</prop>
</props>
<!-- 搜尋的控制器 -->
<bean id="searchController"
class="com.jack.video.SearchController" lazy-init="true">
<property name="compass" ref="compass" />
<property name="searchView" value="/ftl/search.ftl" />
<property name="searchResultsView"
value="/ftl/search.ftl" />
<property name="pageSize" value="10" />
<property name="sectionSize" value="10" />
<property name="searchHelper">
<ref local="advanceCompassSearchHelper" />
最後為了能給搜尋到的結果高亮顯示。還需要配置。
<!-- 高亮字段顯示 -->
<bean id="advanceCompassSearchHelper"
class="com.jack.video.util.AdvanceCompassSearchHelper">
<property name="highlightFields">
<list>
<value>CName</value>
</list>
<property name="pageSize">
<value>10</value>
<constructor-arg ref="compass" />
AdvanceCompassSearchHelper .java檔案
public class AdvanceCompassSearchHelper extends CompassSearchHelper {
private String[] highlightFields;
public String[] getHighlightFields() {
return highlightFields;
public void setHighlightFields(String[] highlightFields) {
this.highlightFields = highlightFields;
* @param compass
public AdvanceCompassSearchHelper(Compass compass) {
super(compass);
/*
* (non-Javadoc)
* @see org.compass.core.support.search.CompassSearchHelper#doProcessBeforeDetach(org.compass.core.support.search.CompassSearchCommand,
* org.compass.core.CompassSession, org.compass.core.CompassHits, int,
* int)
@Override
protected void doProcessBeforeDetach(CompassSearchCommand searchCommand,
CompassSession session, CompassHits hits, int from, int size) {
if (from < 0) {
from = 0;
size = hits.getLength();
if (highlightFields == null) {
return;
// highlight fields
for (int i = from; i < size; i++) {
for (String highlightField : highlightFields) {
hits.highlighter(i).fragment(highlightField);
最後就剩下簡單的搜尋頁面和顯示頁面了。
這是搜尋頁主要的代碼。
本文轉自 weijie@java 51CTO部落格,原文連結:http://blog.51cto.com/weijie/74363,如需轉載請自行聯系原作者