[C#]BlogEngine.Net架构与源代码分析系列part14:实现分析(下)——网站页面上值

mikel阅读(791)

     BlogEngine.Net 的成功不仅在于它的架构设计,它的代码实现细节也都是很经典的,每个结构分割的很清晰很自然,希望大家多多品位一下。在这篇文章里我将给大家介绍一下 BlogEngine.Net的Web实现上的几个亮点,包括Web.config,Ajax的运用等。

     Web.config中的几个结点说明

     让我们看一下appSettings结点中的各个选项的含义,以便您对整个BlogEngine.Net的认识更加清晰。
BlogEngine.FileExtension:在这里我们可以自定义Url请求的后缀名称,默认是.aspx。您可以定义自己喜欢的扩展名,例如.extguo,那么对于文章等生成的Url就成了类似http://HostName/CategoryName/PostTitle.extguo的形式。这个结点的使用在很多地方都可以见到,例如:

Post类中的RelativeLink

BlogSettings.Instance.FileExtension就是读取这个结点获得的扩展名。

BlogEngine.VirtualPath:主要是为一些文章等的链接而服务的。我们可以使用虚拟目录安装我们的BlogEngine.Net,那么我们只要设置一下这里就可以得到和直接在根目录下一样的效果。我们需要注意一下Utils关于Url处理的部分,其中:

Utils中的RelativeWebRoot

就是获得相对Web目录。

BlogEngine.MobileDevices:它的值是一个正则表达式,主要是对移动设备做出判断,并给移动设备使用设置的主题。它在这里被使用:

Utils中的IsMobile判断

之后在BlogSetting的Theme中返回。

BlogEngine.AdminRole:管理员角色名,可以动态配置管理员角 色,也就是说系统对是否是管理员的判断中的管理员名称实际上是从这儿获得的。比如有一天我们想把某个角色改为管理员,那么就直接修改这儿就行了,不过这儿 需要的数据肯定也是角色管理中的一个角色名称。

StorageLocation:数据的存储位置,主要是给数据存储是XML格式时使用。在DataStore.cs文件中StorageLocation方法会涉及到。

BlogEngine.HardMinify: 对于JavaScript脚本指定强行压缩(去除一些不必要的字符)的文件名称。我们知道BlogEngine.Net中对于JavaScript请求都 是通过JavaScriptHandler进行的,JavaScriptHandler有一个HardMinify来判断是否已经指定强行压缩。 JavaScriptHandler中会涉及到这部分的引用。注意对WebResource.axd的请求在BlogBasePage中替换成对于 js.axd的请求,之后JavaScriptHandler的处理是使用RetrieveRemoteScript来输出脚本的。

     Ajax的运用

     BlogEngine.Net的很多部分使用原生的Ajax完成。例如 评论的打分,widget的管理等部分。我们在讲述BlogBasePage时提到的AddLocalizationKeys实际上就是初始化页面脚本的 一些变量,之后使用AddJavaScriptInclude(Utils.RelativeWebRoot + "blog.js")引入blog.js,如果是管理员(Widget可被管理)又使用 AddJavaScriptInclude(Utils.RelativeWebRoot + "admin/widget.js")引入widget.js,使用 AddStylesheetInclude(Utils.RelativeWebRoot + "admin/widget.css")引入widget样式,注意先后顺序,因为widget.js需要使用核心的blog.js。blog.js中这段代码就是Ajax调用的核心:

Ajax核心

 

     在线评论预览与评论的提交

     结合blog.js与User controls\CommentView.ascx,我们看一下它的处理过程。CommentView可以显示文章的评论列表和提交新评论。当点击 Preview时,会调用blog.js中的ToggleCommentMenu:

评论的预览与提交

     请注意isPreview的引入与它的逻辑,这个Preview实际上也是需要回调到服务器端的程序的,之后生成预览的Render,当 点击Save时isPreview为false,这时回调服务器端的代码时才真正的保存,然后浏览器回调客户端的AppendComment完成一些初始 化工作。CommentView是一个UserControl并实现了 ICallbackEventHandler接口,这个接口有两个方法GetCallbackResult和RaiseCallbackEvent,在 RaiseCallbackEvent中我们可以看出,提交的评论参数使用"-|-"作为分隔符,经过一系列处理最后将这个新评论的呈现给了 _Callback,_Callback由GetCallbackResult返回。浏览端使用 WebForm_DoCallback('ctl00$cphBody$CommentView1',argument, callback,'comment',null,false);在这部分里我们只要实现ICallbackEventHandler接口就行了,实现的 细节都已经有.Net提供了,感兴趣细节的朋友可以查一查ASP.NET的回调方面的资料。

     Widget排序的实现

     当我们用鼠标拖住一个Widget移动到某个位置再放开鼠标时,发现这个Widget在WidgetZone中的排序被永久存储了,甚至 在你清空cookie时依然生效,BlogEngine.Net是在服务器端进行的存储,DataStore的be_WIDGET_ZONE中的 Widget的顺序就是在页面上Widget的显示顺序。这实际上是通过间接调用WidgetEditor.aspx中的MoveWidgets方法实现 的(前文提及过)。那么在浏览器端是如何处理这些排序问题的呢?

     在widget.js中的大部分代码都是用来处理拖放排序的,initdragableElements主要完成使某个Widget可以 被拖动的初始化工作,widget.js的最后一句代码addLoadEvent(initdragableElements)使其在页面加载时执行。注 意initdragableElements中:

拖动事件的Hookup

当鼠标onmouseup时执行stop_dragDropElement,在stop_dragDropElement中通过调用 saveData,saveData使用上文提到的CreateCallback完成服务器端的回调,其中saveString就是已排序的字符串,主要 用于发送给服务器端程序处理。

     总结

     实际上在BlogEngine.Net的Web站点中还有很多比较有用的东西值得我们去研究,例如FilterByApml的实现,对文 章的评分,邮件的发送等,这里就不做更多的讨论。关于在线评论预览我个人觉得没有必要去回调服务器,完全可以由客户端搞定,不知道大家是怎么想的。那个 Widget的排序一直都深深的吸引着我,这种处理我见得很少,所以拿出来分享。

     在本系列的最后一篇文章中我会就BlogEngine.Net的优秀部分和不太推荐的部分做一个总结,并谈一下我对它的感受,希望大家继续关注。

     坚持写完,坚持看完。

     上一篇:BlogEngine.Net架构与源代码分析系列part13:实现分析(上)——HttpHandlers与HttpModules

 

     返回到目录

版权声明
作者:Thriving.country
出处:http://thriving-country.cnblogs.com/
本文版权归作者和博客园共同所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接.

[Flash]Flash加密和破解大法

mikel阅读(1054)

FLASH的破解与加密大法

转载:http://hi.baidu.com/lisa910502/blog/item/7719e306827fc97e03088166.html
一、破解篇

  这里所谈的破解,包括提取swf、破解已加密及未加密的swf,即通常所说的“swf to fla”。

  获取swf的工具:

   * Flash Saver 保存网页中的swf
   * Flash文件格式转换器(FlashChanger) 转换未加壳的exe为swf
   * Flash吸血鬼 不得已时用之。

2 flash资源的下载提取

提取范围很广,只要能看到Flash的窗口,包括加壳及未加壳的exe、网页等等。在使用 Flash吸血鬼提取swf的过程中建议不要进行其他操作,否则速度会变得极其缓慢,配置不好的机器有可能死机。这也是这款软件目前版本(v2.2)最大的一个不足之处。如果想中止程序,可以在任务管理器中结束。

  使用Temporary Internet Files(IE缓存)下载MV、SWF等资源

  偶尔会有网友问笔者关于网上 MV 如何下载,其实方法很简单,只要到 Temporary Internet Files 文件夹下就能找到想找的大部分网络资源。

  Temporary Internet Files IE 的临时文件夹。目录一般在C:\Documents and Settings\你的用户名\Local Settings\Temporary Internet Files

  使用 Temporary Internet Files 查找资源的技巧:先清空 Temporary Internet Files,然后用 IE 打开或刷新你要找的资源 (比如 MV) 所在的网页。再刷新 Temporary Internet Files 就能看到了,如果资源比较大,需要过一会,等下载完后再刷新才能看到。

  有时,部分资源会被隐藏。查看 Temporary Internet Files 的属性可以断定里面有文件,可是里面的内容却看不到。此时,用 WinRAR 压缩一下 Temporary Internet Files 就能看到了。为了不浪费时间,压缩的时候,压缩方式请选择“存储”。为了便于搜索查找,可以把压缩后的 Temporary Internet Files 解压到另一个目录下,里面的东西此时已经一目了然,分别分布在 Content.IE5 文件夹下的四个子文件夹中。

  可以将 Temporary Internet Files 移动到其他分区下,一方面可以给系统分区减负,另一方面也便于查找。移动方法如下:
Internet 选项 常规选项卡 在“Internet 临时文件”区点击“设置” 移动文件夹 选择一个分区,例如选择 D,就把 Temporary Internet Files 移到了 D 盘的根目录下。最后会提示重启,其实不是重启,是注销。记得保存当前的其他工作,按确定注销。

  从Word中提取Flash
  测试环境:WindowsXP / Office2003

3.从doc文档中提取flash、flash的破解工具

1. 需要一款16进制编辑工具WinHex
  2. 打开含有Flash的Word文档,点击“控件工具箱”的“设计模式”按钮进入设计模式,选择Word中的Flash,复制粘贴到任意文件夹,会看到一个“片段”文件。
  3. 打开WinHex,将该“片段”文件拉到WinHex中,单击下拉菜单“搜索”→“查找16进制值”,搜索“465753”,在搜索到的“465753”中的“4”位置上单击右键,选择“选块开始”。
  4. 继续“搜索”→“查找16进制值”,搜索“3A5C”,然后按住F3,直到出现“3A5C未找到”,点击“是”,在最后搜索到的“3A5C”中 “C”位置上单击右键,选择“选块结尾”。(注:少数情况可能会搜索不到“3A5C”,则改为搜索“3A”或“5C”,方法相同)。
  5. 在选块内任意处点击右键→编辑→复制选块→进入新文件→输入文件名 (如test.swf) →保存。

  常用破解工具

  谈到破解,很多朋友都会想到时下流行的闪客精灵。以下为常用的破解工具,按笔者使用的频繁程度,分别有:

  * 硕思闪客精灵(Sothink SWF Decompiler)
  * Action Script Viewer(ASV)
  * Imperator FLA(有使用者译为“罗马统治者”)
  (这是笔者最早认识的用来还原swf的工具,可惜一直在关注也没有发现2.0以上的破解版,只有1.6.9.8的破解版,这已经是3年前的版本了,只对Flash6.0以下有效。)
  * 硕思闪客之锤(Sothink SWF Quicker)

  以上四款,以Decompiler最为常用。ASV虽然强大,但在实用性方面却不如Decompiler,这应当也是为什么数年来 Decompiler能够长久风靡的原因。而ASV对付Flashincrypt加密过的swf却是轻而易举,这大大弥补了Decompiler的不足。不少网友知道用ASV来查看swf,但是不知道如何使用它来将swf还原成fla,以5.01版本为例,只需两步:

  1. 打开等待破解的swf文件(支持拖放打开),输出重建数据(File Export Rebuild Data (JSFL)…)到某一目录下,例如:桌面\新建文件夹。
  2. 双击目录下的“rebuildcommand.jsfl”,系统将启动Flash重建fla文件。根据原swf文件的复杂程度,重建fla所需的时间将有所区别。

4.flash的破解:修改后缀绕开下载工具

破解附言

  破解swf,依赖的主要是现成工具,多款工具综合使用,一款不行试另一款,如果作者有意加密,视破解者自身水平,在获取 swf时将遇到规模可大可小的困难,在破解时亦将不可避免的多花些许心思。如果遇到 SWF Encrypt 加密过的作品,只能对其中的AS无奈了。前几天听闻闪客互联的猎人兄对 SWF Encrypt 有破解之法,然而似有卖关之嫌,未见其实。

———————————————————————–

二、加密篇

  加密方法流传不少,此处只谈笔者所知的较为实用的方法:

  更改后缀,避开 Flash Saver 等下载工具

  此方法可有效避开 Flash Saver 等下载工具。使提取者不得不从缓存中查找文件,一定程度上增加了提取难度。后缀可改为 gif、jpg、txt 等等。虽然可以更改后缀,然而在插入到网页时,仍然需要以 swf 的形式插入,使用此 swf 来加载改过后缀的影片。

  限制 Flash 在指定域名/网址中播放 (Flash 防盗链)

  url = "http://www.zhugao.cn";

  /*
以下判断网址的前 20 个字符(字符数根据你的网址作相应修改),如果与"url"不一致则播放失败。注:swf 可以放在任意目录下,只要网址的前 20 个字符是正确的。
*/

  if(_url.substring(0, 20)<>url){
gotoAndStop(2);

  /*
这里可以做一些东西,例如:将发布设置中的“本地回放安全性”设为“只访问网络”,然后在这里做无数的弹窗
onEnterFrame = function(){
getURL("http://www.zhugao.cn", "_blank");
}
*/

5.flash常用加密工具

 }else{
gotoAndPlay(3); //跳到正常播放
}

  为了便于阅读,以下是没有注释的代码:

  url = "http://www.zhugao.cn";
if(_url.substring(0, 20)<>url){
gotoAndStop(2);
}else{
gotoAndPlay(3);
}

  如果要允许多个域名,可以这样写:
url = "http://www.zhugao.cn";
url2 = "http://zhugao.cn";
if((_url.substring(0, 20)==url) || (_url.substring(0, 16)==url2)){
gotoAndPlay(3);
}else{
gotoAndStop(2);
}

  注意:用此方法,设计过程中导出时的技巧:
用IE打开先打开指定目标网址,以避免在导出时频繁弹出窗口,如果无效,请将默认浏览器设置成IE,关闭导出时的player窗口即可继续编辑。有时Flash软件会因此发生错误而被强行结束,导出前请保存文档,切记!

  常用加密工具

  * SWF Encrypt
可有效防止目前流行的几乎所有破解工具对其所加密作品的AS查看。2006年10月更新为3.0.12,尽管加密后文件仍然有明显的增大(视原swf的复杂程度,增大幅度有所不同),然而令人振奋的是,已经支持放射状渐变,支持Flash8.0。加密技巧:分解 swf逐个加密,以尽量避免加密后单个文件体积庞大的问题。

  * Flashincrypt
  可轻易防止闪客精灵目前的版本对其所加密作品的AS查看,加密后的文件几乎保持原文件大小。遗憾的是不能防止 Action Script Viewer 5.0 以上的版本。

6.与JavaScript的结合

适当应用与JavaScript结合

  加密JS,从而实现间接加密swf。相关工具及例子:

  * T4nk JS混淆工具
  用于JavaScript的混淆加密。
  * Encrypt HTML
  加密网页脚本,包括 HTML source code, javascript, VBScript, text, links and graphics 等。
  * 从Flash到JavaScript的通讯,从JavaScript到Flash的通讯
  * 控制 Flash Player JavaScript 方法一览表:
·播放动画:Play()
  例:(网页中的 Flash id).Play();
·停止动画:StopPlay()
·动画是否正在播放:IsPlaying()
·跳转到某帧:GotoFrame(frame_number)
·获取动画总帧数:TotalFrames()
·回传当前动画所在帧数:CurrentFrame()
·使动画返回第一帧:Rewind()
·放大指定区域:SetZoomRect(left,top,right,buttom)
·改变动画大小:Zoom(percent)
·使动画在 x,y 方向上平移:Pan(x_position,y_position,unit)
·返回动画被载入的百分比:PercentLoaded()
·加载动画:LoadMovie(level_number,path)
  例:(网页中的 Flash id).LoadMovie(0, "***/***.swf");
·movie_clip 跳转到指定帧数:TGotoFrame(movie_clip,frame_number)
  例:(网页中的 Flash id).TGotoFrame("_root.实例名.次实例名",帧数);
·movie_clip 跳转到指定标签:TGotoLabel(movie_clip,label_name)
  例:(网页中的 Flash id).TGotoLabel("_root.实例名.次实例名","标签名");
·回传 movie_clip 当前帧:TCurrentFrame(movie_clip)
·回传 movie_clip 当前标签:TCurrentLabel(movie_clip)
·播放 movie_clip:TPlay(movie_clip)
·停止 movie_clip 的播放:TStopPlay(movie_clip)
·获取变量:GetVariable(variable_name)
·变量赋值:SetVariable(variable_name,value)
·call 指定帧上的 action:TCallFrame(movie_clip,frame_number)
·call 指定标签上的 action:TCallLabel(movie_clip,label)
·获取 movie_clip 的指定属性:TGetProperty(movie_clip,property)
·设置 movie_clip 的指定属性:TSetProperty(movie_clip,property,number)

7.在Word中插入flash;打包加壳成exe

在Word中插入Flash

测试环境:WindowsXP / Office2003

可用在独立文件给客户看的时候,尽管可以用前述方法从word中提取swf,然而此方法仍然具有一定防范效果。

1. 新建一Word文档并保存。
2. 在Word中依次单击下拉菜单“视图”→“工具栏”→“控件工具箱”。
3. 在“控件工具箱”中点击“其他控件”,选择列表中的“Shockwave Flash Object”。
4. 右键单击插入进来的Flash播放控件,选择“属性”。
5. 在“属性”窗口的“Movie”栏输入Flash动画的路径及文件名,需要用绝对路径,可采用以下两种:
file:///C:/test/test.swf
http://www.zhugao.cn/test.swf
6. 将“EmbedMovie”项设置为“True”,使Flash嵌入到Word中。“Height”和“Width”分别为Flash的高和宽。 “Scale”默认为ShowAll,为缩放模式,始终显示Flash中的所有内容,如果改为NoScale则始终按1:1比例,不会缩放Flash中的内容。
7. 单击控件工具箱上的“退出设计模式”按钮,在Word中即可播放Flash了。再次按下该按钮则暂停播放,进入设计模式。如当时未显示Flash,请保存退出Word,再打开该Word文档,点击“退出设计模式”按钮即可看到Flash。

打包成加壳exe

用Flash的默认程序打包的exe很容易转成swf,SWFKit是一款很不错的加壳打包软件,不易被还原。

  三、后记

破解时需要多种方法或工具综合使用,加密亦然,需根据用途综合加密。对于网络用swf的推荐加密方案:更改后缀,限制在指定域名播放,分解成多个swf并用SWF Encrypt加密。此方案主要依赖于SWF Encrypt,重在保护作品的AS,一旦SWF Encrypt遭到破解软件的有效攻击,此方案即宣告破产。 文/互联网


几款常用的FLASH
Imperator–最好的FLASH破解工具 1.0
最好的Flash破解工具之一,能将FLASH还原到99%,包括所有的元件,层,侦,As,我见过的最好的工具.

FLASH破解利器 Flash Decompiler v2.9.0.349

SWF Brower

SWF Scanner

硕思闪客精灵 (重点推荐)

Flash发展到现在已经进入MX时代了,Flash的破解软件也随着Flash版本的不断更新发展出了很多种类,我收集的Flash破解软件就不下二十种。

在没有用硕思闪客精灵之前,一般破解一个Flash要经过以下几个步骤:
一.如果是EXE文件,先要转化成SWF文件,这要用Exetoswf或者Swfextractor。
二. 如果要查看其中的Action Script代码,你又要用新的软件了,一般用Action Script Viewer。
硕思闪客精灵的使用相当简单,如果你用过SWF Brower和SWF Scanner的话一看界面就清楚了。打开一个你想破解的SWF文件,选择你需要的素材,然后点Export,选择相应的文件夹就可以了。然后你在这个文 件夹中寻找你需要的素材就可以了。
在这里我结合我使用的经验把硕思闪客精灵和当前名气最盛的SWF Brower、SWF Scanner进行比较,对硕思闪客精灵的优点和缺点做一点个人的分析。
我在Windows 2000平台下对三个软件使用做了一些比较,硕思闪客精灵版本为2001a,SWF Brower版本为2.93,SWF Scanner版本为2.0。
一.三者安装都很简单,在Win2000下能都稳定运行,截面类似,主要功能一目了然,操作性比较好。硕思闪客精灵、SWF Brower在98、me、2000和XP下都可以正常运行,SWF Scanner在XP下不能安装。
二.三者都可以只能打开SWF文件,对打包之后的EXE文件没办法打开。如果以后SWF Decompile能直接打开打包的EXE文件就方便多了。
三. SWF Brower只能打开输出时没有设保护的SWF文件,如果设了保护,就必须用Deflash处理之后才能打开,但硕思闪客精灵不需要使用Deflash处理就可以破解。
四. 三者均能打开Flash5.0及以前版本的SWF文件,对最新的Flash MX输出的6.0版本的flash文件都不能打开。
五. 硕思闪客精灵和SWF Brower都提供了Flash播放功能,但SWF Scanner没有。SWF Brower还能对SWF文件播放进行控制。SWF Dcompiler和SWF Scanner都能想资源管理器一样对电脑的文件夹进行管理,但SWF Scanner只能一次打开一个文件,不便于快速预览。
六.硕思闪客精灵能够对SWF文件里的9中对象进行提取,包括 shape,image,sound,font,text,sprite,buttom,frame。SWF Brower能提取sound events,sound streams,graphics,movies clips,swf internals。SWF Scanner能提取Actions,Sound,Images等。这里就硕思闪客精灵提取的种类最多,达到9种。
七.我们最关系的还是图片和声音的提取。对与位图,三者都能很好获得,但有时候SWF Brower不能提取得很完全,特别是对那些用Deflash处理过的SWF文件提取经常有问题。对于声音的提取,三者都是输出MP3格式的声音,但 SWF Brower提取的声音却经常因为不支持这种格式而不能直接导入Flash中。
八.硕思闪客精灵最大的特点就是能输出frame,就是能把打开的SWF文件分解成单帧的SWF文件。这有什么用处呢,当你要查看这帧里的图片时就可以直 接将生成的这帧SWF文件导入Flash就可以了,而不用将原来庞大的SWF文件整个导入。
九.硕思闪客精灵也提供矢量图输出,但输出的文件格式是gls,只能配合闪客巫师才能使用,而不能直接用Flash打开或导入,这也使我们不能方便的调用源SWF文件中的矢量图。
十. 在输出素材前SWF Brower能预览提取的位图,SWF Scanner能预览提取的声音和图片。硕思闪客精灵没有这些预览功能。
十一.硕思闪客精灵的输出操作可以一步到位,只要选取所有输出类型之后,点Export就可以了。但其他两个软件都要一个一个输入,显得要麻烦多了。
十二.硕思闪客精灵打开文件和输出文件的速度相当快,处理同样大小的SWF文件要比SWF Brower和SWF Scanner要快。
十三. SWF Brower能够做屏幕保护程序,SWF Scanner能够更改文件属性、查看Action Script(没有Action Script Viewer专业)。这些都是硕思闪客精灵所没有的功能。
十四.硕思闪客精灵是由中国人开发的,不仅有英文版而且有中文版,再也不用到处找汉化。

[搜索引擎]Apache Solr : 基于Lucene的可扩展集群搜索服务器

mikel阅读(722)

Apache Solr : 基于Lucene的可扩展集群搜索服务器

作者 Ryan Slobojan译者 崔康 发布于 2008年11月13日 上午7时27分

社区
Java
主题
搜索
标签
Lucene,
Apache Solr

Apache Solr项目,是一款基于Apache Lucene的开源企业搜索服务器,最近发布了1.3版。InfoQ采访了Solr的创建者Yonik Seeley,了解了新版本的更多信息和Solr提供给最终用户的功能。

Seeley首先描述了目标用户:“需要搜索框、分面浏览(导航)或者两者结合的任何人”,Solr的关键特性包括:

  • 基于标准的开放接口——Solr搜索服务器支持通过XML、JSON和HTTP查询和获取结果。
  • 易管理——Solr可以通过HTML页面管理,服务器统计数据以JMX输出,Solr配置通过XML完成。
  • 分面浏览——搜索结果自动分类。
  • 突出显示命中词——匹配的字符自动在搜索结果中高亮显示。
  • 可伸缩性——快速增量更新和快照分发/复制到其他服务器。
  • 灵活的插件体系——新功能能够以插件的形式方便的添加到Solr服务器上。

Seeley同时谈到了该版本中的主要新功能:

  • 分布式搜索——索引现在可以透明的分割成多个部分,单个Solr服务器基于各个配置和模式支持多索引,无须停止Solr服务器就可以改动主要的配置。
  • 扩展了查询功能——包含了一个新的Java客户端(SolrJ)和若干新功能,例如直接配置对于特定查询哪些文档首先命中、近似命中、搜索过期、记录分面时间和拼写检查
  • 增强了数据导入工具——数据库和其他结构化数据源现在都可以导入、映射和转化。
  • 更多可定制扩展点——存在一个新的更新处理器链,允许在查询时修改和重定向文档;一个搜索组件链修改和添加查询结果、用户查询分析器和插件式功能。
  • 性能增强——显著提高了索引速度,二进制响应格式和快速查询删除功能。

详细的更新日志可以这里获得。

Seeley谈到了更多Solr在伸缩性、功能和实用性方面的细节:

Solr已经部署过数以百万计容量的文档,如果借助分布式搜索,Solr应该能够处理数十亿的文档集合。
Solr基于Lucene,具有优秀的全文相关性,可以很方便的提供词组接近性增强、近期文档增强、编辑增强和基于数字值的专有函数的定制评分机制。
AOL正在使用Solr增强它的频道功能:音乐、橄榄球运动、食谱、参考中心、房地产和汽车都使用这项技术。Solr的搜索功能也应用于Netflix、 Zappos、Gamespot、和Internet Archive。还有很多大客户我目前还不能透漏。

关于Solr的未来计划,Seeley提到了更多的可扩展性、对大集群更方便的配置和管理、基于区域和实时的搜索、重构以使用Spring配置插件。Seeley同时提供了一个邮件列表,在那里他详细讨论了Solr未来、特别是2.0版的计划。

查看英文原文:Apache Solr: Extensible, Clustered Search Server Built on Lucene

[C#]BlogEngine.Net架构与源代码分析系列part13:实现分析(上)——HttpHa

mikel阅读(857)

     这已经是系列 的第13篇了,实际上到现在为止您应该对BlogEngine.Net的整体设计有了一定的把握,对部分实现细节有了比较深刻的认识,在阅读 BlogEngine.Net时希望坚持到最后,并把握住宏观,深入到微观。本文将详细介绍BlogEngine.Net中的HttpHandlers与 HttpModules,主要说明它们要实现的功能以及如何使用,并对几个必要的HttpHandler或HttpModule进行比较细致的分析。

     HttpHandler和HttpModule

     对于HttpHandler和HttpModule我这里不想多说了, 因为关于它们讲解的文章实在太多太多了,大家可以在博客园的找找看中直接输入“HttpHandler和HttpModule”就可以找到。我的理解就是 一个HttpHandler要实现IHttpHandler接口,主要是对某个请求进行直接处理,一个HttpModule要实现IHttpModule 接口,主要是在HttpApplication的生命周期的事件中对请求和响应进行过滤。它们都可以在Web.config文件中进行配置。

     BlogEngine.Net中的HttpHandler

     BlogEngine.Net中的HttpHandler都在BlogEngine.Core.Web.HttpHandlers空间下(除了MetaWeblogHandler,已经讲过,这里就不包含它了),通过Web.config我们可以看到它们的映射关系:

HttpHandlers映射表

下面对它们进行一一描述:

FileHandler:主要完成对于一些物理文件的请求,例如在文章中插入的文件资源的请求就由它来处理。它的实现比较简单,就直接去磁盘的文件保存目录中读取,我们只要留意一下SetContentType就行了。

ImageHandler:与FileHandler类似,不过它处理的是图片。与FileHandler分开的原因主要就是图片需要在页面上展现(ContentType必须给浏览器讲清楚或采用默认)。

SyndicationHandler:它比较复杂,主要完成各种订阅需求的处理,需要结合 SyndicationFormat(格式枚举)和SyndicationGenerator(按照SyndicationFormat的格式生成 XML)一起使用。我们可以看一下它的实现过程,首先根据请求的查询字符串生成标题,格式,列表(GenerateItemList使用了Search 等),使用CleanList进行了一个过滤,分页处理,SetHeader,最后使用SyndicationGenerator的WriteFeed进 行了输出。这里考虑的情况比较多,但是BlogEngine.Net使用的分割方法很好的解决了复杂的订阅问题,值得研究一下。

SiteMap:网站地图,可以给一些搜索引擎提供更好的搜索信息,以XML格式将一些文章等页面的链接输出。

TrackbackHandler:接收Trackback信息的处理,前文已经讲过,这里不多说了。

PingbackHandler:接收Pingback信息的处理,前文已经讲过,这里也不多说了。

OpenSearchHandler:提供公开搜索处理,前文已经讲过,这里也不多说了。

RsdHandler:这个处理器很有用,它完成将BlogEngine.Net中的一些公开的接口等信息发布出去,类似WebService的WSDL文件。

CssHandler:主要处理了页面中的Css文件的压缩,上文中讲述BlogBasePage中提及过。处理器的实现很值得关注,压缩可以使用gzip或deflate两种格式,

经典的压缩处理

并提供了一些事件供外界Hookup处理。压缩之前去掉空格等字符,分为从本地获得文件和从远程使用WebClient下载文件。并使用了缓存。

JavaScriptHandler:主要处理页面中引用的脚本的压缩,与Css处理方式类似。注意StripWhitespace的处理与Css的不同。

RatingHandler:主要完成给Post打分的功能,记得上文中有部分涉及到,从PostViewBase中的Rating可以看出,这个请求实际上是通过Ajax发送过来的。

OpmlHandler:获得OPML列表文件,类似收藏文章的列表。

BlogMLExportHandler:BlogEngine.Net中的文章导出处理,以前的文章讲过。

Sioc、Foaf、Apml的注释都是“Based on John Dyer's (http://johndyer.name/) extension.”,这个应该是对于某个标准XML的输出吧,主要提供了本博客系统中的一些公开的信息。关于它们不做太多的研究,我想这并不影响我们 对BlogEngine.Net的研究。

     实际上这些HttpHandlers的请求链接很多都是在BlogBasePage加入到Html的Head中的,或者给浏览器使用,或者给搜索引擎使用。

     BlogEngine.Net中的HttpModule

     BlogEngine.Net中的HttpModule都在BlogEngine.Core.Web.HttpModules空间下,通过Web.config我们可以看到它们的映射关系:

httpModules映射表

请注意它们的注册顺序,因为WwwSubDomainModule和UrlRewrite都Hookup了HttpApplication的BeginRequest事件。下面对它们进行一一描述:

WwwSubDomainModule:Hookup了HttpApplication的BeginRequest事件,主要是对请求的URL中的"www"的处理以得到绝对的链接。

UrlRewrite:Hookup了HttpApplication的BeginRequest事 件,对一些URL的重写,实际上WwwSubDomainModule和UrlRewrite都是在处理URL,我们在看BlogEngine.Net中 的源代码时多留意一下它的URL,包括Post中的各种链接的URL等,注意区分它们都是做什么用的。

ReferrerModule:主要是对于请求的Referrer进行统计,纪录这些请求都是从哪里发送来的,提供了相应的事件供外部Hookup,注意IsSpam的实现和对于纪录日志使用了新线程来异步完成。

CompressionModule:一个Page页面的压缩处理模块,同样根据请求来判断是使用 gzip还是deflate,对于页面中链接的WebResource也是用WebResourceFilter进行了过滤处 理,WebResourceFilter实现了Stream,

WebResourceFilter的Write方法

在重写的Write中主要是将webresource.axd转交给了JavaScriptHandler处理以达到压缩的目的。注意它是在PreRequestHandlerExecute中Hookup的,都是给Response提供的流过滤器。

     总结

     由于篇幅所限,对于BlogEngine.Net中一些 HttpHandlers和HttpModules我并没有作更多的深入讨论,这里只是提供给大家一个学习指南,希望有所帮助。 BlogEngine.Net中大量使用了正则匹配,Url处理,压缩,缓存等都是比较通用的,值得我们关注与学习。

     通用的处理方法值得我们去收藏

     上一篇:BlogEngine.Net架构与源代码分析系列part12:页面共同的基类——BlogBasePage

     

     返回到目录

版权声明
作者:Thriving.country
出处:http://thriving-country.cnblogs.com/
本文版权归作者和博客园共同所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接.

[C#]BlogEngine.Net架构与源代码分析系列part12:页面共同的基类——BlogBa

mikel阅读(886)

     上一篇文章我 向大家展示了BlogEngine.Net中Theme的原理和一些开发规范,里面有很多内容和这篇文章有着联系,建议大家这两篇文章结合在一起看,这样 效果会更好。在这篇文章中我主要向大家说明BlogBasePage,PostViewBase,CommentViewBase这三个类的内部实现上的 一些技巧以及它们与页面,文章和评论之间是如何组织在一起的,希望对大家阅读这部分代码有帮助。

     认识一下它们

     BlogBasePage,PostViewBase,CommentViewBase它们都是一些元素的基类,首先把这些元素定义成基类,然后使用继承的方式实现我认为主要有以下好处:

1.代码复用会得到提升,对于一些大量的同样操作都可以放在基类中,子类直接可以继承使用。

2.职责清晰,例如在Theme中的CommentView.ascx直接继承CommentViewBase就行了,CommentView.ascx只是来处理将Comment如何展现的问题。

3.规范化,这是继承带来的一个很重要的好处,因为子类就是一个父类,只要它是就可以使用

BlogBasePage:Web站点的根目录下的每一个页面都是从它继承而来,BlogBasePage继承自Page。而页面不是直接从Page继承而来。
PostViewBase:是一个Post显示功能部分的基类,themes中每个主题的PostView.ascx都是直接从它继承而来,PostViewBase继承自UserControl。
CommentViewBase:是一个Comment显示功能部分的基类,themes中每个主题的CommentView.ascx都是直接从它继承而来,CommentViewBase继承自UserControl。

     实现分析

     BlogBasePage到底都做了些什么?

OnPreInit中主要完成根据BlogSetting中的Theme找到相应的页面的Master文件(包括主题选择时的预览判断),此外还处理了Post的删除。
OnLoad中做得事情很多,主要是在head中加入一些资源引用(包括SIOC,APML,FOAF等),实际上就是当我们打开页面查看源代码看到 head中多如牛毛的link。还有增加一些脚本的全局变量,增加BlogSetting中的自定义Head的html,增加track脚本,增加脚本引 用(通过JavaScriptHandler来实现),增加样式(注意css的压缩是通过CssHandler实现的)。
OnPreRenderComplete中完成了标题的设置。
OnError中还对使用Comment的恶意攻击做了处理。

protected override void OnError(EventArgs e)
{
    HttpContext ctx 
= HttpContext.Current;
    Exception exception 
= ctx.Server.GetLastError();
    
if (exception != null && exception.Message.Contains("callback"))
    {
        
// This is a robot spam attack so we send it a 404 status to make it go away.
        ctx.Response.StatusCode = 404;
        ctx.Server.ClearError();
        Comment.OnSpamAttack();
    }
    
base.OnError(e);
}

 

     PostViewBase到底都做了些什么?

PostViewBase是一个用户控件,主要是显示一个Post,内部除了一些Post属性 外,还有CommentFeed(通过SyndicationHandler处理),增加分类链接,增加Tag链接,增加管理链接,增加评分的脚本来给文 章评分等。此外在Page_Load还对加入内容中的一个自定义的控件标签进行了特殊的处理,这种格式如:[UserControl:~/path /usercontrol.ascx],使用一个正则来判断,如果内容中有这种标签,那么内容显示时使用加载的控件来代替。

     CommentViewBase到底都做了些什么?

CommentViewBase是一个用户控件,主要是显示一个Comment,内部除了Comment和Post属性外,还有内容,管理链接,国旗显示,Gravatar显示等。请大家留意一下后面的两个图片的显示处理。

     了解了这些,上一篇文章中讲述的Theme中的几个必要文件的数据显示问题就清晰多了吧。

     页面的继承与组织关系

     这部分没有什么原理性的东西,只是帮助大家快速阅读代码而做的一个文件的介绍。

login.aspx:继承BlogBasePage,完成登录,注销,修改密码等与登录有关的用户接口。
default.aspx:继承BlogBasePage,内部使用PostList.ascx用户控件完成文章的列表显示接口。
search.aspx:继承BlogBasePage,用一个repeater显示搜索结果,这个以前提及过。
archive.aspx:继承BlogBasePage,对文章的归档显示,注意它的归档的处理过程。
contact.aspx:继承BlogBasePage,主要是完成阅读者给文章的发布者发送邮件。注意它还实现了ICallbackEventHandler,来完成ajax回调提交。
error404.aspx:继承BlogBasePage,404错误转向。
page.aspx:继承BlogBasePage,完成删除Page,显示Page(注意对注入控件显示的处理和与Post区别)。
post.aspx:继承BlogBasePage,完成文章的显示,使用User controls/CommentView.ascx来完成评论列表的显示和评论的提交。Page_Init中动态加载PostViewBase,处理了 “上一篇”和“下一篇”等导航链接(需要Post类本身的支持),phRDF完成了Trackback的接收(以前文章提及过)。
对于Theme中的文件上文已经讲过,这里就不再多说。
对于admin/Pages中的这些管理页面都是直接继承自Page,Master为admin1.master,在Web.config中定义了访问权限等,这主要是实现了前端页面和后台管理的分开处理。
blog.js是BlogEngine.Net的所有脚本文件,里面封装Ajax处理(例如回调,评论的在线浏览等)。

     总结

     像BlogEngine.Net这种将几乎所有页面的Page再进行一下自定义的封 装的处理方式在很多项目中都会得到应用,这一点我觉得很好。对于注入控件的处理方式也值得我们去学习。这种注入控件我想主要是完成一些外部资源的引入问题 的,把文章或Page的显示交给这个用户控件来处理会很灵活。

     麻雀虽小,五脏俱全

     上一篇:BlogEngine.Net架构与源代码分析系列part11:开发扩展(下)——自定义Theme

 

     返回到目录

版权声明
作者:Thriving.country
出处:http://thriving-country.cnblogs.com/
本文版权归作者和博客园共同所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接.

[C#]BlogEngine.Net架构与源代码分析系列part11:开发扩展(下)——自定义The

mikel阅读(876)

     个性化的主题是一个完善的 Blog系统中所必备的,同时也是一个亮点。在这篇文章里我将给大家展示一下BlogEngine.Net的第三个开发特性,那就是自定义的Theme。 本文的重点放在BlogEngine.Net的开发规范和实现原理上。如果您对BlogEngine.Net的架构很了解的话,那么开发一个自己的 Theme是一件很简单的事情,如果您不是很了解,那么你也可以按照本文讲述的规范开发出一个自定义的Theme来。

     BlogEngine.Net中的Theme

     在BlogEngine.Net的源代码中默认存储了三个Theme(Standard默认,Mobile移动版,Indigo),更多的Theme您可以到它的官方站点下载。 同样这些Theme支持热插拔,我们只要把下载的Theme放在themes目录下就可以实现它的安装。相信这种Theme会给用户带来更多的使用上的感 受。由于BlogEngine.Net开放源代码,所以对于Theme的开发也完全由用户自己控制。如果大家想知道这个Theme到底有多厉害,看看 BlogEngine.Net的官方站点就知道了,估计那就是使用BlogEngine.Net,然后换了一个Theme做的。

     规范与原理

     对于用户来说到底使用哪个Theme是存储在BlogSetting中的,在设置页 面中我们可以看到一个下拉列表来选择主题,这个下拉列表的数据是通过读取themes目录下的子文件夹名称获得的,这就要求我们在开发Theme时要以 Theme的名称作为这个文件夹的名称。需要注意的一个问题就是在BlogEngine.Net的Web站点的根目录下的所有.aspx的 Codebehind都是继承自BlogBasePage,这个类又继承自Page类,也就是说BlogBasePage将一些页面中共有的操作进行了统 一的处理,对于这个类我会在接下来的一篇文章中进行分析。

     在BlogBasePage中有这么一段代码:

private string _Theme = BlogSettings.Instance.Theme;
/// <summary>
/// Assignes the selected theme to the pages.
/// </summary>
protected override void OnPreInit(EventArgs e)
{            
    
if (Request.QueryString["theme"!= null)
        _Theme 
= Request.QueryString["theme"];
    MasterPageFile 
= Utils.RelativeWebRoot + "themes/" + _Theme + "/site.master";
    
base.OnPreInit(e);
    
//….

}

 

这段代码就是在页面预初始化时(注意一定要放在这个处理器中)将Page的 MasterPageFiles设置为BlogSetting中所设置主题名称的目录中的site.master,这就要求我们在开发自己的Theme时 需要创建页面的主文件site.master。

     此外就是在研究了PostViewBase和CommentViewBase(这两个类也会在下一篇文章中做详细的说明)的实现以后对于Post和Comment的显示也是到BlogSetting中所设置主题名称的目录中去查找PostView.ascx(直接继承自PostViewBase)和CommentView.ascx(直接继承自CommentViewBase),这就需要我们在开发自己的Theme中需要创建文章的显示界面PostView.ascx和评论的显示界面CommentView.ascx。

     以上几个文件是开发BlogEngine.Net的Theme所必须的,实际上也就形成了一个完整的前台页面了。当然你也可以定义自己的布局,css,图片等。这些文件到底应该如何定义,以Standard为例,先让我们看一下它的实现。

     site.master中依次是资源的引入,header部分,顶部的一些链接,主题部分,版权部分,WidgetZone。请注意:

<blog:SearchOnSearch runat="server" MaxResults="3" Headline="You searched for" Text="Here are some results for the search term on this website" />
<asp:ContentPlaceHolder ID="cphBody" runat="server" />

SearchOnSearch是一个控件,主要完成根据搜索引擎的参数在本站中进行再次搜索。<asp:ContentPlaceHolder ID="cphBody" runat="server" />在site.master中必须存在的,因为Page中已经存在对它的引用。

     PostView.ascx中依次是标题,作者,创建时间,主体,标签,分类,一些链接和管理菜单。其中<asp:PlaceHolder ID="BodyContent" runat="server" />同样也是必须存在的,因为在PostViewBase中就是将Post的内容输出到BodyContent控件中(请参照PostViewBase的Page_Load方法)。

     CommentView.ascx中依次是评论的作者,时间,Gravatar图片显示,内容,管理连接等。这里似乎没有什么是必须的。

     只要遵守这些规范我们就可以开发Theme了,除此之外对于Widget的引入我们也不必使用WidgetZone,只要将这些Widget的控件类直接放在site.master中就行了,其实这已经不能算作一个Widget,只能说是一种类似Widget的控件。对于BlogBasePage,PostViewBase,CommentViewBase以及各个页面之间的继承关系,我会在下一篇文章中做详细的介绍,希望大家继续关注。

     总结

     这篇文章涉及到的内容比较少,并且和下一篇文章有很多联系。实际上,Theme的实现应该是基于BlogBasePage,PostViewBase,CommentViewBase等的,它主要应用了ASP.NETsite.master布局页面,通过动态设置实现。这样操作损失了一个IDE的重要特性——智能感知,开发起来可能会有些不便,但是这样的架构还是不错的。

     看来ASP.NET的site.master的确很有用

     上一篇:BlogEngine.Net架构与源代码分析系列part10:开发扩展(中)——Widget小工具

 

     返回到目录

版权声明
作者:Thriving.country
出处:http://thriving-country.cnblogs.com/
本文版权归作者和博客园共同所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接.

[C#]BlogEngine.Net架构与源代码分析系列part10:开发扩展(中)——Widget

mikel阅读(971)

   上篇文章我向大家介绍了BlogEngine.Net中开发扩展的重要一部分——Extension。在本文中我将向大家展示它的另外一种扩展特性,那就是Widget小工具,主要是Widget的开发标准和工作原理等。

     什么是Widget与为什么要使用Widget

     Widget实际上就是一种带有界面的小工具,主要应用在桌面领域,例 如:Yahoo!Widget,还有Vista自带的边栏等。在BlogEngine.Net中它就是页面左侧或右侧的那种小的分区,例如 Category list,Calendar,Tag cloud等,这种东西实际上在很多Blog系统中都存在,在BlogEngine.Net中我们就叫它Widget。

     Widget可以将Blog系统中很多的功能提供给用户一个统一的界面访问接口。如果有一些功能需要加到页面上,我们首先考虑的就是可否作成一个Widget来实现,因为这种Widget具有统一的开发标准,可以很方便的达到我们的目的。

     WidgetBase和WidgetEditBase

     在BlogEngine.Net中,作为一个有界面的Widget我们只需要继承WidgetBase类就行了。WidgetBase直接继承了UserControl,重写了Render用来生成统一的Widget界面,至于具体Widget中显示什么,则由自定义Widget类本身来完成,WidgetBase中 有一个抽象方法LoadWidget用来完成Widget对象的初始化工作,IsEditable用于说明Widget是否可以编辑,如果可以编辑在 Render时就会输出编辑按钮,那么这个Widget也必须提供一个编辑界面(继承了WidgetEditBase)。此外还需要注意WidgetBase中GetSettings会根据WidgetID从DataStore(前文讲述过)中获得相应的配置信息(也就是内容信息)并存储在Cache中。Cache在这部分的DataStore的处理中运用很多,希望大家留意。

     如果某个Widget可以编辑,那么它还需要一个实现WidgetEditBase的类,这个类主要是给用户提供一个对于Widget配置信息(具体内容)修改的界面,它提供了一个抽象的Save方法用于将修改的信息保存到DataStore中,还有一个Saved事件用于外部监听以便进行扩展。

     所有已经实现的Widget必须放在widgets目录下,并以Widget的名称给相应的文件夹命名,如果只是浏览我们加入一个widget.ascx就行了,如果需要修改还需要加入一个edit.ascx,以TextBox(可以设置一些关于作者的描述信息)的实现为例:

在widgets\TextBox中有widget.ascxedit.ascx两个文件(加上Codebehind一共四个),在widget.ascx.cs的LoadWidget(重写父类的方法)获得DataStore信息并加入到Widget内容中。

Code

同样对于edit.ascx.cs中重写了父类的Save方法将内容又保存回DataStore中。

     Widget的增,删,改,排序等是如何处理的

     在admin目录下存在WidgetEditor.aspx用来对Widget的操作进行处理。它实际上是一个通用的模板,也是一个操作的路由,根据请求的参数进行相应的操作。

增加Widget:我们将自己的按照上文的标准开发的Widget放在widgets的目录以后就已经完成了Widget的安装。通过添加列表(这 是WidgetZone生成的一个列表,实际上就是搜索widgets目录下的文件而获得的所有已安装的Widget列表)就可以转向 WidgetEditor.aspx,之后将这个Widget添加进来,而WidgetEditor.aspx是通过AddWidget方法完成的。

删除Widget:这里的删除不是卸载,而只是从WidgetZone中移出Widget,同时删除DataStore信息。当我们点击 Widget中的删除时会使用WidgetEditor.aspx来处理,而WidgetEditor.aspx又是通过RemoveWidget完成 的。

修改Widget:当我们点击Widget的修改时会转向WidgetEditor.aspx,而WidgetEditor.aspx使用 InitEditor读取了DataStore中的信息并加载了相应Widget中的edit.ascx,实际上对于Widget的修改一部分(总体的描 述信息)是通过WidgetEditor.aspx直接修改完成的,而另一部分(Widget的配置信息)则是由WidgetEditor.aspx委托 edit.ascx来完成的,这样做的好处显而易见,可以实现修改界面的个性化处理,这也是继承带来的好处。

Code

 

排序Widget:当我们在拖动某个Widget时它会进行新的排序,这个排序是持久性的。最初见到BlogEngine.Net时这个功能就很吸引我。那么它是如何实现的呢?

Code

从这里可以看出move是一个使用";"分隔的WidgetID序列来表示顺序,这个序列是JavaScript生成的。服务器接收到这个序列以后 使用MoveWidgets并对于DataStore中的Widget列表进行重新的排序。对于JavaScript的实现已经超出本文的范围,这里不做 讨论。感兴趣的朋友可以研究一下admin/widget.js,Widget这部分的所有JavaScript都在此,写的也是不错的。

     由此可见WidgetEditor.aspx是Widget管理的一个核心。

     WidgetZone是一个Widget的容器

     WidgetZone上文已经涉及到,它就是一个Widget的容器。 WidgetZone继承自PlaceHolder,在OnLoad时会根据DataStore将已经添加的Widget加载到PlaceHolder 中,在Render的时候还会去查找安装在widgets目录下的Widget列表。这个WidgetZone在BlogEngine.Net中并不是一 个必须的类,你可以将Widget直接放在主界面的某个位置上就可以使用。但是,如果不使用它来管理而直接显示Widget会失去Widget的管理特 性,在下一篇制作Theme的文章中我会对其进行详细的说明。

     总结

     Widget的实现无非是BlogEngine.Net中的经典。 BlogEngine.Net对这些界面上的小工具进行了统一的抽象,尤其是继承的使用带来了很大的扩展空间。WidgetEditor.aspx的统一 管理也是非常经典的,尤其是排序和修改部分更值得大家仔细研究。此外,Widget的XCopy安装也是很不错的,实际上BlogEngine.Net的 一个重要特性就是在Web上实现了很多这种热插拔(Plug'n play),包括Extension,Widget等。

     继承的正确使用给我们带来的好处实在太多

     上一篇:BlogEngine.Net架构与源代码分析系列part9:开发扩展(上)——Extension与管理上的实现

 

     返回到目录

版权声明
作者:Thriving.country
出处:http://thriving-country.cnblogs.com/
本文版权归作者和博客园共同所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接.

[C#]BlogEngine.Net架构与源代码分析系列part9:开发扩展(上)——Extensi

mikel阅读(1462)

     从这篇文章开始的连续三篇文章我将向大家展示BlogEngine.Net中的三大开发扩展特性,它们分别是Extension,Widget和Theme。程序员可以在符合一定标准条件下开发自己的扩展,然后将扩展像插件一样(Plug'n play)与BlogEngine.Net进行集成,来达到个性化的应用。本文将详细介绍第一种扩展Extension的开发标准,管理部分介绍等。

     声明一下
     上一篇文章的回复中有人提到希望我写一下自己的看法和BlogEngine.Net的优缺点等,实际上我想把这些内容放在最后的总结篇里,不过 在以后的每一篇文章中我也会或多或少的加入一些。对于这些看法只是我的一己之见,如果您觉得有帮助那更好,如果有不对之处还请指出。

     什么是Extension与为什么使用Extension

     Extension这个词我很喜欢,具有扩展之意。BlogEngine.Net中的Extension是特指使用了ExtensionAttribute特性标明的类。ExtensionAttribute被定义在BlogEngine.Core.Web.Controls中,继承了.Net中Attribute,内部主要有描述,版本,作者等成员。主要用来标识一个Extension类的信息,以便统一管理模型。BlogEngine.Net中的Extension都被放在了Web站点的App_Code\Extensions或子目录中。它在内部实现时大都是通过静态构造器来监听业务类的消息,并对这些消息提供一些处理。

     Extension在BlogEngine.Net中可以做很多事情,例如:纪录业务日志,对文章的词语进行过滤或替换,对业务类活动的统计分析等。总之,写一些Extension会给你的Blog带来很多意想不到的扩展,目前一些开源社区已经有很多对于BlogEngine.Net的Extension的开发,这里有很多下载,感兴趣的朋友可以研究一下。

     认识一下BlogEngine.Net已有的Extension

     在Web站点的App_Code\Extensions中我们会看到有很多Extension。

     Smilies:监听了Comment.Serving,也就是每当有评论被显示(Serving)时,它就会使用Post_CommentServing处理,主要是将评论中一些词语替换成一些图片。

     SendPings:这里不再说了,在本系列的第七篇文章中已经做了详细的说明。它主要是发送pingback和trackback信息等。

     SendCommentMail:就是每当文章有评论产生时根据配置会向文章作者的邮箱发送评论邮件,功能类似博客园中的评论邮件发送,实现类似Smilies的实现。

     ResolveLinks:也就是每当有评论被显示(Serving)时,解决评论中的超链接过长等问题。

     BreakPost:实现得很有意思,主要是处理文章显示的[more]问题,这都可以作为扩展,真是绝了。从这里我们也能看出以前的一个疑问,那就是Serving的作用,它主要是处理显示问题的,给[more]加入超链接。

     BBCode:似乎是一个在评论显示时,进行字符替换以便按照样式显示的Extension。

     CodeFormatter:这是一个第三方开发的对文章中包含的源代码进行格式输出的Extension。对于它的实现比较复杂,但是结构还是比较清晰的,有兴趣的朋友可以研究一下,这里就不再做过多说明。

     实现一个自己的Extension

     对于开发人员来说实现一个Extension是很简单的事,例如我们想把文章访问的IP纪录下来就可以这样实现:

LoggingIP

 

     Extension如何被Host起来的

     BlogEngine.Net使用反射技术来启动这些Extension。这些Extension在整个应用程序启动时随之启动,应用程序通过查找已编译的程序集动态加载这些Extension类到内存中来,也就执行了类构造器,实际上这些Extension也就运行起来。我们在Global.asax中可以看到如下代码:

 1 void Application_Start(object sender, EventArgs e)
 2 {
 3     ArrayList codeAssemblies = Utils.CodeAssemblies();
 4     foreach (Assembly a in codeAssemblies)
 5     {
 6         Type[] types = a.GetTypes();
 7         foreach (Type type in types)
 8         {
 9             object[] attributes = type.GetCustomAttributes(typeof(ExtensionAttribute), false);
10             foreach (object attribute in attributes)
11             {
12                 if (ExtensionManager.ExtensionEnabled(type.Name))
13                 {
14                     a.CreateInstance(type.FullName);
15                 }
16             }
17         }
18     }
19 }

这里请大家注意一下Utils.CodeAssemblies()的实现使用了反射动态加载已编译的程序集(查找程序集的方法)。对于 ExtensionManager.ExtensionEnabled是在管理中判断这个Extension是否启用,ExtensionManager 下文会提到。

     Extension的管理

     这里所说的Extension目前可能还不是很完善。不过它的实现是 BlogEngine.Net非常经典的一部分,很值得去仔细学习和研究,其中很多地方应用到了反射,XML序列化等。它提供给管理员对这些 Extension一个统一的管理,包括控制源代码的浏览,应用和取消Extension,对其进行设置(DataStore)等。由于这部分的源代码比 较多,不适合对其进行更细致的分析,我在这里只是简单介绍一下它的整体设计。

ExtensionManager分成了两部分:
1.逻辑处理,位于App_Code/ExtensionManager中,有四个.cs文件:
ExtensionManager:完成了Extension管理部分常用的方法,也对页面提供一些直接性的服务。
ManagedExtension:是每个可被管理的Extension类的封装。
ExtensionSettings:也是为了管理Extension而封装的设置类,注意它与BlogEngine.Core.DataStore中的同名类的区别。
ExtensionParameter:主要是为ExtensionSettings服务的参数处理的封装。
这些是ExtensionManager主要逻辑,完成包括Extenison配置的加载和存储调用,缓存处理,统一化的管理模型,为页面提供一些直接的服务等。
1.页面管理,位于admin/Extension Manager中,这一部分是调用第一部分来实现管理的,第一部分中有很多信息也是为它服务的:

Default.aspx:一个承载页面,路由导航。
Extensions.ascx:一个Extenison的管理列表。
Editor.ascx:是Extension源代码浏览器。
Settings.ascx:是Extension设置器。注意它实际上是一个统一的配置界面。

对于ExtensionManager的实现逻辑是很复杂的,希望这个整体的介绍能给您阅读代码时带来帮助,如果有不清楚的问题可以给我回复一起讨 论。这一部分我们需要注意一下配置从DataStore的加载和修改是如何完成的,对于逻辑中的配置和参数部分是如何统一化的。

     总结

     我觉得Extension这种扩展非常的优秀,当然这种扩展要想发挥出来肯定对于业务核心部 分地设计是有很多要求的。尤其是它的ExtensionManager对模型的统一性的处理更值得我们去学习和研究,里面的反射机制用的很棒。不过目前这 个ExtensionManager还有很多不太完善的地方,例如源代码修改支持,新Extension的动态添加等,可能BlogEngine.Net 会在将来的版本中提供这些功能吧。

     上一篇:BlogEngine.Net架构与源代码分析系列part8:扩展——DataStore分析

 

     返回到目录

版权声明
作者:Thriving.country
出处:http://thriving-country.cnblogs.com/
本文版权归作者和博客园共同所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接.

[C#]BlogEngine.Net架构与源代码分析系列part8:扩展——DataStore分析

mikel阅读(829)

     本系列的第四篇文章我 给大家做了关于BlogEngine.Net全局配置的分析。在这篇文章里我将会对BlogEngine.Net中比较经典的部分DataStore做一 个简单的分析,这个DataStore主要完成了BlogEngine.Net三大扩展特性(Extension,Widget,Theme)的数据存储 部分,它提供了一个扩展特性统一的存储模型。DataStore是建立在Provider存储(本系列第三篇文章中介绍过)的上层,本文研究的内容会和后面讲到的扩展部分的文章有一定联系,希望大家继续关注。

     BlogEngine.Net三大扩展特性大多数都是由开发者完成的, 也就是说大多数都是后加入到BlogEngine.Net中的,所以这些存储必须单独完成,而且对于模型的统一性很重要。既然是由开发者开发,那么这些标 准就显得格外重要,这样开发出的部分才可以与系统中的部分很好的集成。这里所说的DataStore就是指 BlogEngine.Core.DataStore空间下的类型。

BlogEngine.Net中的DataStore如何设计的

先看一幅继承图吧:

从上图我们可以看到ExtensionSettings和WidgetSettings是SettingBase的直接子类。ExtensionSettings主要是为Extension而对SettingBase的实现,WidgetSettings是为Widget而对SettingBase的实现,对于Theme整个BlogEngine.Net中目前没有涉及到。

ExtensionSettingsBehavior,StringDictionaryBehavior,XMLDocumentBehavior 这三个类都实现了ISettingsBehavior接口,而ISettingsBehavior只有加载配置和保存配置两个方法声明。此外 ExtensionType是一个枚举用来表示扩展的类型。

SettingBase也有加载和保存配置的两个方法,此外SettingBase中还有一个对于ISettingsBehavior的引用,而SettingBase的加载和保存内部也是通过ISettingsBehavior的保存和加载完成的,这好像是一个桥模式。由以上分析我们可以知道对于Extension的数据加载和保存是通过ExtensionSettings完成的,具体实现是由ExtensionSettingsBehavior来做,ExtensionSettingsBehavior的内部使用BlogService调用Provider完成。对于Widget的数据的加载和保存是通过WidgetSettings完成的,具体实现由StringDictionaryBehavior来做,StringDictionaryBehavior的内部也是使用BlogService调用Provider完成,注意SerializableStringDictionary继承自StringDictionary并实现了IXmlSerializable来完成字典对象的序列化和反序列化。

     对于Extension的存储的具体信息通过代码我们可以看到是一个Object,这个Object的格式是由ExtensionManager(这个在后续的相关文章也会讲到)来确定的,也主要是为ExtensionManager服务的。

<?xml version="1.0" encoding="utf-8"?>
<ManagedExtension xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Name="Smilies">
<Version>1.3</Version>
     <Description>Converts ASCII smilies into real smilies in the comments</Description>
     <Author>BlogEngine.NET</Author>
     <AdminPage />
     <Enabled>true</Enabled>

     <ShowSettings>true</ShowSettings>
</ManagedExtension>

WidgetSettings的存储的具体信息实际上是一个字典,字典项代表具体信息。

<?xml version="1.0" encoding="utf-8"?>
<SerializableStringDictionary>
  
<SerializableStringDictionary>
    
<DictionaryEntry Key="content" Value="Something about the author " />
  
</SerializableStringDictionary>
</SerializableStringDictionary>

XMLDocumentBehavior主要是为了配置WidgetZone而设计的,它实际上是一个Widget的集合的配置,在页面加载时会读取这些配置来决定怎样显示相应的Widget。

除此之外还需要我们注意的一个地方就是配置对象在XML和数据库的存储表示,实际上它们内部的信息都是一段XML,相应的对于这两种的数据访问的结 果处理也是不一致的(我觉得这个地方设计的不是很好,因为这一层似乎对于Provider有些依赖关系代码,参见 XMLDocumentBehavior.cs,不过还好毕竟是实现依赖于实现嘛,可能也没想出更好的办法)。

客户端的使用

     Extension(App_Code\ExtensionManager\Manager.cs):

Code

     StringDictionary(widgets\TextBox\edit.ascx.cs):

Code

     XMLDocument(App_Code\Controls\WidgetZone.cs):

Code

     对于客户端的使用部分涉及到了Extension,Widget部分等,这些内容会在后续的文章中进行详细说明。

总结

1.桥模式的使用

2.统一的配置模型

3.对于XML存储和数据库存储的处理方式不同

     面向对象的设计原则真是太经典了

     上一篇:BlogEngine.Net架构与源代码分析系列part7:Web2.0特性——Pingback&Trackback

 

     返回到目录

版权声明
作者:Thriving.country
出处:http://thriving-country.cnblogs.com/
本文版权归作者和博客园共同所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接.

[C#]BlogEngine.Net架构与源代码分析系列part7:Web2.0特性——Pingba

mikel阅读(992)

     今 天这篇文章主要向大家讲述一下Blog系统中应用最多的,具有Web2.0特性的,也是一种标准化的——Pingback&Trackback。 分析一下BlogEngine.Net提供的比较全面的Pingback&Trackback支持。本文内容相对来说比较独立,如果您对整个系列 感兴趣请参照这里

Pingback&Trackback参考

     简单地说,Pingback&Trackback是博客在链接、引用其他博客内容时通知对方博客的一种自动机制,告知对方链接位置及可能包含一定的摘要文本(视情况而定)。这样带来的好处是显而易见的,对Pingback&Trackback发送者来说,避免了手动通知对方的麻烦;对Pingback&Trackback接收者而言,则可以随时掌握自己的某篇文章被什么人链接及具体链接信息,等等。例如:

博客A发布了一篇文章;博客B看到后,发布评论、引用、介绍博客A上该篇文章的贴子;但此时博 客A是无从知道博客B上对自己文章的引用情况的,要让博客A知道,博客B须:在博客A上留言,介绍自己对该篇文章的看法,比如说“在我的博客发布了一篇文 章,也讨论这个问题——”,并附上相应页面的链接;向博客A发送E-mail,说明自己对该篇文章的进一步讨论,同时,也许希望博客A能在页面上放上自己 的链接,以帮助对这一话题有兴趣的用户能找到自己的博客;Pingback&Trackback实现的功能便是将第三个步骤自动化了,再也不需这么一个繁琐的过程,即:博客A发布了一篇文章;博客B看到后,发布评论、引用、介绍博客A上该篇文章的贴子;在文章发布时,博客B即自动向博客A发送Pingback&Trackback;博客A收到相应的Pingback&Trackback,如果未设置人工审核,相应的内容即会出现在博客A该文的留言中,如果设置了人工审核,则出现在博客A的审核列表中,博客A认为不是spam后将其发布在留言中。

BlogEngine.Net中的Pingback&Trackback实现

BlogEngine.Net中的Pingback&Trackback的实现主要涉及到以下几组文件:

1.Web站点App_Code/Extensions中:SendPings.cs
2.BlogEngine.Core的Ping中:PingService.cs、Manager.cs、Pingback.cs、Trackback.cs
3.BlogEngine.Core的Web/HttpHandlers中:PingbackHandler.cs、TrackbackHandler.cs

     从BlogEngine.Net中的Pingback&Trackback的具体实现来看,Pingback和Trackback的区别只在于数据的交换格式上,Pingback和PingService主要是使用标准的XMLRPC来完成数据的交换(上一篇文章中有部分涉及),而Trackback主要的request是使用类似的下面的格式完成:title={0}&url={1}&excerpt={2}&blog_name={3},response同样是使用XML传输

<?xml version=\"1.0\" encoding=\"iso-8859-1\"?><response><error>0</error></response>

但是它们要实现的功能是类似的。

     实际上SendPings类是BlogEngine.Net的一个Extension(类具有Extension特性,这个后面会有专门的一篇文章来讲解),它监听了Page.Saved和Post.Saved:

1 /// <summary>
2 /// Hooks up an event handler to the Post.Saved event.
3 /// </summary>
4 static SendPings()
5 {
6     Post.Saved += new EventHandler<SavedEventArgs>(Post_Saved);
7     Page.Saved += new EventHandler<SavedEventArgs>(Post_Saved);
8 }

这里再次证明了BusinessBase这种状态维护方式的优越性。

     通过代码我们可以看出当Page或Post被保存时会向 SendPings发出通知,之后SendPings会从线程池中获得一个线程来向PingService发送Ping消息并使用Manager发送 Pingback&Trackback消息。PingService这里主要是处理我们自己设置的Ping服务,对服务地址列表中的服务发送通知 来说明某篇文章已经更新了。Manager主要分析文章中的超链接部分,找到Trackback入口地址,然后向该地址发送Trackback的 TrackbackMessage(这是一个消息的封装,注意它使用Trackback请求的格式重写了ToString方法),如果发送不成功再向这个 地址发送Pingback消息。Pingback和Trackback这两个类主要完成了Pingback&Trackback消息格式的具体处 理并执行发送之。

Code

 

使用PingbackHandler和TrackbackHandler对外提供支持

     同样PingbackHandler和TrackbackHandler两个 HttpHandler主要是为了使BlogEngine.Net也具有接收Pingback&Trackback消息并处理的能力。它们都是从 请求中获得数据,并将这些数据生成一个Comment对象并关联到相应的文章中,同样它们也提供了 Received,Accepted,Rejected,Spammed四个静态(类)事件来对这一处理周期进行跟踪,外部可以对这些事件提供相应的处理 程序来达到扩展的目的。请大家注意,在Web站点中的Post.aspx中有下面一段代码:

<!– 
    <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
      <rdf:Description rdf:about="<%=Post.AbsoluteLink %>" dc:identifier="<%=Post.AbsoluteLink %>" dc:title="<%=Post.Title %>" trackback:ping="<%=Post.TrackbackLink %>" />
    </rdf:RDF>
    
–>

这段代码被使用Html注释掉了,生成的Html为如下格式:

<!– 
    <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
      <rdf:Description rdf:about="http://localhost/BlogEngine.Web/post/2008/06/28/Welcome-to-BlogEngineNET-1-4.aspx" dc:identifier="http://localhost/BlogEngine.Web/post/2008/06/28/Welcome-to-BlogEngineNET-1-4.aspx" dc:title="Welcome to BlogEngine.NET 1.4.5" trackback:ping="http://localhost/BlogEngine.Web/trackback.axd?id=c3b491e5-59ac-4f6a-81e5-27e971b903ed" />
    </rdf:RDF>
    
–>

http://localhost/BlogEngine.Web/trackback.axd?id=c3b491e5-59ac-4f6a-81e5-27e971b903ed实际上就是这篇文章的Trackback地址。

     当然这个Trackback地址一般可以由用户自己指定,例如在博客园发文章时我们就可以自己输入一个。

参考文章

1.Trackback和Pingback的区别

2.Trackback, Pingback , Backlink与博客

     有些东西只有成为标准以后才会发光。

     上一篇:BlogEngine.Net架构与源代码分析系列part6:开放API——MetaWeblog与BlogImporter

     下一篇:BlogEngine.Net架构与源代码分析系列part8:扩展——DataStore分析

 

     返回到目录

版权声明
作者:Thriving.country
出处:http://thriving-country.cnblogs.com/
本文版权归作者和博客园共同所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接.