赞
踩
CompassTemplate ct = (CompassTemplate) context.getBean("compassTemplate");Article article = new Article();article.setTitle("Compass Test");article.setPublishDate(new Date());article.setAuthor(1);ct.save(article); //存储对象需要索引的数据到Compass的索引中。
import org.apache.log4j.Logger;import java.util.Date;import junit.framework.TestCase;import org.compass.core.Compass;import org.compass.core.CompassDetachedHits;import org.compass.core.CompassHit;import org.compass.core.CompassHits;import org.compass.core.CompassSession;import org.compass.core.CompassTemplate;import org.compass.core.CompassTransaction;import org.compass.core.support.search.CompassSearchCommand;import org.compass.core.support.search.CompassSearchResults;import org.springframework.context.support.ClassPathXmlApplicationContext;import com.mobilesoft.esales.dao.hibernate.ArticleDAO;import com.mobilesoft.esales.dao.hibernate.AuthorDAO;import com.mobilesoft.esales.model.Article;import com.mobilesoft.esales.model.Author;import com.mobilesoft.framework.search.service.CompassSearchService;/** * Compass服务使用的测试用例 * * @author liangchuan@mobile-soft.cn * */public class TestCompass extends TestCase { private static final Logger logger = Logger.getLogger(TestCompass.class); private static ClassPathXmlApplicationContext context = null; private static CompassTemplate ct; static { context = new ClassPathXmlApplicationContext(new String[] { "applicationContext.xml", "applicationContext-resources.xml", "applicationContext-dao.xml", "applicationContext-service.xml", "applicationContext-compass.xml" }); ct = (CompassTemplate) context.getBean("compassTemplate"); } protected void setUp() throws Exception { } /** * 插入测试数据 */ public void testInsert() { ArticleDAO articleDao = (ArticleDAO) context.getBean("articleDAO"); AuthorDAO authorDao = (AuthorDAO) context.getBean("authorDAO"); Article article = new Article(); Author author = new Author(); author.setAge((short) 27); author.setUsername("liangchuan"); author.setPassword("liangchuan"); article.setTitle("Compass Test"); article.setPublishDate(new Date()); article.setAuthor(1); authorDao.save(author); articleDao.save(article); ct.save(article); ct.save(author); } /** * 用于测试使用CompassTransaction事务方式 */ public void testTransactionalFind() { Compass compass = ct.getCompass(); CompassSession session = compass.openSession(); CompassTransaction tx = null; try { tx = session.beginTransaction(); CompassHits hits = session.find("Compass*"); logger.error("testTransactionalFind() - CompassHits hits=" + hits.getLength()); for (int i = 0; i < hits.getLength(); i++) { Object hit = hits.data(i); if (hit instanceof Article) { Article item = (Article) hit; logger.error("testTransactionalFind() - article hits=" + item.getTitle()); } else if (hit instanceof Author) { Author item = (Author) hit; logger.error("testTransactionalFind() - author hits=" + item.getUsername()); } else { logger.error("testTransactionalFind() - error hits="); } } tx.commit(); } catch (Exception e) { if (tx != null) { tx.rollback(); } } finally { session.close(); } } /** * 用于演示CompassDetachedHits的使用。 * 由于CompassTempalte得到的结果集必须在transactionalcontext中才能使用, * 因此必须使用CompassDetachedHits方式测试CompassDetachedHits方式 */ public void testDetachedFind() { // 由于CompassTempalte得到的结果集必须在transactional // context中才能使用,因此必须使用CompassDetachedHits方式 // 测试CompassDetachedHits方式 CompassDetachedHits hits = ct.findWithDetach("Compass*"); logger.error("testDetachedFind() - CompassHits hits=" + hits.getLength()); for (int i = 0; i < hits.getLength(); i++) { Object hit = hits.data(i); if (hit instanceof Article) { Article item = (Article) hit; logger.error("testDetachedFind() - article hits=" + item.getTitle()); } else if (hit instanceof Author) { Author item = (Author) hit; logger.error("testDetachedFind() - author hits=" + item.getUsername()); } else { logger.error("testDetachedFind() - error hits="); } } } /** * 用于演示com.mobilesoft.framework.search.service.CompassSearchService的使用 * */ class CompassSearch extends CompassSearchService{ CompassSearch(){ Compass compass = ct.getCompass(); CompassSession session = compass.openSession(); CompassTransaction tx = null; try { tx = session.beginTransaction(); CompassSearchCommand command = new CompassSearchCommand(); command.setQuery("Compass"); CompassSearchResults results= performSearch(command,session); logger.error("CompassSearch() - CompassHit TotalHits value=" +results.getTotalHits()); for (int i = 0; i < results.getHits().length; i++) { CompassHit hits=results.getHits()[i]; Object hit=hits.getData(); logger.error("CompassSearch() - CompassHit hit=" + hit); //$NON-NLS-1$ if (hit instanceof Article) { Article item = (Article) hit; logger.error("testCompassSearchService() - article hits=" + item.getTitle()); } else if (hit instanceof Author) { Author item = (Author) hit; logger.error("testCompassSearchService() - author hits=" + item.getUsername()); } else { logger.error("testCompassSearchService() - error hits="); } tx.commit(); } } catch (Exception e) { if (tx != null) { tx.rollback(); } } finally { session.close(); } } } public void testCompassSearchService() { new CompassSearch(); } protected void tearDown() throws Exception { }}
<?xml version="1.0"?><!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd"><beans default-lazy-init="true"> <bean id="compassTemplate" class="org.compass.core.CompassTemplate"> <property name="compass" ref="compass"/> </bean> <bean id="annotationConfiguration" class="org.compass.annotations.config.CompassAnnotationsConfiguration"> </bean> <bean id="compass" class="org.compass.spring.LocalCompassBean"> <property name="classMappings"> <list> <value>com.mobilesoft.esales.model.Article</value> <value>com.mobilesoft.esales.model.Author</value> </list> </property> <property name="compassConfiguration" ref="annotationConfiguration"/> <property name="compassSettings"> <props> <prop key="compass.engine.connection"> file://compass </prop> <prop key="compass.transaction.factory"> org.compass.spring.transaction.SpringSyncTransactionFactory </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="compassSearchService" class="com.mobilesoft.framework.search.service.CompassSearchService"> <property name="compass" ref="compass"/> <property name="pageSize" value="15"/> </bean> <!-- 定时重建索引(利用quartz)或随Spring ApplicationContext启动而重建索引 --> <bean id="compassIndexBuilder" class="com.mobilesoft.framework.search.service.CompassIndexBuilder" lazy-init="false"> <property name="compassGps" ref="compassGps"/> <property name="buildIndex" value="false"/> <property name="lazyTime" value="10"/> </bean></beans>
package com.mobilesoft.framework.search.service;import java.util.HashSet;import java.util.Set;import org.apache.commons.lang.StringUtils;import org.compass.core.CompassQuery.SortDirection;import org.compass.core.CompassQuery.SortPropertyType;import org.compass.core.support.search.CompassSearchCommand;import org.springframework.util.Assert;public class AdvancedSearchCommand extends CompassSearchCommand { /** * 封装基于Compass 的排序参数. */ class CompassSort { private String name; private SortPropertyType type; private SortDirection direction; public CompassSort() { } public CompassSort(String sortParamName, String paramType, boolean isAscend) { Assert.isTrue(StringUtils.isNotBlank(sortParamName)); setName(sortParamName); if ("int".equalsIgnoreCase(paramType)) { setType(SortPropertyType.INT); } else if ("float".equalsIgnoreCase(paramType)) { setType(SortPropertyType.FLOAT); } else if ("string".equalsIgnoreCase(paramType)) { setType(SortPropertyType.STRING); } else { setType(SortPropertyType.AUTO); } if (isAscend) { setDirection(SortDirection.AUTO); } else { setDirection(SortDirection.REVERSE); } } public String getName() { return name; } public void setName(String name) { this.name = name; } public SortPropertyType getType() { return type; } public void setType(SortPropertyType type) { this.type = type; } public SortDirection getDirection() { return direction; } public void setDirection(SortDirection direction) { this.direction = direction; } } /** * 搜索结果排序表. */ private Set<CompassSort> sortMap = new HashSet<CompassSort>(); private String[] highlightFields; /** * @param paramType 现定义了三种类型: int string 以及 float。<br> * 除去这三种外,其他会被自动定义为SortPropertyType.AUTO 具体的可见{@link org.compass.core.CompassQuery.SortPropertyType} * @param isAscend 顺序还是倒序排序 * @see org.compass.core.CompassQuery.SortPropertyType#AUTO * @see org.compass.core.CompassQuery.SortPropertyType#INT * @see org.compass.core.CompassQuery.SortPropertyType#STRING * @see org.compass.core.CompassQuery.SortPropertyType#FLOAT * @see org.compass.core.CompassQuery.SortDirection#AUTO * @see org.compass.core.CompassQuery.SortDirection#REVERSE */ public void addSort(String sortParamName, String paramType, boolean isAscend) { this.sortMap.add(new CompassSort(sortParamName, paramType, isAscend)); } public Set<CompassSort> getSortMap() { return sortMap; } public void setSortMap(Set<CompassSort> sortMap) { this.sortMap = sortMap; } public String[] getHighlightFields() { return highlightFields; } public void setHighlightFields(String[] highlightFields) { this.highlightFields = highlightFields; }}
package com.mobilesoft.framework.search.service;import org.apache.log4j.Logger;import org.compass.gps.CompassGps;import org.springframework.beans.factory.InitializingBean;import org.springframework.util.Assert;/** * 通过quartz定时调度定时重建索引或自动随Spring ApplicationContext启动而重建索引的Builder. * 会启动后延时数秒新开线程调用compassGps.index()函数. * 默认会在Web应用每次启动时重建索引,可以设置buildIndex属性为false来禁止此功能. * 也可以不用本Builder, 编写手动调用compassGps.index()的代码. * */public class CompassIndexBuilder implements InitializingBean { private static final Logger log = Logger.getLogger(CompassIndexBuilder.class); // 是否需要建立索引,可被设置为false使本Builder失效. private boolean buildIndex = false; // 索引操作线程延时启动的时间,单位为秒 private int lazyTime = 10; // Compass封装 private CompassGps compassGps; // 索引线程 private Thread indexThread = new Thread() { @Override public void run() { try { Thread.sleep(lazyTime * 1000); log.info("begin compass index..."); long beginTime = System.currentTimeMillis(); // 重建索引. // 如果compass实体中定义的索引文件已存在,索引过程中会建立临时索引, // 索引完成后再进行覆盖. compassGps.index(); long costTime = System.currentTimeMillis() - beginTime; log.info("compss index finished."); log.info("costed " + costTime + " milliseconds"); } catch (InterruptedException e) { // simply proceed } } }; /** * 实现<code>InitializingBean</code>接口,在完成注入后调用启动索引线程. * * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() */ public void afterPropertiesSet() throws Exception { if (buildIndex) { Assert.notNull(compassGps, "CompassIndexBuilder not set CompassGps yet."); 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; }}
package com.mobilesoft.framework.search.service;import org.compass.core.Compass;import org.compass.core.CompassCallback;import org.compass.core.CompassDetachedHits;import org.compass.core.CompassHits;import org.compass.core.CompassQuery;import org.compass.core.CompassSession;import org.compass.core.CompassTemplate;import org.compass.core.CompassTransaction;import org.compass.core.support.search.CompassSearchCommand;import org.compass.core.support.search.CompassSearchResults;import org.springframework.beans.factory.InitializingBean;import org.springframework.util.Assert;import com.mobilesoft.framework.search.service.AdvancedSearchCommand.CompassSort;/** * 仿照 {@link org.compass.spring.web.mvc.CompassSearchController} * 中的代码,构建了一个Service,方便不使用Spring MVC * * @see org.compass.spring.web.mvc.CompassSearchController * @see org.compass.spring.web.mvc.AbstractCompassCommandController */public class CompassSearchService implements InitializingBean { //每页显示的条目数量 private Integer pageSize = 15; private Compass compass; private CompassTemplate compassTemplate; /** * 公开的搜索接口,返回匹配的搜索结果,与 * {@link org.compass.spring.web.mvc.CompassSearchController#handle(javax.servlet.http.HttpServletRequest, *javax.servlet.http.HttpServletResponse,Object,org.springframework.validation.BindException) 处理相似 * * @see org.compass.spring.web.mvc.CompassSearchController#handle(javax.servlet.http.HttpServletRequest, *javax.servlet.http.HttpServletResponse,java.lang.Object,org.springframework.validation.BindException) */ public CompassSearchResults search(final CompassSearchCommand command) { return (CompassSearchResults) getCompassTemplate().execute( CompassTransaction.TransactionIsolation.READ_ONLY_READ_COMMITTED, new CompassCallback() { public Object doInCompass(CompassSession session) { return performSearch(command, session); } }); } /** * 通过此方法调用搜索引擎,进行结果匹配搜索. * * @see org.compass.spring.web.mvc.CompassSearchController#performSearch( *org.compass.spring.web.mvc.CompassSearchCommand,org.compass.core.CompassSession) */ protected CompassSearchResults performSearch(CompassSearchCommand searchCommand, CompassSession session) { long time = System.currentTimeMillis(); CompassQuery query = buildQuery(searchCommand, session); CompassHits hits = query.hits(); CompassDetachedHits detachedHits; CompassSearchResults.Page[] pages = null; if (pageSize == null) { doProcessBeforeDetach(searchCommand, session, hits, -1, -1); detachedHits = hits.detach(); } else { int iPageSize = pageSize; int page = 0; int hitsLength = hits.getLength(); if (searchCommand.getPage() != null) { page = searchCommand.getPage(); } int from = page * iPageSize; if (from > hits.getLength()) { // 如果起始的条目大于搜索到的条目 from = hits.getLength() - iPageSize; doProcessBeforeDetach(searchCommand, session, hits, from, hitsLength); detachedHits = hits.detach(from, hitsLength); } else if ((from + iPageSize) > hitsLength) { // 结束的条目大于搜索到的结果 doProcessBeforeDetach(searchCommand, session, hits, from, hitsLength); detachedHits = hits.detach(from, hitsLength); } else { // 中间的页码,直接取出相应的条目 doProcessBeforeDetach(searchCommand, session, hits, from, iPageSize); detachedHits = hits.detach(from, iPageSize); } doProcessAfterDetach(searchCommand, session, detachedHits); int numberOfPages = (int) Math.ceil((float) hitsLength / iPageSize); pages = new CompassSearchResults.Page[numberOfPages]; for (int i = 0; i < pages.length; i++) { pages[i] = new CompassSearchResults.Page(); pages[i].setFrom(i * iPageSize + 1); pages[i].setSize(iPageSize); pages[i].setTo((i + 1) * iPageSize); if (from >= (pages[i].getFrom() - 1) && from < pages[i].getTo()) { pages[i].setSelected(true); } else { pages[i].setSelected(false); } } if (numberOfPages > 0) { CompassSearchResults.Page lastPage = pages[numberOfPages - 1]; if (lastPage.getTo() > hitsLength) { lastPage.setSize(hitsLength - lastPage.getFrom()); lastPage.setTo(hitsLength); } } } time = System.currentTimeMillis() - time; CompassSearchResults searchResults = new CompassSearchResults(detachedHits.getHits(), time, pageSize); searchResults.setPages(pages); return searchResults; } /** * 构建Lucene搜索器. */ protected CompassQuery buildQuery(CompassSearchCommand searchCommand, CompassSession session) { CompassQuery query = session.queryBuilder().queryString(searchCommand.getQuery().trim()).toQuery(); if (AdvancedSearchCommand.class.isAssignableFrom(searchCommand.getClass())) { AdvancedSearchCommand advancedSearchCommand = (AdvancedSearchCommand) searchCommand; for (CompassSort sort : advancedSearchCommand.getSortMap()) { query.addSort(sort.getName(), sort.getType(), sort.getDirection()); } } return query; } /** * 在detach 之前,可以做一些操作。比如highlighting... * * @param from 需要注意的是,如果pageSize 没有指定,那么这里传入的参数为-1 */ protected void doProcessBeforeDetach(CompassSearchCommand searchCommand, CompassSession session, CompassHits hits, int from, int size) { if (AdvancedSearchCommand.class.isAssignableFrom(searchCommand.getClass())) { if (from < 0) { from = 0; size = hits.getLength(); } String[] highlightFields = ((AdvancedSearchCommand) searchCommand).getHighlightFields(); if (highlightFields == null) { return; } // highlight fields for (int i = from; i < size; i++) { for (String highlightField : highlightFields) { hits.highlighter(i).fragment(highlightField); } } } } /** * An option to perform any type of processing before the hits are detached. */ protected void doProcessAfterDetach(CompassSearchCommand searchCommand, CompassSession session, CompassDetachedHits hits) { } public void afterPropertiesSet() throws Exception { Assert.notNull(compass, "Must set compass property"); this.compassTemplate = new CompassTemplate(compass); } public Integer getPageSize() { return pageSize; } public void setPageSize(Integer pageSize) { this.pageSize = pageSize; } public void setCompass(Compass compass) { this.compass = compass; } protected CompassTemplate getCompassTemplate() { return this.compassTemplate; }}
8、Model层
package com.mobilesoft.esales.model;import java.util.Date;import org.compass.annotations.Searchable;import org.compass.annotations.SearchableId;import org.compass.annotations.SearchableProperty;import org.compass.core.CompassTemplate;@Searchablepublic class Article implements java.io.Serializable { @SearchableId private Integer id; @SearchableProperty(name="title") private String title; @SearchableProperty(name="author") private Integer author; @SearchableProperty(name="publishDate") private Date publishDate; /** default constructor */ public Article() { } /** minimal constructor */ public Article(String title, Date publishDate) { this.title = title; this.publishDate = publishDate; } /** full constructor */ public Article(String title, Integer author, Date publishDate) { this.title = title; this.author = author; this.publishDate = publishDate; } public Integer getId() { return this.id; } public void setId(Integer id) { this.id = id; } public String getTitle() { return this.title; } public void setTitle(String title) { this.title = title; } public Integer getAuthor() { return this.author; } public void setAuthor(Integer author) { this.author = author; } public Date getPublishDate() { return this.publishDate; } public void setPublishDate(Date publishDate) { this.publishDate = publishDate; }}
package com.mobilesoft.esales.model;import org.compass.annotations.Searchable;import org.compass.annotations.SearchableId;import org.compass.annotations.SearchableProperty;import org.compass.core.CompassTemplate;@Searchablepublic class Author implements java.io.Serializable { @SearchableId private Integer id; @SearchableProperty(name="username") private String username; private String password; @SearchableProperty(name="age") private Short age; public Author() { } /** minimal constructor */ public Author(String username, String password) { this.username = username; this.password = password; } /** full constructor */ public Author(String username, String password, Short age) { this.username = username; this.password = password; this.age = age; } // Property accessors public Integer getId() { return this.id; } public void setId(Integer id) { this.id = id; } public String getUsername() { return this.username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return this.password; } public void setPassword(String password) { this.password = password; } public Short getAge() { return this.age; } public void setAge(Short age) { this.age = age; }}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。