以下是鄙人在学习compass所做的笔记(如果鄙人写的不是很清楚的话,可以从电驴或者迅雷上搜索v521刘伟老师的compass学习视频)。系统框架采用Struts2.1.6+Spring2.5.4+Hibernate3+compass2.1.0,JDK版本采用6.0的。
首先,需要将将SSH整合好。具体的我不在此说明,可以在google上进行搜索。我将重点说明compass如何与SSH进行整合。
使用compass框架,首先需要进行compass关于实体类的映射。compass在其文档中说明,一般是在实体类相对应的*.cpm.xml中进行配置的。但是在开发中,我们可以借助jdk关于标注的新特性,将此文件省略。具体代码如下所示:
- package com.zhou.model;
- import java.io.Serializable;
- import org.compass.annotations.Searchable;
- import org.compass.annotations.SearchableId;
- import org.compass.annotations.SearchableProperty;
- @Searchable
- public class Product implements Serializable {
- private static final long serialVersionUID = -3148838659193709682L;
- //Field
- @SearchableId
- private String id;
- @SearchableProperty(name="name")
- private String name;
- @SearchableProperty(name="price")
- private Integer price;
- @SearchableProperty(name="brand")
- private String brand;
- @SearchableProperty(name="description")
- private String description;
- // Constructors
- /** default constructor */
- public Product() {
- }
- /** full constructor */
- public Product(String name, Integer price, String brand, String description) {
- this.name = name;
- this.price = price;
- this.brand = brand;
- this.description = description;
- }
- // Property accessors
- public String getId() {
- return this.id;
- }
- public void setId(String id) {
- this.id = id;
- }
- public String getName() {
- return this.name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public Integer getPrice() {
- return this.price;
- }
- public void setPrice(Integer price) {
- this.price = price;
- }
- public String getBrand() {
- return this.brand;
- }
- public void setBrand(String brand) {
- this.brand = brand;
- }
- public String getDescription() {
- return this.description;
- }
- public void setDescription(String description) {
- this.description = description;
- }
- }
如代码所示,实体类的类声明和属性声明分别加入了相应的标注。public class前面的“@Searchable”表示此类可以被索引,也就是此类对应的数据库可以被索引。属性id前的“@SearchableId”表示索引建立的id。其他属性前面的“@SearchableProperty(name="name")”表示此字段可以被索引、被检索。name=“name”表示此字段被索引后的名称。在检索类中,可以根据此名字指定搜索的字段名称。
建立索引的类(CompassIndexBuilder.java)
- package com.zhou.service.impl;
- import java.util.Date;
- import org.compass.gps.CompassGps;
- import org.springframework.beans.factory.InitializingBean;
- public class CompassIndexBuilder implements InitializingBean {
- private boolean buildIndex = false;
- private int lazyTime = 5;
- private CompassGps compassGps;
- private Thread indexThread = new Thread() {
- public void run() {
- try {
- Thread.sleep(lazyTime * 1000);
- System.out.println("begin compass index...");
- long beginTime = System.currentTimeMillis();
- compassGps.index();
- long costTime = System.currentTimeMillis() - beginTime;
- System.out.println("compss index finished.");
- System.out.println("costed " + costTime + " milliseconds");
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- };
- public void afterPropertiesSet() throws Exception {
- System.out.println(new Date()+"调用");
- if (buildIndex) {
- indexThread.setDaemon(true);
- indexThread.setName("Compass Indexer");
- indexThread.start();
- }
- }
- public void setBuildIndex(boolean buildIndex) {
- this.buildIndex = buildIndex;
- }
- public void setLazyTime(int lazyTime) {
- this.lazyTime = lazyTime;
- }
- public void setCompassGps(CompassGps compassGps) {
- this.compassGps = compassGps;
- }
- }
详细的解释可以观看视频,在此不再说明。
将compass的配置写在同一个文件(applicationContext-compass)中,以便同一管理。内容如下:
- <?xml version="1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"
- default-lazy-init="true">
- <!-- 如果使用jdk标注新特性,此处必须有的 -->
- <bean id="annotationConfiguration" class="org.compass.annotations.config.CompassAnnotationsConfiguration">
- </bean>
- <bean id="compass" class="org.compass.spring.LocalCompassBean">
- <property name="resourceDirectoryLocations">
- <list>
- <value>classpath:com/zhou</value>
- </list>
- </property>
- <property name="connection">
- <value>/lucene/indexes</value>
- </property>
- <property name="classMappings">
- <list>
- <value>com.zhou.model.Product</value>
- </list>
- </property>
- <property name="compassConfiguration"
- ref="annotationConfiguration" />
- <property name="compassSettings">
- <props>
- <prop key="compass.transaction.factory">
- org.compass.spring.transaction.SpringSyncTransactionFactory
- </prop>
- <prop
- key="compass.engine.analyzer.MMAnalyzer.CustomAnalyzer">
- net.paoding.analysis.analyzer.PaodingAnalyzer
- </prop>
- <prop
- key="compass.engine.highlighter.default.formatter.simple.pre">
- <!--[CDATA[<font color="red"><b>]]>
- </prop>
- <prop
- key="compass.engine.highlighter.default.formatter.simple.post">
- <![CDATA[</b></font>]]-->
- </prop>
- </props>
- </property>
- <property name="transactionManager" ref="transactionManager" />
- </bean>
- <bean id="hibernateGpsDevice"
- class="org.compass.gps.device.hibernate.HibernateGpsDevice">
- <property name="name">
- <value>hibernateDevice</value>
- </property>
- <property name="sessionFactory" ref="sessionFactory" />
- <property name="mirrorDataChanges">
- <value>true</value>
- </property>
- </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>
- <bean
- class="org.compass.spring.device.SpringSyncTransactionGpsDeviceWrapper">
- <property name="gpsDevice" ref="hibernateGpsDevice" />
- </bean>
- </list>
- </property>
- </bean>
- <bean id="compassTemplate"
- class="org.compass.core.CompassTemplate">
- <property name="compass" ref="compass" />
- </bean>
- <!-- 定时重建索引(利用quartz)或随Spring ApplicationContext启动而重建索引 -->
- <bean id="compassIndexBuilder"
- class="com.zhou.service.impl.CompassIndexBuilder" lazy-init="false">
- <property name="compassGps" ref="compassGps" />
- <property name="buildIndex" value="true" />
- <property name="lazyTime" value="5" />
- </bean>
- </beans>
在业务层进行数据检索的代码如下:
- public List<Product> searchProducts(String queryString) {
- List<Product> products = new ArrayList<Product>();
- Compass compass = compassTemplate.getCompass();
- CompassSession session = compass.openSession();
- CompassHits hits = session.queryBuilder().queryString(
- "name:" + queryString).toQuery().hits();
- System.out.println("---------------------------------------------");
- System.out.println("queryString=" + queryString);
- System.out.println("结果个数=" + hits.length());
- for (int i = 0; i < hits.length(); i++) {
- Product hit = (Product) hits.data(i);
- String ht = hits.highlighter(i).fragment("name");
- if (null != ht) {
- hit.setName(ht);
- }
- products.add(hit);
- }
- return products;
- }
以上是关键部分的说明。在bs层中的检索方法searchProducts(String queryString)中,有很多地方需要深入的思考一下。比如:在“CompassHits hits = session.queryBuilder().queryString("name:" + queryString).toQuery().hits();”中的“name”就是至前面实体类中的“@SearchableProperty(name="name")”中“name”的值,表示只对该字段进行检索。又比如涉及到结果分页显示的话,该如何封装返回的结果。究竟是一次全部封装到List中还是每页显示n条就封装n条,翻页的时候继续hit呢?有待深入思考。
附件为样例程序,但是相关的jar包太大了,无法上传!需要自己查找。