`

Compass将lucene、Spring、Hibernate三者结合

阅读更多
Java代码 复制代码 收藏代码
  1. 1.概述   
  2. Compass将lucene、Spring、Hibernate三者的起来,以很低很低的成本快速实现企业应用中的搜索功能。    
  3. HomePage: http://www.opensymphony.com/compass/     
  4. springside里用了compass来做图书搜索,快速建立的流程如下:    
  5. 1.用简单的compass annotation把Book对象映射到Lucene。    
  6. 2.配置compass默认提供的基于Spring MVC的Index Controller 和Search Controller。    
  7. 3.编写查询结果的显示页面,将controller返回的变量显示出来。    
  8.   
  9. 2.Object/Search Engine Mapping的 Annotations配置    
  10. 使用JDK5 的annotation 来进行OSEM(Object/Search Engine Mapping)比用xml文件按简单许多,下面就是简单的搜索类,可见@SearchableID@SearchableProperty@SearchableComponent 三个标记,分别代表主键、可搜索的属性与关联的,另一个可搜索的对象,另外Compass要求POJO要有默认构造函数,要实现equals()和hashcode():    
  11. 详细请点击查看springside中的Product.java ,  Book.java, Category.java    
  12.  public class Product  {           
  13. @SearchableId      
  14. private Integer id;       
  15. private Category category;       
  16. private String name;       
  17. private Double unitprice;       
  18. @SearchableProperty(name = "name")      
  19.  public String getName() {        return this.name;    }       
  20. @SearchableComponent (refAlias = "category")       
  21. public Category getCategory() {        return this.category;    }      
  22.  public Double getUnitprice() {        return this.unitprice;    }     
  23.     
  24. 3. 与spring,hibernate集成配置    
  25. 3.1 spring配置文件   
  26. hiberante中的sessionFactory,transactionManager相比大家也是轻车熟路了.compass已经对对spring集成做了很好的封装,让我们的使用更加简单,我们可以不为compass编写一行代码,就可以做完搜索引擎的检索.下面是compass在spring中的简明配置. 详情点击查看springside中的applicationContext-lucene.xml  :     
  27. <beans>   
  28. <bean id="annotationConfiguration"          class="org.compass.annotations.config.CompassAnnotationsConfiguration"></bean>   
  29. <bean id="compass" class="org.compass.spring.LocalCompassBean">   
  30.    <!-- anontaition式设置     -->     
  31.   <property name="classMappings">   
  32.      <list>   
  33.         <value>org.springside.bookstore.domain.Book</value>   
  34.      </list>   
  35.   </property>   
  36.   <property name="compassConfiguration" ref="annotationConfiguration"/>   
  37.    <property name="compassSettings">   
  38.         <props>   
  39.             <prop key="compass.engine.connection">file://${user.home}/springside/compass</prop>   
  40.             <prop key="compass.transaction.factory">org.compass.spring.transaction.SpringSyncTransactionFactory</prop>   
  41.         </props>   
  42.     </property>   
  43.    <property name="transactionManager" ref="transactionManager"/>   
  44.  </bean>   
  45.   <bean id="hibernateGpsDevice" class="org.compass.spring.device.hibernate.SpringHibernate3GpsDevice">   
  46.      <property name="name">   
  47.         <value>hibernateDevice</value>   
  48.      </property>   
  49.      <property name="sessionFactory" ref="sessionFactory"/>   
  50.  </bean>   
  51. <bean id="compassGps" class="org.compass.gps.impl.SingleCompassGps" init-method="start" destroy-method="stop">   
  52.   <property name="compass" ref="compass"/>   
  53.   <property name="gpsDevices">   
  54.       <list>   
  55.           <ref local="hibernateGpsDevice"/>   
  56.       </list>   
  57.   </property>   
  58.  </bean>   
  59. </beans>      
  60. 上面要留意的配置有:    
  61. annotationConfiguration: 使用annotation配置,指定要转换的POJO如Book   
  62. compass.engine.connection : 索引文件在服务器上的存储路径.   
  63. hibernateGpsDevice: 与hibernate的绑定,用Hibernate 3 事件系统,支持Real Time Data Mirroring .经Hiberante的数据改变会自动被反射到索引里面.    
  64. 3.2 web Controller的配置   
  65. 两个Controller都是现成的,只要配置相关选项即可。    
  66. 详情请查看springside的bookstore-servlet.xml    
  67. <bean id="indexBookController" class="org.compass.spring.web.mvc.CompassIndexController">      
  68. <property name="compassGps" ref="compassGps"/>       
  69. <property name="indexView" value="/admin/indexBook.jsp"/>       
  70. <property name="indexResultsView" value="/admin/indexBook.jsp"/>   
  71. </bean><bean id="searchBookController" class="org.compass.spring.web.mvc.CompassSearchController">     
  72.  <property name="compass" ref="compass"/>     
  73.  <propertyname="searchView"value="/home/top.jsp"/>     
  74.  <property name="searchResultsView" value="/home/searchBook.jsp"/>      
  75. <property name="pageSize" value="5"/></bean>     
  76.     
  77. 3.3 View JSP    
  78.   简单搜索页面:只需要一个query 参数:    
  79. <INPUT type="text" size="20" name="query">    
  80. 结果页面:    
  81. 结果页面将返回几个变量,包括:    
  82. searchResults(搜索结果) 包括hits(结果)和 searchtime(耗时)    
  83.     pages(分页信息) 包括page_from page_to等   
  84.     command(原来的查询请求)    
  85. 具体使用见springside的advancedSearch.jsp ,下面是简版的代码:    
  86.   <c:if test="${not empty searchResults}">       耗时:   
  87.  <c:out value="http://www.zhmy.com/${searchResults.searchTime}"/>ms         
  88.  <c:forEach var="hit" items="${searchResults.hits}">               
  89.  <c:choose>                    
  90.  <c:when test="${hit.alias == 'book'}">                           
  91.  <div class="left_content">                                   
  92.  <a href="#" class"title"> 《${hit.data.name}》</a>  <br/> 作者:${hit.data.author}<br/>                           
  93. </div>                       
  94. </c:when>                 
  95. </c:choose>           
  96. </c:forEach></c:if>     
  97.     
  98. 4.扩展高级搜索   
  99. 扩展高级搜索其实很简单,SpringSide已经初步封装了加入包含以下任意单词,不包含以下任何单词,分类选择等条件及每页显示条数的确定。    
  100. 如果需要更多条件:    
  101. 1. 加强搜索页面,加入更多条件的显示。    
  102. 2. 扩展compass的command class,接受从搜索条件页传过来的条件。 可从springside的AdvancedSearchCommand  扩展或从Compass的原类扩展。    
  103. 3. 扩展compass的searchController, 将command中的变量重新处理为一个符合Lucene语法规则的query变量 即可(见springside中的AdvancedSearchController ),同时可以为搜索条件页查询图书分类列表一类的变量。    
  104.    你可以从springside的AdvancedSearchController扩展,重载onSetupCommand (),参考父类的做法,加装自己的条件。重载referenceData(),把图书分类列表这种条件加入到AdvancedSearchCommand 的referenceData Map中供搜索条件页显示,例子见BookSearchController。    
  105. 也可以参考BookSearchController和AdvancedSearchController的做法,完全自行扩展。   
  106.     
  107.     
  108. 其实compass只是简单的应用的话,也很容易上手的    
  109. 假如使用了hibernate+spring+compass    
  110. 关于compass在spring中的配置如下,保存为一个xml文件,在web.xml中引入即可    
  111. Java代码    
  112. <?xml version="1.0" encoding="UTF-8"?>      
  113. <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">      
  114. <beans>      
  115.     <bean id="annotationConfiguration" class="org.compass.annotations.config.CompassAnnotationsConfiguration"></bean>      
  116.      
  117.     <bean id="compass" class="org.compass.spring.LocalCompassBean">      
  118.         <!-- 这里的配置意思是指需要搜索的POJO对象 -->      
  119.         <property name="classMappings">      
  120.             <list>      
  121.                 <value>com.tourye.model.TnInfomation</value>      
  122.             </list>      
  123.         </property>      
  124.                 <!-- 这里的配置意思是指使用annotation进行compass配置 -->      
  125.         <property name="compassConfiguration" ref="annotationConfiguration" />      
  126.         <property name="compassSettings">      
  127.             <props>      
  128.                 <prop key="compass.engine.connection">/home/dev/compass</prop>这里说明索引文件所放的目录      
  129.                 <prop key="compass.transaction.factory">org.compass.spring.transaction.SpringSyncTransactionFactory</prop>      
  130.                 <!-- <prop key="compass.engine.analyzer.default.type">net.paoding.analysis.analyzer.PaodingAnalyzer</prop> -->这里的注释是为了说明使用paoding的分词器,由于测试时,有时会出问题,所以暂时禁用      
  131.             </props>      
  132.         </property>      
  133.         <property name="transactionManager">      
  134.             <ref bean="transactionManager" />      
  135.         </property>      
  136.         <!--      
  137.             高亮设置,未测试成功,需要相关的代码辅助 <property name="compass.engine.highlighter.default.formatter.simple.pre"> <value><![CDATA[<font      
  138.             color="red"><b>]]></value> </property> <property name="compass.engine.highlighter.default.formatter.simple.post">      
  139.             <value><![CDATA[</b></font>]]></value> </property>      
  140.         -->      
  141.     </bean>      
  142.         下面的两段配置是为了说明compass构建索引与hibernate的insert/delete/update操作同步      
  143.     <bean id="hibernateGpsDevice" class="org.compass.gps.device.hibernate.HibernateGpsDevice">      
  144.         <property name="name">      
  145.             <value>hibernateDevice</value>      
  146.         </property>      
  147.         <property name="sessionFactory">      
  148.             <ref bean="mySessionFactory" />      
  149.         </property>      
  150.         <property name="nativeExtractor">      
  151.             <bean class="org.compass.spring.device.hibernate.SpringNativeHibernateExtractor" />      
  152.         </property>      
  153.     </bean>      
  154.      
  155.     <bean id="compassGps" class="org.compass.gps.impl.SingleCompassGps" init-method="start" destroy-method="stop">      
  156.         <property name="compass">      
  157.             <ref bean="compass" />      
  158.         </property>      
  159.         <property name="gpsDevices">      
  160.             <list>      
  161.                 <bean class="org.compass.spring.device.SpringSyncTransactionGpsDeviceWrapper">      
  162.                     <property name="gpsDevice" ref="hibernateGpsDevice" />      
  163.                 </bean>      
  164.             </list>      
  165.         </property>      
  166.     </bean>      
  167.      
  168.     <!-- 自动随Spring ApplicationContext启动而重建索引,未研究 -->      
  169.     <bean id="compassIndexBuilder" class="com.tourye.service.timer.CompassIndexBuilder" lazy-init="false">      
  170.         <property name="compassGps" ref="compassGps" />      
  171.         <property name="buildIndex" value="true" />      
  172.         <property name="lazyTime" value="10" />      
  173.     </bean>      
  174. </beans>     
  175.     
  176. 第二步:    
  177. 使用annotatio声明要索引的object,如下所示,自己根据需要进行设置    
  178. Java代码    
  179. @Searchable     
  180. public class TnInfomation implements java.io.Serializable {      
  181.     private static final long serialVersionUID = -4503017770118428686L;      
  182.           
  183.     @SearchableId(name = "id")      
  184.     private Long              id;      
  185.           
  186.     private int               type;      
  187.     @SearchableProperty(name="title")      
  188.     private String            title;      
  189.     @SearchableProperty(name="keywords")      
  190.     private String            keywords;      
  191.     @SearchableProperty(name="content")      
  192.     private String            content;      
  193.     private int               author;      
  194.     private Date              createtime;      
  195.     private Date              updatetime;      
  196.     @SearchableProperty(name="approvetime")      
  197.     private Date              approvetime;      
  198.     private int               clicks;      
  199.     private int               critiques;      
  200.     private String            provenance;      
  201.     @SearchableProperty(name="status")      
  202.     private byte              status; /* 待审核(0) 已审核(1)*/     
  203.     
  204. 第三步,建立搜索service    
  205. Java代码    
  206. public class InfomationSearchServiceImpl implements InfomationSearchService {      
  207.     private Compass compass;      
  208.      
  209.     public Compass getCompass() {      
  210.         return compass;      
  211.     }      
  212.      
  213.     public void setCompass(Compass compass) {      
  214.         this.compass = compass;      
  215.     }      
  216.      
  217.     /*    
  218.      * (non-Javadoc)    
  219.      *     
  220.      * @see    
  221.      * com.tourye.infomation.compass.InfomationSearchService#search(java.lang    
  222.      * .String, int, int)    
  223.      */     
  224.     public CompassSearchResults search(String query, int page, int pageSize) throws Exception {      
  225.         CompassSession session = compass.openSession();      
  226.         try {      
  227.             session.beginTransaction();      
  228.             //构建compass查询编辑器      
  229.             CompassQueryBuilder querybuilder = session.queryBuilder();      
  230.             CompassQuery cq = null;      
  231.             CompassSearchCommand csc = null;      
  232.             //声明查询条件,query是查询字符串      
  233.             if (StringUtils.isNotEmpty(query)) {      
  234.                 cq = querybuilder.bool().addMust(querybuilder.spanEq("status"1)).addMust(      
  235.                         querybuilder.queryString(query).toQuery()).toQuery();      
  236.                 cq.addSort("approvetime", CompassQuery.SortDirection.REVERSE);      
  237.                 csc = new CompassSearchCommand(cq, new Integer(Math.max(0, page - 1)));      
  238.             } else {      
  239.                 csc = new CompassSearchCommand(query.trim());      
  240.             }      
  241.             // 搜索命令InfomationSearchHelper和CompassSearchHelper相同,自己可以实现      
  242.             InfomationSearchHelper searchHelper = new InfomationSearchHelper(compass, pageSize);      
  243.             CompassSearchResults searchResults = searchHelper.search(csc);      
  244.      
  245.             return searchResults;      
  246.         } finally {      
  247.             if (session != null) session.close();      
  248.         }      
  249.     }      
  250. }  
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics