1.概述
Compass将lucene、Spring、Hibernate三者的起来,以很低很低的成本快速实现企业应用中的搜索功能。
HomePage: http://www.opensymphony.com/compass/
springside里用了compass来做图书搜索,快速建立的流程如下:
1.用简单的compass annotation把Book对象映射到Lucene。
2.配置compass默认提供的基于Spring MVC的Index Controller 和Search Controller。
3.编写查询结果的显示页面,将controller返回的变量显示出来。
2.Object/Search Engine Mapping的 Annotations配置
使用JDK5 的annotation 来进行OSEM(Object/Search Engine Mapping)比用xml文件按简单许多,下面就是简单的搜索类,可见@SearchableID, @SearchableProperty与@SearchableComponent 三个标记,分别代表主键、可搜索的属性与关联的,另一个可搜索的对象,另外Compass要求POJO要有默认构造函数,要实现equals()和hashcode():
详细请点击查看springside中的Product.java , Book.java, Category.java
public class Product {
@SearchableId
private Integer id;
private Category category;
private String name;
private Double unitprice;
@SearchableProperty(name = "name")
public String getName() { return this.name; }
@SearchableComponent (refAlias = "category")
public Category getCategory() { return this.category; }
public Double getUnitprice() { return this.unitprice; }
3. 与spring,hibernate集成配置
3.1 spring配置文件
hiberante中的sessionFactory,transactionManager相比大家也是轻车熟路了.compass已经对对spring集成做了很好的封装,让我们的使用更加简单,我们可以不为compass编写一行代码,就可以做完搜索引擎的检索.下面是compass在spring中的简明配置. 详情点击查看springside中的applicationContext-lucene.xml :
<beans>
<bean id="annotationConfiguration" class="org.compass.annotations.config.CompassAnnotationsConfiguration"></bean>
<bean id="compass" class="org.compass.spring.LocalCompassBean">
<!-- anontaition式设置 -->
<property name="classMappings">
<list>
<value>org.springside.bookstore.domain.Book</value>
</list>
</property>
<property name="compassConfiguration" ref="annotationConfiguration"/>
<property name="compassSettings">
<props>
<prop key="compass.engine.connection">file://${user.home}/springside/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.SpringHibernate3GpsDevice">
<property name="name">
<value>hibernateDevice</value>
</property>
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<bean id="compassGps" class="org.compass.gps.impl.SingleCompassGps" init-method="start" destroy-method="stop">
<property name="compass" ref="compass"/>
<property name="gpsDevices">
<list>
<ref local="hibernateGpsDevice"/>
</list>
</property>
</bean>
</beans>
上面要留意的配置有:
annotationConfiguration: 使用annotation配置,指定要转换的POJO如Book
compass.engine.connection : 索引文件在服务器上的存储路径.
hibernateGpsDevice: 与hibernate的绑定,用Hibernate 3 事件系统,支持Real Time Data Mirroring .经Hiberante的数据改变会自动被反射到索引里面.
3.2 web Controller的配置
两个Controller都是现成的,只要配置相关选项即可。
详情请查看springside的bookstore-servlet.xml
<bean id="indexBookController" class="org.compass.spring.web.mvc.CompassIndexController">
<property name="compassGps" ref="compassGps"/>
<property name="indexView" value="/admin/indexBook.jsp"/>
<property name="indexResultsView" value="/admin/indexBook.jsp"/>
</bean><bean id="searchBookController" class="org.compass.spring.web.mvc.CompassSearchController">
<property name="compass" ref="compass"/>
<propertyname="searchView"value="/home/top.jsp"/>
<property name="searchResultsView" value="/home/searchBook.jsp"/>
<property name="pageSize" value="5"/></bean>
3.3 View JSP
简单搜索页面:只需要一个query 参数:
<INPUT type="text" size="20" name="query">
结果页面:
结果页面将返回几个变量,包括:
searchResults(搜索结果) 包括hits(结果)和 searchtime(耗时)
pages(分页信息) 包括page_from page_to等
command(原来的查询请求)
具体使用见springside的advancedSearch.jsp ,下面是简版的代码:
<c:if test="${not empty searchResults}"> 耗时:
<c:out value="http://www.zhmy.com/${searchResults.searchTime}"/>ms
<c:forEach var="hit" items="${searchResults.hits}">
<c:choose>
<c:when test="${hit.alias == 'book'}">
<div class="left_content">
<a href="#" class= "title"> 《${hit.data.name}》</a> <br/> 作者:${hit.data.author}<br/>
</div>
</c:when>
</c:choose>
</c:forEach></c:if>
4.扩展高级搜索
扩展高级搜索其实很简单,SpringSide已经初步封装了加入包含以下任意单词,不包含以下任何单词,分类选择等条件及每页显示条数的确定。
如果需要更多条件:
1. 加强搜索页面,加入更多条件的显示。
2. 扩展compass的command class,接受从搜索条件页传过来的条件。 可从springside的AdvancedSearchCommand 扩展或从Compass的原类扩展。
3. 扩展compass的searchController, 将command中的变量重新处理为一个符合Lucene语法规则的query变量 即可(见springside中的AdvancedSearchController ),同时可以为搜索条件页查询图书分类列表一类的变量。
你可以从springside的AdvancedSearchController扩展,重载onSetupCommand (),参考父类的做法,加装自己的条件。重载referenceData(),把图书分类列表这种条件加入到AdvancedSearchCommand 的referenceData Map中供搜索条件页显示,例子见BookSearchController。
也可以参考BookSearchController和AdvancedSearchController的做法,完全自行扩展。
其实compass只是简单的应用的话,也很容易上手的
假如使用了hibernate+spring+compass
关于compass在spring中的配置如下,保存为一个xml文件,在web.xml中引入即可
Java代码
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="annotationConfiguration" class="org.compass.annotations.config.CompassAnnotationsConfiguration"></bean>
<bean id="compass" class="org.compass.spring.LocalCompassBean">
<!-- 这里的配置意思是指需要搜索的POJO对象 -->
<property name="classMappings">
<list>
<value>com.tourye.model.TnInfomation</value>
</list>
</property>
<!-- 这里的配置意思是指使用annotation进行compass配置 -->
<property name="compassConfiguration" ref="annotationConfiguration" />
<property name="compassSettings">
<props>
<prop key="compass.engine.connection">/home/dev/compass</prop>这里说明索引文件所放的目录
<prop key="compass.transaction.factory">org.compass.spring.transaction.SpringSyncTransactionFactory</prop>
<!-- <prop key="compass.engine.analyzer.default.type">net.paoding.analysis.analyzer.PaodingAnalyzer</prop> -->这里的注释是为了说明使用paoding的分词器,由于测试时,有时会出问题,所以暂时禁用
</props>
</property>
<property name="transactionManager">
<ref bean="transactionManager" />
</property>
<!--
高亮设置,未测试成功,需要相关的代码辅助 <property name="compass.engine.highlighter.default.formatter.simple.pre"> <value><![CDATA[<font
color="red"><b>]]></value> </property> <property name="compass.engine.highlighter.default.formatter.simple.post">
<value><![CDATA[</b></font>]]></value> </property>
-->
</bean>
下面的两段配置是为了说明compass构建索引与hibernate的insert/delete/update操作同步
<bean id="hibernateGpsDevice" class="org.compass.gps.device.hibernate.HibernateGpsDevice">
<property name="name">
<value>hibernateDevice</value>
</property>
<property name="sessionFactory">
<ref bean="mySessionFactory" />
</property>
<property name="nativeExtractor">
<bean class="org.compass.spring.device.hibernate.SpringNativeHibernateExtractor" />
</property>
</bean>
<bean id="compassGps" class="org.compass.gps.impl.SingleCompassGps" init-method="start" destroy-method="stop">
<property name="compass">
<ref bean="compass" />
</property>
<property name="gpsDevices">
<list>
<bean class="org.compass.spring.device.SpringSyncTransactionGpsDeviceWrapper">
<property name="gpsDevice" ref="hibernateGpsDevice" />
</bean>
</list>
</property>
</bean>
<!-- 自动随Spring ApplicationContext启动而重建索引,未研究 -->
<bean id="compassIndexBuilder" class="com.tourye.service.timer.CompassIndexBuilder" lazy-init="false">
<property name="compassGps" ref="compassGps" />
<property name="buildIndex" value="true" />
<property name="lazyTime" value="10" />
</bean>
</beans>
第二步:
使用annotatio声明要索引的object,如下所示,自己根据需要进行设置
Java代码
@Searchable
public class TnInfomation implements java.io.Serializable {
private static final long serialVersionUID = -4503017770118428686L;
@SearchableId(name = "id")
private Long id;
private int type;
@SearchableProperty(name="title")
private String title;
@SearchableProperty(name="keywords")
private String keywords;
@SearchableProperty(name="content")
private String content;
private int author;
private Date createtime;
private Date updatetime;
@SearchableProperty(name="approvetime")
private Date approvetime;
private int clicks;
private int critiques;
private String provenance;
@SearchableProperty(name="status")
private byte status; /* 待审核(0) 已审核(1)*/
第三步,建立搜索service
Java代码
public class InfomationSearchServiceImpl implements InfomationSearchService {
private Compass compass;
public Compass getCompass() {
return compass;
}
public void setCompass(Compass compass) {
this.compass = compass;
}
/*
* (non-Javadoc)
*
* @see
* com.tourye.infomation.compass.InfomationSearchService#search(java.lang
* .String, int, int)
*/
public CompassSearchResults search(String query, int page, int pageSize) throws Exception {
CompassSession session = compass.openSession();
try {
session.beginTransaction();
//构建compass查询编辑器
CompassQueryBuilder querybuilder = session.queryBuilder();
CompassQuery cq = null;
CompassSearchCommand csc = null;
//声明查询条件,query是查询字符串
if (StringUtils.isNotEmpty(query)) {
cq = querybuilder.bool().addMust(querybuilder.spanEq("status", 1)).addMust(
querybuilder.queryString(query).toQuery()).toQuery();
cq.addSort("approvetime", CompassQuery.SortDirection.REVERSE);
csc = new CompassSearchCommand(cq, new Integer(Math.max(0, page - 1)));
} else {
csc = new CompassSearchCommand(query.trim());
}
// 搜索命令InfomationSearchHelper和CompassSearchHelper相同,自己可以实现
InfomationSearchHelper searchHelper = new InfomationSearchHelper(compass, pageSize);
CompassSearchResults searchResults = searchHelper.search(csc);
return searchResults;
} finally {
if (session != null) session.close();
}
}
}
Compass将lucene、Spring、Hibernate三者结合
最新推荐文章于 2024-08-12 17:42:17 发布