您的位置:首页 > 运维架构 > 网站架构

用compass快速给你的网站添加搜索功能<三>

2012-09-06 23:17 465 查看
第四步:建立搜索功能。
首先写一个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) {

throw new IllegalArgumentException(

"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

* search operation.

*/

public void setSearchView(String searchView) {

this.searchView = searchView;

}
/**

* Returns the name of the results that the

* {@link org.compass.core.support.search.CompassSearchResults} will be

* saved under. Defaults to "searchResults".

*/

public String getSearchResultsName() {

return searchResultsName;

}
/**

* Sets the name of the results that the

* {@link org.compass.core.support.search.CompassSearchResults} will be

* saved under. Defaults to "searchResults".

*/

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

* pagination will be used.

*

* @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.

*

* <p>

* 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 pageSize

* 每一页显示的条目数

* @param sectionSize

* 每一节显示的页数.

*/

public CompassPage(CompassHit[] elements, int pageSize, int pageNumber, int totalElements, int sectionSize, String query, long searchTime) {

super();

this.elements = elements;

this.pageSize = pageSize;

this.pageNumber = pageNumber;

this.totalElements = totalElements;

this.sectionSize = sectionSize;

this.query = query;

this.searchTime = searchTime;

if (Integer.MAX_VALUE == this.pageNumber

|| this.pageNumber > getLastPageNumber()) // last page

{

this.pageNumber = getLastPageNumber();

}

}
public String getQuery() {

return query;

}
public void setQuery(String query) {

this.query = query;

}
public CompassHit[] getElements() {

return elements;

}
public void setElements(CompassHit[] elements) {

this.elements = elements;

}
public int getPageNumber() {

return pageNumber;

}
public void setPageNumber(int pageNumber) {

this.pageNumber = pageNumber;

}
public int getSectionSize() {

return sectionSize;

}
public void setSectionSize(int sectionSize) {

this.sectionSize = sectionSize;

}
public int getTotalElements() {

return totalElements;

}
public void setTotalElements(int totalElements) {

this.totalElements = totalElements;

}
public void setPageSize(int pageSize) {

this.pageSize = 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() {

return pageSize;

}
public int getPreviousPageNumber() {

return (getThisPageNumber() == 1) ? 1 : getThisPageNumber() - 1;

}
public int getPreviousSectionFirstPageNumber() {

return (pageNumber / sectionSize - 1) * sectionSize + 1;

}
public Object getThisPageElements() {

return elements;

}
public int getThisPageFirstElementNumber() {

return (getThisPageNumber() - 1) * getPageSize() + 1;

}
public int getThisPageLastElementNumber() {

int fullPage = getThisPageFirstElementNumber() + getPageSize() - 1;

return getTotalNumberOfElements() < fullPage ? getTotalNumberOfElements()

: fullPage;

}
public int getThisPageNumber() {

return pageNumber;

}
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++) {

pagesBar.add(new Integer(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() {

return totalElements;

}
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"

class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">

<property name="mappings">

<props>

<prop key="/search.htm">searchController</prop>

</props>

</property>

</bean>

<!-- 搜索的控制器 -->

<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" />

</property>

</bean>

最后为了能给搜索到的结果高亮显示。还需要配置。
<!-- 高亮字段显示 -->

<bean id="advanceCompassSearchHelper"

class="com.jack.video.util.AdvanceCompassSearchHelper">

<property name="highlightFields">

<list>

<value>CName</value>

</list>

</property>

<property name="pageSize">

<value>10</value>

</property>

<constructor-arg ref="compass" />

</bean>

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);

}

}

}

}

最后就剩下简单的搜索页面和显示页面了。
这是搜索页主要的代码。
<form method="get" action="/search.htm">	<input type="text" size="50" name="query" value="${query?if_exists}" />      <input type="hidden" name="page" value="1"/>

<input type="submit" value="搜索" /></form>

以下是结果页的主要代码。

<#macro s_search_result data="" config="">
<script type="text/javascript">
var videoList = {
channelId: ${channelId}
};
</script>
<div class="box">
<div class="ir_box">
<div class="title">
<@s_option_button />
<ul class="tag_menu">
<li><a class="current" href="javascript:;"><span>搜索结果</span></a></li>
</ul>
</div>
<div class="content">
<@s_module_config data=config />
<div class="show_mode">
</div>
<div class="show_mode">
<ul class="nonce_mode">
<li>共有 ${data.totalElements} 项符合 ${data.query} 的查询结果</li>
<li>第 ${data.pageNumber}/${data.lastPageNumber} 页</li>
<li>用时 ${data.searchTime} 毫秒</li>
</ul>
<ul class="choose_mode">
<li></li>
<li></li>
</ul>
</div>
<#if data.elements?exists && data.elements?has_content >
<#list data.elements as d>
<div class="veol_cloud">

<div class="vec_content">

<div class="vec_info">
<p>
<strong>名字:</strong><@s_se v=d.data.description />
</p>
<p>
<strong>导演:</strong>
<span class="null_director"><@s_se v=d.data.director /></span>
</p>

<p>
<strong>类型:</strong>
<span class="null_genre"><@s_se v=d.data.genre /></span>
</p>

</div>

</div>
</div>
</div>
</#list>
<ul class="paging">
<li>
<span>共有 <b>${data.totalElements}</b> 项 第 <b>${data.pageNumber}</b> / <b>${data.lastPageNumber}</b> 页</span>
</li>
<li>
<a href="/search.htm?query=${data.query}&page=1" title="第一页">←</a>
</li>
<#if (data.getThisSectionFirstPageNumber()>1)>
<li>
<a href="/search.htm?query=${data.query}&page=${data.getThisSectionFirstPageNumber()}" title="快速向前翻10页" /><<</a>
</li>
</#if>
<#if (data.getPreviousPageNumber()>1)>
<li>
<a href="/search.htm?query=${data.query}&page=${data.getPreviousPageNumber()}" title="向前翻1页" /><</a>
</li>
</#if>
<#if data.getThisSectionPagesBar()?exists>
<#list data.getThisSectionPagesBar() as d>
<li>
<a href="/search.htm?query=${data.query}&page=${d}">${d}</a>
</li>
</#list>
</#if>
<#if (data.getNextPageNumber()<=data.lastPageNumber)>
<li>
<a href="/search.htm?query=${data.query}&page=${data.getNextPageNumber()}" title="向后翻1页" />></a>
</li>
</#if>
<#if (data.getNextSectionFirstPageNumber()<=data.lastPageNumber)>
<li>
<a href="/search.htm?query=${data.query}&page=${data.getNextSectionFirstPageNumber()}" title="快速向后翻10页" />>></a>
</li>
</#if>
<li>
<a href="/search.htm?query=${data.query}&page=${data.lastPageNumber}" title="最后一页">→</a>
</li>
</ul>
<#else>
暂无相关影片
</#if>
</div>
</div>
</div>
</#macro>

现在把快速给你的网站搭建搜索功能已讲完。写的过程中可能有不对的地方,希望你在调试的时候该过来。

基本的实现原理及过程已讲了,至于如何用,就看你自己来。

我主要快速的把要点讲了一下。里面还有很多细节。有时间的话再和大家讨论。

转自:http://jackweijie.iteye.com/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: