仿照博客园搜索功能 找找看的实现 发现问题 杂谈

仿照博客园搜索功能 找找看的实现 发现问题 杂谈

我记得在园子里有园友提出博客园的搜索功能是采用的Lucene.net,具体是不是我也不确定,但是宁可信其是,所以我在仿照博客园 搜索功能的时候采用的也是Lucene.net,有园友给我提意见,就是我以前的博客中提到的那些框架,例如log4net,Quartz.net等都是片面的讲解一个框架结构,只能作为练习用,而不能真正的在项目中使用,具体原因就是在实战中会遇到各种问题,没对应的策略,所以今天我就来把我这个仿照系统的搜索功能的实现简单的描述一下,重点说明的是在项目中使用这些框架应该注意的地方,这样才会更贴切实战,也更有用一些。

利用Lucene.net 进行搜索,应该分为三步走战略

  1. 利用IndexWriter进行创建索引
  2. 利用Analyzer对索引进行分词
  3. 利用IndexReader对索引进行提取

总的来说就是这三步,下面我们来具体分析一下这三步在实战中都应该采用什么策略。

首先,创建索引,因为博客会不断的被添加,所以我们在创建索引的时候要指定索引为增量添加(在IndexWriter实例化的时候有一个属性设置为false就可以)

1  Lucene.Net.Store.Directory dir = FSDirectory.Open("d:/index"); 2  IndexWriter writer = new IndexWriter(dir, new PanGuAnalyzer(), false, IndexWriter.MaxFieldLength.LIMITED);

 

设置了创建索引为增量索引以后,我们还需要指定其中的某些参数,让lucene.net在特定的计算机上工作最大化。

现在有一个问题出现了,我们不可能手动的去创建索引,所以我们要使用定时器去自动的创建索引,这就用到了Quartz.net定时器,

还有一个问题就是我们创建索引因为是自动创建,所以不需要界面显示,并且需要在后台运行,所以我们创建索引最好是采用Windows 服务形式来承载。

当然了,在程序运行过程中会遇到各种问题,需要我们记录成粗错误发生的位置以及时间,这就会用到log4net 日志管理框架。

 

问题一个一个的出现了,现在我们就要把这些问题逐个的解决,首先就是创建Windows 服务,这个在Vs中很容易的就可以实现。现在我把仿照博客园实现搜索的Windows服务的部分代码贴出来分析一下,

 1 public partial class Service1 : ServiceBase  2  {  3 private readonly ILog logger = LogManager.GetLogger(typeof(Service1));  4  5  6 public Service1()  7  {  8  log4net.Config.XmlConfigurator.Configure();  9  InitializeComponent(); 10  SchedulerManager.GetSchedulerFactory().GetScheduler().ListenerManager.AddJobListener(SchedulerManager.GetJobListener()); 11  } 12 13 protected override void OnStart(string[] args) 14  { 15 try 16  { 17 JobKey jobKey = new JobKey("CreateIndex", "CreateIndexGroup"); 18 19 IJobDetail jobDetail = JobBuilder.Create().WithIdentity(jobKey).OfType(typeof(Jobs.QuzrtaNet)).Build(); 20 21 ITrigger trigger = TriggerBuilder.Create().WithCronSchedule("0 0/59 * * * ?").StartNow().Build(); 22  SchedulerManager.GetScheduler().ScheduleJob(jobDetail, trigger); 23 logger.Info("任务 " + jobDetail.Key.Group + "已经调度陈功"); 24 if (SchedulerManager.GetScheduler().IsStarted == false) 25  { 26  SchedulerManager.GetScheduler().Start(); 27 logger.Info("服务已经成功启动"); 28  } 29  } 30 catch (Exception ex) 31  { 32 logger.Error("服务启动失败", ex); 33 if (this.CanStop == true) 34  { 35 this.Stop(); 36  } 37  } 38  } 39 40 protected override void OnStop() 41  { 42 try 43  { 44 if (SchedulerManager.GetScheduler().IsShutdown == false) 45  { 46  SchedulerManager.GetScheduler().Shutdown(); 47 logger.Info("Quartz服务成功终止"); 48  } 49  } 50 catch (Exception ex) 51  { 52 logger.Error("服务停止失败",ex); 53  } 54 55  } 56 protected override void OnPause() 57  { 58 59  } 60 61 protected override void OnContinue() 62  { 63 64  } 65 }

 

 

在上面额代码中,有几点我要说明一下。

  1. 对于log4net 需要在程序启动的时候进行配置log4net.Config.XmlConfigurator.Configure();这句代码一定不能少,否则log4net就不会根据配置文件进行更改其特性
  2. 对于Quartz.net的操作,我们利用单例模式来获取对象的实例,因为在Quartz.net 3.0中的很多接口方法都已经改变,所以如果你采用的是最新版的版

    本,那么你可能要进行一些修改,你可以看到我现在的写法和园子里其他园友的写法有所不同,这都不是什么问题,因为接口方法更改了。

    在quartz.net 中通过继承IJOb接口来实现一个任务,我们在Windows 服务启动的时候可以定时执行多个任务。这就会遇到一个问题,例如,你规定了

    一个trigger的周期为1分钟,那么触发器没隔一分钟就胡执行一次这个任务,但是你的这个任务的执行需要一个小时的时间?这时你看会出现什么问题?

    触发器没一分钟触发一次,但是任务会执行一个小时。这个问题我曾经想过,但是也没找到很完美的解决方案,最好的办法可能就是把触发器的触发周期

    调长,比如调成每天执行一次,这样就可以避免多次触发的问题。

  3. 我们再来注意一下log4net,这个框架会根据配置文件来动态的输出日志到不同的介质,但是在我们配置log4net的时候,一定要注意精确,因为一点的拼

    写错误都会导致log4net 不能正常工作。

     1 <configSections>  2 <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>  3 </configSections>  4 <log4net debug="false">  5 <appender name="LogFileAppender" type="log4net.Appender.FileAppender">  6 <param name="File" value="c:\Log\DBLog.txt"/>  7 <param name="AppendToFile" value="true"/>  8 <layout type="log4net.Layout.PatternLayout">  9 <param name="ConversionPattern" value="%d [%t] %-5p %c [%x] - %m%n"/> 10 </layout> 11 </appender> 12 13 <appender name="ADONetAppender" type="log4net.Appender.ADONetAppender"> 14 <bufferSize value="10"/> 15 <connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/> 16 <connectionString value="server=.\sqlexpress;database=DbLog;user id=sa;password=yuanjinzhou"/> 17 <commandText value="INSERT INTO Log ([Date],[Thread],[Level],[Logger],[Message],[Exception]) VALUES (@log_date, @thread, @log_level, @logger, @message, @exception)"/> 18 <parameter> 19 <parameterName value="@log_date"/> 20 <dbType value="DateTime"/> 21 <layout type="log4net.Layout.RawTimeStampLayout"/> 22 </parameter> 23 <parameter> 24 <parameterName value="@thread"/> 25 <dbType value="String"/> 26 <size value="255"/> 27 <layout type="log4net.Layout.PatternLayout"> 28 <conversionPattern value="%thread"/> 29 </layout> 30 </parameter> 31 <parameter> 32 <parameterName value="@log_level"/> 33 <dbType value="String"/> 34 <size value="50"/> 35 <layout type="log4net.Layout.PatternLayout"> 36 <conversionPattern value="%level"/> 37 </layout> 38 </parameter> 39 <parameter> 40 <parameterName value="@logger"/> 41 <dbType value="String"/> 42 <size value="255"/> 43 <layout type="log4net.Layout.PatternLayout"> 44 <conversionPattern value="%logger"/> 45 </layout> 46 </parameter> 47 <parameter> 48 <parameterName value="@message"/> 49 <dbType value="String"/> 50 <size value="4000"/> 51 <layout type="log4net.Layout.PatternLayout"> 52 <conversionPattern value="%message"/> 53 </layout> 54 </parameter> 55 <parameter> 56 <parameterName value="@exception"/> 57 <dbType value="String"/> 58 <size value="2000"/> 59 <layout type="log4net.Layout.ExceptionLayout"/> 60 </parameter> 61 </appender> 62 <root> 63 <level value="DEBUG"/> 64 <appender-ref ref="ADONetAppender"/> 65 <appender-ref ref="LogFileAppender"/> 66 </root> 67 </log4net>

    log4net的输出介质园子里有很多介绍,我这里贴出来配置文件,就是不想有太多人因为拼写错误而导致log4net不能正常工作。其中我要特别强调一下的

    就是log4net输出日志到数据库中,这里面有很多配置参数,其中 

    <connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>

    connectionType结点中的System.Data后面的Version以后的内容我们一定要添加上,我在多次试验中发现如果后面的版本号不加上的话,log4net不

    会正确的把日志插入到数据库中,而加上版本号就可以,所以当你不能把日志插入到数据库中时,检查一下版本号是否写上。

  4. 另外有一点我想再说一下,就是我们在服务启动的时候为Scheduler添加任务以及触发器,其中任务和触发器是分开的,我们不要在继承自IJOb的任务类

    中添加任何的触发器,因为我发现园子里有园友这样用过,所以我提醒一下各位,触发器和任务是分开的。

  5. 对于Lucene.net如何创建索引以及查询,以及分词,我这里使用的分词插件是盘古分词,这些内容在前面的博客中我有说明过,不再赘述。

总结一下,log4net日志管理框架,可以输出日志到任何的介质,对log4net的配置文件的配置是重点。

Lucene.net可以用来实现创建索引,通过索引进行查询,实现全文检索的功能。

Quartz.net 实现的是定时器任务,可以按照定时规则按照规定的时间执行任务。

根据我在仿照博客园搜索功能中遇到的问题,其实任何一个框架的单纯使用都很简单,但是在实战中如何更加合理的使用这些框架,更加高效的让这些框架协同工

作使我们做项目的时候需要思考的重点,有时候思考 分析一下,甚至总结一下会对自己的能力提升有很大的好处。虽然我在这篇博客中总结的问题不多,但是这

都是我在做项目的时候遇到的问题,困扰了我好几天的时间才发现的原因。

有总结才会有提高,有总结才会有进步,我不敢说通过完善这个仿照博客园的系统我有学习到很多东西,但是我发现了我自己的很多不足,这是很珍贵的,只有发
现不足才可以弥补。

我经常看见有些园友看了一下某个框架的配置文件,在试验的时候能够让框架运行输出自己想要的结果,然后就说掌握了这个框架,这个框架有多么的简单,等等,我都会笑一笑,继续其他的事情。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/110242.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • pcl点云合并_pcl点云重建

    pcl点云合并_pcl点云重建本节记录下点云聚类方法1.欧式聚类分割方法//为提取点云时使用的搜素对象利用输入点云cloud_filtered创建Kd树对象tree。pcl::search::KdTree::Ptrtree(newpcl::search::KdTree);tree-&amp;amp;gt;setInputCloud(cloud_filtered);//创建点云索引向量,用于存储实际的点云信息首先创…

    2022年10月21日
  • [图像]Canny检测的Matlab实现(含代码)「建议收藏」

    [图像]Canny检测的Matlab实现(含代码)「建议收藏」图象的边缘是指图象局部区域亮度变化显著的部分,该区域的灰度剖面一般可以看作是一个阶跃,既从一个灰度值在很小的缓冲区域内急剧变化到另一个灰度相差较大的灰度值。Canny边缘检测基本特征如下:(1)必须满足两个条件:①能有效地抑制噪声;②必须尽量精确确定边缘的位置。(2)根据对信噪比与定位乘积进行测度,得到最优化逼近算子。这就是Canny

  • Windows Phone 奇怪现象之ListBox在WP8能载入数据在WP7.x不能

    Windows Phone 奇怪现象之ListBox在WP8能载入数据在WP7.x不能

  • Ubuntu18.04 Cmake升級

    Ubuntu18.04 Cmake升級

  • 怎么在python中安装matplotlib_matplotlib依赖库

    怎么在python中安装matplotlib_matplotlib依赖库您也可以试试直接用第5步的pycharm安装试试,或许会更快。1.快捷键win+R输入cmd打开DOS命令框。2.虽然下载Python的时候自带有pip,但这里更新一下pip,输入更新pip命令:python-mpipinstall–upgradepip3.然后使用pip下载matplotlib:到这里如果直接使用命令:pipinstallmatplotlib基本很难成功。在安装模块时指定国内镜像:pipinstall包名-ihttp://pypi

  • 二分法注意点_二分法怎么用

    二分法注意点_二分法怎么用思路我相信对很多读者朋友来说,编写二分查找的算法代码属于玄学编程,虽然看起来很简单,就是会出错,要么会漏个等号,要么少加个1。不要气馁,因为二分查找其实并不简单。思路很简单,细节是魔鬼。本文以问答的形式,探究几个最常用的二分查找场景:寻找一个数、寻找左侧边界、寻找右侧边界。而且,我们就是要深入细节,比如不等号是否应该带等号,mid是否应该加一等等。分析这些细节的差异以及出现这些差异的原因,保证你能灵活准确地写出正确的二分查找算法。零、二分查找框架intbinarySearch(int[]

    2022年10月25日

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号