用compass快速给你的网站添加搜索功能<二>
版权声明:原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://weijie.blog.51cto.com/340746/74363 |
用compass快速给你的网站添加搜索功能<二>
在上一篇文章中主要讲了,配置要索引的表和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> </bean> 最后就是自动生成索引的页面了,这里我用的是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) { 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=""> 现在把快速给你的网站搭建搜索功能已讲完。写的过程中可能有不对的地方,希望你在调试的时候该过来。 基本的实现原理及过程已讲了,至于如何用,就看你自己来。 我主要快速的把要点讲了一下。里面还有很多细节。有时间的话再和大家讨论。 本文出自 “魏杰的技术专栏” 博客,请务必保留此出处http://weijie.blog.51cto.com/340746/74363 本文出自 51CTO.COM技术博客 |



weijie@java
博客统计信息
热门文章
最新评论
友情链接