最新SH、Lucene3、IKAnalyzer3.2.3整合实例

本文介绍了一个基于Spring框架和Lucene实现的全文检索系统。该系统利用Spring的定时任务功能定期更新索引,并通过Hibernate进行数据库操作。此外,还详细展示了如何使用Lucene建立索引的过程。
Spring3.1, Hibernate3.6,Lucene3.0.3以及IKAnalyzer3.2.3, 数据库采用Mysql,连接池采用dbcp.主要Jar如下:

[img]http://dl.iteye.com/upload/attachment/531117/f64f9320-6fd5-38b0-ae19-6de33722bf7d.jpg[/img]


Spring重要Bean配置:

<!--配置定时任务 -->
<bean id="bagnetTask"
class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject">
<ref bean="bagnetJob" />
</property>
<property name="targetMethod">
<value>runJobs</value>
</property>
<!-- keep the job from running while the previous one hasn't finished yet -->
<property name="concurrent" value="false" />
</bean>

<!--配置定时任务触发器 -->

<bean id="jobTrigger"
class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="jobDetail">
<ref bean="bagnetTask" />
</property>
<!-- every 10 mins in the working day from 9:00 to 19:00 we create/update index -->
<property name="cronExpression">
<value>0 0/10 9-19 *,* * ?</value>
</property>
</bean>
<!-- 定时调用的Scheduler-->
<bean autowire="no"
class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref local="jobTrigger" />
</list>
</property>
</bean>

<!-- 事务管理器 -->
<bean id="transactionManger"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
</bean>

<!-- 配置事务拦截器-->
<bean id="transactionInterceptor"
class="org.springframework.transaction.interceptor.TransactionInterceptor">
<property name="transactionManager">
<ref bean="transactionManger" />
</property>
<!-- 下面定义事务传播属性-->
<property name="transactionAttributes">
<props>
<prop key="find*">PROPAGATION_REQUIRED</prop>
<prop key="delete*">PROPAGATION_REQUIRED</prop>
<prop key="add*">PROPAGATION_REQUIRED</prop>
<prop key="update*">PROPAGATION_REQUIRED</prop>
<prop key="do*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>

<!-- 自动代理 -->
<bean id="autoBeanNameProxyCreator"
class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="beanNames">
<list>
<value>*Service</value>
</list>
</property>
<property name="interceptorNames">
<list>
<idref local="transactionInterceptor" />
</list>
</property>
<!-- 这里的配置是必须的,否则无法完成代理的类型转化 这是使用CGLIB来生成代理 -->
<property name="proxyTargetClass" value="true" />
</bean>



Lucene工具类:

package com.dx.bags.util;

import java.io.File;
import java.io.IOException;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.wltea.analyzer.lucene.IKAnalyzer;

public class LuceneUtil
{
private static LuceneUtil instance;
private Analyzer analyzer;
private Directory picDirectory;
private Directory topDirectory;


public Analyzer getAnalyzer()
{
return analyzer;
}

public void setAnalyzer(Analyzer analyzer)
{
this.analyzer = analyzer;
}

public Directory getPicDirectory()
{
return picDirectory;
}

public void setPicDirectory(Directory picDirectory)
{
this.picDirectory = picDirectory;
}

public Directory getTopDirectory()
{
return topDirectory;
}

public void setTopDirectory(Directory topDirectory)
{
this.topDirectory = topDirectory;
}

private LuceneUtil()
{
analyzer = new IKAnalyzer();
try
{
picDirectory = FSDirectory.open(new File(DXConstants.PIC_INDEX_DIR));
topDirectory = FSDirectory.open(new File(DXConstants.TOP_INDEX_DIR));

} catch (IOException e)
{
throw new RuntimeException(e);
}
}

public static LuceneUtil getInstance()
{
if (null == instance)
instance = new LuceneUtil();
return instance;
}

}



建立索引的方法:

public static void createTopIndex(List<SearchTop> list, boolean isFirstTime)
{

RAMDirectory ramDirectory = new RAMDirectory();
try
{
IndexWriter indexwriter = new IndexWriter(ramDirectory, LuceneUtil.getInstance().getAnalyzer(),
true, IndexWriter.MaxFieldLength.LIMITED);
if (list != null && list.size() > 0)
{
for (int i = 0; i < list.size(); i++)
{
Document doc = new Document();

SearchTop searchTop = list.get(i);

Field field = new Field("id", String.valueOf(searchTop.getId()), Field.Store.YES, Field.Index.NO);
doc.add(field);

String title = DXUtil.characterUtil(searchTop.getTitle());
if(title!=null && !"".equals(title)){
field = new Field("title", title, Field.Store.YES, Field.Index.ANALYZED);
doc.add(field);
}

String description = searchTop.getDescription();
if(description!=null && !"".equals(description)){
field = new Field("description", description, Field.Store.NO,Field.Index.ANALYZED);
doc.add(field);
}

field = new Field("cid", String.valueOf(searchTop.getCid()), Field.Store.YES, Field.Index.NOT_ANALYZED);
doc.add(field);

field = new Field("addtime", String.valueOf(searchTop.getCreateDate()), Field.Store.YES, Field.Index.NOT_ANALYZED);
doc.add(field);

String content = DXUtil.characterUtil(searchTop.getContents());
if(content!=null && !"".equals(content)){
field = new Field("contents", content, Field.Store.NO, Field.Index.ANALYZED);
doc.add(field);
}

field = new Field("sex", String.valueOf(searchTop.getSex()), Field.Store.YES, Field.Index.NOT_ANALYZED);
doc.add(field);

field = new Field("tid",String.valueOf(searchTop.getTid()),Field.Store.YES,Field.Index.NOT_ANALYZED);
doc.add(field);

field = new Field("topicid", String.valueOf(searchTop.getTopicId()), Field.Store.YES, Field.Index.ANALYZED);
doc.add(field);

field = new Field("piccount", String.valueOf(searchTop.getPiccount()), Field.Store.YES, Field.Index.NOT_ANALYZED);
doc.add(field);

String city = DXUtil.characterUtil(searchTop.getCityName());
if(city!=null && !"".equals(city)){
field = new Field("cityname", city, Field.Store.YES, Field.Index.ANALYZED);
doc.add(field);
}

field = new Field("purview", dealPurview(searchTop.getSex(), searchTop.getCid()), Field.Store.YES, Field.Index.NOT_ANALYZED);
doc.add(field);

String seasonname = DXUtil.characterUtil(searchTop.getSeasonName());
if(seasonname!=null && !"".equals(seasonname)){
field = new Field("seasonname", seasonname, Field.Store.YES, Field.Index.ANALYZED);
doc.add(field);
}

String recordurl = dealTopUrl(searchTop.getSex(), searchTop.getCid(), searchTop.getTid());
if(recordurl!=null && !"".equals(recordurl)){
field = new Field("recordurl", recordurl, Field.Store.YES, Field.Index.NOT_ANALYZED);
doc.add(field);
}

indexwriter.addDocument(doc);
}
}
indexwriter.optimize();
indexwriter.close();

IndexWriter writer = new IndexWriter(LuceneUtil.getInstance()
.getTopDirectory(), LuceneUtil.getInstance()
.getAnalyzer(), isFirstTime, IndexWriter.MaxFieldLength.LIMITED);
writer.addIndexesNoOptimize(new Directory[] { ramDirectory });
writer.close();
} catch (CorruptIndexException e)
{

throw new RuntimeException(e);
} catch (IOException ex)
{
throw new RuntimeException(ex);
}
}


对增量数据循环建立索引:

private void createTopIndex() {
long count = searchTopService.findTotalRecordNum();
boolean flag = DXUtil.hasNotFile(new File(DXConstants.TOP_INDEX_DIR));
List<SearchTop> tops = new ArrayList<SearchTop>();
int max = DXConstants.PAGE_SIZE;
int first = Integer.parseInt(DXUtil
.getRecordNumFromFile(DXConstants.TOP_TXT));
while (first < count) {
tops = searchTopService.findTopToIndex(first, max);
first = first + max;
IndexCreator.createTopIndex(tops, flag);
if(flag == true)
flag = false;
DXUtil.writeContent(String.valueOf(first), DXConstants.TOP_TXT);
}
if (first >= count)
DXUtil.writeContent(String.valueOf(count), DXConstants.TOP_TXT);
optimiseTopicIndex(flag);
}

//optimize index
private void optimiseTopicIndex(boolean flag) {
IndexWriter writer = null;
try {
writer = new IndexWriter(
LuceneUtil.getInstance().getTopDirectory(), LuceneUtil
.getInstance().getAnalyzer(), flag,
IndexWriter.MaxFieldLength.LIMITED);
writer.optimize();
writer.close();

} catch (Exception e) {

}

}



主要代码以备忘。
Delphi 12.3 作为一款面向 Windows 平台的集成开发环境,由 Embarcadero Technologies 负责其持续演进。该环境以 Object Pascal 语言为核心,并依托 Visual Component Library(VCL)框架,广泛应用于各类桌面软件、数据库系统及企业级解决方案的开发。在此生态中,Excel4Delphi 作为一个重要的社区开源项目,致力于搭建 Delphi 与 Microsoft Excel 之间的高效桥梁,使开发者能够在自研程序中直接调用 Excel 的文档处理、工作表管理、单元格操作及宏执行等功能。 该项目以库文件与组件包的形式提供,开发者将其集成至 Delphi 工程后,即可通过封装良好的接口实现对 Excel 的编程控制。具体功能涵盖创建与编辑工作簿、格式化单元格、批量导入导出数据,乃至执行内置公式与宏指令等高级操作。这一机制显著降低了在财务分析、报表自动生成、数据整理等场景中实现 Excel 功能集成的技术门槛,使开发者无需深入掌握 COM 编程或 Excel 底层 API 即可完成复杂任务。 使用 Excel4Delphi 需具备基础的 Delphi 编程知识,并对 Excel 对象模型有一定理解。实践中需注意不同 Excel 版本间的兼容性,并严格遵循项目文档进行环境配置与依赖部署。此外,操作过程中应遵循文件访问的最佳实践,例如确保目标文件未被独占锁定,并实施完整的异常处理机制,以防数据损毁或程序意外中断。 该项目的持续维护依赖于 Delphi 开发者社区的集体贡献,通过定期更新以适配新版开发环境与 Office 套件,并修复已发现的问题。对于需要深度融合 Excel 功能的 Delphi 应用而言,Excel4Delphi 提供了经过充分测试的可靠代码基础,使开发团队能更专注于业务逻辑与用户体验的优化,从而提升整体开发效率与软件质量。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值