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

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

我记得在园子里有园友提出博客园的搜索功能是采用的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 实现的是定时器任务,可以按照定时规则按照规定的时间执行任务。

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

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

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

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

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

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

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

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • python破解版激活码【中文破解版】

    (python破解版激活码)这是一篇idea技术相关文章,由全栈君为大家提供,主要知识点是关于2021JetBrains全家桶永久激活码的内容IntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,下面是详细链接哦~https://javaforall.net/100143.html83PVI25FMO-eyJsaWN…

    2022年3月27日
    75
  • sublime text3的激活成功教程和使用

    sublime text3的激活成功教程和使用个人博客:ZJBLOG之所以想用这个是因为最近在学Python不知道用啥ide好,看同事说这个不错就了解了下,已经有的notepad++感觉不太好编程吧,做记事本就行了,atom又感觉太卡了,打开慢的要死,加了一些特效插件后也卡。。所以试一下这个。首先安装sublimetext3(好像这个版本比2好就选择这个了)安装直接官网下载就行了官网地址:http://www.sublime…

    2022年7月11日
    62
  • oracle拼接字符串函数_拼接字符串

    oracle拼接字符串函数_拼接字符串concat(param1,param2)

    2022年9月20日
    0
  • Java标识符命名规则(超详细!)[通俗易懂]

    Java标识符命名规则(超详细!)[通俗易懂]规则1:标识符只能由数字、字母(包括中文)、下划线_、美元符号$组成,不能含有其它符号。规则2:标识符不能以数字开头规则3:关键字不能做标识符。例如:publicclassstaticvoid这些蓝色的字体都是关键字,关键字是不能做标识符的。规则4:标识符是严格区分大小写的。大写A和小写a不一样。规则5:标识符理论上是没有长度限制的。…

    2022年7月7日
    22
  • linux 重启nginx命令「建议收藏」

    linux 重启nginx命令「建议收藏」/usr/local/nginx/sbin/nginx-sreload

    2022年6月19日
    20
  • 设计模式之享元(flyweight)模式

    现在在大力推行节约型社会,“浪费可耻,节俭光荣”。在软件系统中,有时候也会存在资源浪费的情况,例如,在计算机内存中存储了多个完全相同或者非常相似的对象,如果这些对象的数量太多将导致系统运行代价过高。那

    2021年12月28日
    50

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

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