经过三天的折腾,终于把Compass整合SSH搞定了,下边贴出源码,给正在学习的朋友,毕竟网上关于Compass的详细介绍还是太少了。
我用到的版本是struts2+spring 2.5 +hibernate 3.2+compass 2.2+Quartz 1.6
一、创建一张表,表名PRODUCT
CREATE TABLE "LICE"."PRODUCT"
( "PRODUCT_ID" VARCHAR2(40) NOT NULL ENABLE,
"PRODUCT_NAME" VARCHAR2(80),
"PRODUCT_PRICE" NUMBER(6,2),
"PRODUCT_BRAND" VARCHAR2(40),
"PRODUCT_DESC" VARCHAR2(200),
"VERSION" NUMBER(10,0),
PRIMARY KEY ("PRODUCT_ID")
)
二、PRODUCT表对应的实体类
package com.lice.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Version;
import org.hibernate.annotations.GenericGenerator;
import org.compass.annotations.*;
@Entity
@Table(name = "PRODUCT", schema = "LICE")
@Searchable
public class Product implements java.io.Serializable {
// Fields
@SearchableId
private String productId;
@SearchableProperty(name="productName")
private String productName;
@SearchableProperty(name="productPrice")
private Double productPrice;
@SearchableProperty(name="productBrand")
private String productBrand;
@SearchableProperty(name="productDesc")
private String productDesc;
@SearchableProperty(name="version")
private Integer version;
// Constructors
public Product() {
}
public Product(String productName, Double productPrice,
String productBrand, String productDesc) {
this.productName = productName;
this.productPrice = productPrice;
this.productBrand = productBrand;
this.productDesc = productDesc;
}
// Property accessors
@GenericGenerator(name = "generator", strategy = "uuid.hex")
@Id
@GeneratedValue(generator = "generator")
@Column(name = "PRODUCT_ID", unique = true, nullable = false, length = 40)
public String getProductId() {
return this.productId;
}
public void setProductId(String productId) {
this.productId = productId;
}
@Column(name = "PRODUCT_NAME", length = 80)
public String getProductName() {
return this.productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
@Column(name = "PRODUCT_PRICE", precision = 6)
public Double getProductPrice() {
return this.productPrice;
}
public void setProductPrice(Double productPrice) {
this.productPrice = productPrice;
}
@Column(name = "PRODUCT_BRAND", length = 40)
public String getProductBrand() {
return this.productBrand;
}
public void setProductBrand(String productBrand) {
this.productBrand = productBrand;
}
@Column(name = "PRODUCT_DESC", length = 200)
public String getProductDesc() {
return this.productDesc;
}
public void setProductDesc(String productDesc) {
this.productDesc = productDesc;
}
@Version
public Integer getVersion() {
return version;
}
public void setVersion(Integer version) {
this.version = version;
}
}
注意如果要用hibernate查询,model里必须加上@SearchableProperty(name="XXXX")这种注释。
三、对象的DAO和实现类
import java.util.List;
import com.lice.model.Product;
public interface ProductDao {
public void create(Product p);
public Product getProduct(String id);
public List getProducts();
public void update(Product product);
public void remove(String id);
}
package com.lice.dao.hibernate;
import java.util.List;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import com.lice.dao.ProductDao;
import com.lice.model.Product;
public class ProductDaoHibernate extends HibernateDaoSupport implements ProductDao {
public void create(Product p) {
getHibernateTemplate().save(p);
}
public Product getProduct(String id) {
return (Product)getHibernateTemplate().get(Product.class, id);
}
public List getProducts() {
return getHibernateTemplate().find("from Product order by id desc");
}
public void remove(String id) {
getHibernateTemplate().delete(getProduct(id));
}
public void update(Product product) {
getHibernateTemplate().saveOrUpdate(product);
}
}
四、对应的Service和实现类
import java.util.List;
import com.lice.model.Product;
public interface ProductManager {
public void insertProduct(Product p);
public Product findProdcut(String id);
}
package com.lice.service.impl;
import java.util.ArrayList;
import java.util.List;
import com.lice.dao.ProductDao;
import com.lice.model.Product;
import com.lice.service.ProductManager;
public class ProductManagerImpl implements ProductManager {
private ProductDao productDao;
public Product findProdcut(String id) {
return productDao.getProduct(id);
}
public void insertProduct(Product p) {
productDao.create(p);
}
public ProductDao getProductDao() {
return productDao;
}
public void setProductDao(ProductDao productDao) {
this.productDao = productDao;
}
}
五、对应的action
package com.lice.action;
import java.util.List;
import org.apache.struts2.ServletActionContext;
import com.lice.model.Product;
import com.lice.service.CompassManager;
import com.lice.service.ProductManager;
import com.opensymphony.xwork2.ActionSupport;
public class ProductAction extends ActionSupport{
private static final long serialVersionUID = -2189044281576376151L;
private ProductManager productManager;
private CompassManager compassManager;
private Product product;
private String queryString;
public String insert(){
productManager.insertProduct(product);
return SUCCESS;
}
public String search(){
List results=compassManager.productCompass(queryString);
System.out.println(results.size());
ServletActionContext.getRequest().setAttribute("searchresults", results);
return SUCCESS;
}
public ProductManager getProductManager() {
return productManager;
}
public void setProductManager(ProductManager productManager) {
this.productManager = productManager;
}
public Product getProduct() {
return product;
}
public void setProduct(Product product) {
this.product = product;
}
public String getQueryString() {
return queryString;
}
public void setQueryString(String queryString) {
this.queryString = queryString;
}
public CompassManager getCompassManager() {
return compassManager;
}
public void setCompassManager(CompassManager compassManager) {
this.compassManager = compassManager;
}
}
六、配置文件applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd" default-lazy-init="true">
<!-- load jdbc.properties -->
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:jdbc.properties</value>
</list>
</property>
</bean>
<!-- 定义数据源的Bean ,给Hibernate的sessionFactory-->
<bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
<property name="maxActive" value="${jdbc.maxActive}"/>
<property name="maxWait" value="${jdbc.maxWait}"/>
<property name="poolPreparedStatements" value="${jdbc.poolPreparedStatements}"/>
<property name="defaultAutoCommit" value="${jdbc.defaultAutoCommit}"/>
<property name="logAbandoned" value="${jdbc.logAbandoned}"/>
<property name="removeAbandoned" value="${jdbc.removeAbandoned}"/>
<property name="removeAbandonedTimeout" value="${jdbc.removeAbandonedTimeout}"/>
</bean>
<!-- 定义Hibernate的sessionFactory,通过该Bean,可以获得Hibernate的Session-->
<!-- 如果hibernate用了annotation,这里必须用AnnotationSessionFactoryBean -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource"><ref bean="dataSource" /></property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle9Dialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.cache.use_second_level_cache">true</prop>
<prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop>
<prop key="hibernate.jdbc.fetch_size">30</prop>
<prop key="hibernate.jdbc.batch_size">50</prop>
<prop key="hibernate.statement_cache.size">0</prop>
</props>
</property>
<property name="configLocation" value="classpath:hibernate.cfg.xml" />
</bean>
<bean name="productDao" class="com.lice.dao.hibernate.ProductDaoHibernate">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<bean name="productManager" class="com.lice.service.impl.ProductManagerImpl ">
<property name="productDao" ref="productDao"></property>
<property name="compassTemplate" ref="compassTemplate"></property>
</bean>
<bean id="compassManager" class="com.lice.service.impl.CompassManagerImpl">
<property name="compassTemplate" ref="compassTemplate"></property>
</bean>
<bean id="productBean" class="com.lice.action.ProductAction" scope="prototype">
<property name="productManager" ref="productManager"></property>
<property name="compassManager" ref="compassManager"></property>
</bean>
<!-- 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory">
<ref local="sessionFactory"/>
</property>
</bean>
<!-- 配置事务特性,配置add、delete和update开始的方法,事务传播特性为required-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="insert*" propagation="REQUIRED"/>
<tx:method name="delete*" propagation="REQUIRED"/>
<tx:method name="update*" propagation="REQUIRED"/>
<tx:method name="*" read-only="true"/>
</tx:attributes>
</tx:advice>
<!-- 配置那些类的方法进行事务管理,当前com.lice.service包中的子包、类中所有方法需要,还需要参考tx:advice的设置 -->
<aop:config>
<aop:pointcut id="allManagerMethod" expression="execution (* com.lice.service.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="allManagerMethod"/>
</aop:config>
</beans>
七、配置文件applicationContext-compass.xml
<?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">
<!-- productMapping Mapping -->
<bean id="productMapping"
class="org.compass.gps.device.jdbc.mapping.ResultSetToResourceMapping">
<property name="alias"> <value>product</value></property>
<property name="indexUnMappedColumns"><value>false</value></property>
<property name="selectQuery">
<value>
select t.product_id as productId ,t.version as version,t.product_name as productName
,t.product_price as productPrice ,t.product_brand as productBrand
,t.product_desc as productDesc from product t
</value>
</property>
<property name="versionQuery">
<value>
select t.product_id as productId ,COALESCE(t.version, 0) as version from product t
</value>
</property>
<property name="idMappings">
<list>
<bean class="org.compass.gps.device.jdbc.mapping.IdColumnToPropertyMapping">
<property name="columnName"><value>productId</value></property>
<property name="propertyName"><value>productId</value></property>
<property name="columnNameForVersion"><value>t.product_id</value></property>
</bean>
</list>
</property>
<property name="dataMappings">
<list>
<bean class="org.compass.gps.device.jdbc.mapping.DataColumnToPropertyMapping">
<property name="columnName"><value>productName</value></property>
<property name="propertyName"><value>productName</value></property>
</bean>
<bean class="org.compass.gps.device.jdbc.mapping.DataColumnToPropertyMapping">
<property name="columnName"><value>productPrice</value></property>
<property name="propertyName"><value>productPrice</value></property>
</bean>
<bean class="org.compass.gps.device.jdbc.mapping.DataColumnToPropertyMapping">
<property name="columnName"><value>productBrand</value></property>
<property name="propertyName"><value>productBrand</value></property>
</bean>
<bean class="org.compass.gps.device.jdbc.mapping.DataColumnToPropertyMapping">
<property name="columnName"><value>productDesc</value></property>
<property name="propertyName"><value>productDesc</value></property>
</bean>
</list>
</property>
<property name="versionMappings">
<list>
<bean class="org.compass.gps.device.jdbc.mapping.VersionColumnMapping">
<property name="columnName"><value>version</value></property>
</bean>
</list>
</property>
</bean>
<bean id="productMappingResolver"
class="org.compass.gps.device.jdbc.ResultSetResourceMappingResolver">
<property name="mapping"><ref local="productMapping" /></property>
<property name="dataSource"><ref bean="dataSource" /></property>
</bean>
<bean id="compass" class="org.compass.spring.LocalCompassBean">
<property name="mappingResolvers">
<list>
<ref local="productMappingResolver" />
</list>
</property>
<property name="compassSettings">
<props>
<prop key="compass.engine.connection">target/compass</prop>
<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.analyzer.MMAnalyzer.CustomAnalyzer">
org.apache.lucene.annalysis.cn.SmartChineseAnalyzer
</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="jdbcGpsDevice" class="org.compass.gps.device.jdbc.ResultSetJdbcGpsDevice">
<property name="name"><value>jdbcDevice</value></property>
<property name="dataSource"><ref bean="dataSource" /></property>
<!-- 同步更新索引 -->
<property name="mirrorDataChanges"><value>false</value></property>
<property name="saveSnapshotAfterMirror"><value>false</value></property>
<property name="mappings">
<list>
<ref local="productMapping" />
</list>
</property>
<property name="snapshotPersister">
<bean class="org.compass.gps.device.jdbc.snapshot.FSJdbcSnapshotPersister">
<property name="path" value="target/compass/snapshot" />
</bean>
</property>
</bean>
<bean id="scheduledJdbcGpsDevice" class="org.compass.gps.device.ScheduledMirrorGpsDevice">
<property name="gpsDevice" ref="jdbcGpsDevice" />
<property name="mirrorDataChanges" value="true"></property>
<property name="period">
<value>1800000</value>
</property>
</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">
<property name="compass" ref="compass" />
<property name="gpsDevices">
<list>
<ref bean="scheduledJdbcGpsDevice"/>
</list>
</property>
</bean>
<bean id="compassTemplate" class="org.compass.core.CompassTemplate">
<property name="compass" ref="compass" />
</bean>
</beans>
八、定时触发的Java文件和配置文件applicationContext-jobs.xml
package com.lice.task;
import org.apache.log4j.Logger;
import org.compass.gps.CompassGps;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.scheduling.quartz.QuartzJobBean;
public class CompassTask extends QuartzJobBean{
private Logger log = Logger.getLogger(CompassTask.class);
private CompassGps compassGps;
protected void executeInternal(JobExecutionContext context)
throws JobExecutionException {
long beginTime = System.currentTimeMillis();
log.info("--------compass job----------");
if (compassGps == null)
return;
log.info("-------- compass job start ---------");
compassGps.index();
log.info("-------- compass job end -------- :" + (System.currentTimeMillis() - beginTime));
}
public CompassGps getCompassGps() {
return compassGps;
}
public void setCompassGps(CompassGps compassGps) {
this.compassGps = compassGps;
}
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<!-- Quartz Scheduler, with pre-registered triggers -->
<!-- Will automatically start scheduling on context startup -->
<bean id="scheduler"
class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref local="compassTrigger" />
</list>
</property>
</bean>
<!-- 触发器-->
<bean id="compassTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">
<!-- 装配将要被调度的工作 -->
<property name="jobDetail" ref="compassJob" />
<!-- 延迟工作的第一次执行时间 eg.120秒后 -->
<property name="startDelay" value="120000" />
<!-- 触发器运行这个工作的频度(以毫秒作为单位 -->
<property name="repeatInterval" value="300000" />
</bean>
<!-- 定时触发 -->
<bean id="cronCompassTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="jobDetail" ref="compassJob" />
<property name="cronExpression">
<value>0 0 6 * * ?</value>
</property>
</bean>
<bean name="compassJob" class="org.springframework.scheduling.quartz.JobDetailBean">
<property name="jobClass">
<value>com.lice.task.CompassTask</value>
</property>
<!-- 给 CompassTask要注入的参数-->
<property name="jobDataAsMap">
<map>
<entry key="compassGps">
<ref bean="compassGps"/>
</entry>
</map>
</property>
</bean>
</beans>
九、配置一个中文分词paoding-dic-home.properties
paoding.dic.home=C:/paoding/dic
paoding.dic.detector.interval=60
十、hibernate.cfg.xml
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<mapping class="com.lice.model.Product"/>
</session-factory>
</hibernate-configuration>
十一、启动加载的一个lintener
package com.lice.listener;
import java.io.File;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.compass.gps.CompassGps;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
public class StartupListener implements ServletContextListener {
private static final Log log = LogFactory.getLog(StartupListener.class);
public static ApplicationContext ctx = null;
public void contextDestroyed(ServletContextEvent arg0) {
// TODO Auto-generated method stub
}
public void contextInitialized(ServletContextEvent event) {
ServletContext context = event.getServletContext();
try{
ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(context);
CompassGps compassGps=(CompassGps) ctx.getBean("compassGps");
if(!compassGps.isRunning()){
compassGps.start();
log.info("删除现有索引");
File f=new File("lucene/indexes");
if(f.exists()){
deleteFiles(f);
}
log.info("原始索引文件删除完毕");
log.info("compass开始构建索引");
new Thread(){
public void run(){
try{
((CompassGps)ctx.getBean("compassGps")).index();
log.info("compass成功构建索引");
}catch(Exception e){
e.printStackTrace();
log.error("compass构建索引失败",e);
}
}
}.start();
}
}catch(Exception e){
log.error("加载compass错误",e);
}
}
private void deleteFiles(File tmpFile){
if(tmpFile.isDirectory()){
for(File file:tmpFile.listFiles()){
deleteFiles(file);
}
}else{
tmpFile.delete();
}
}
}