Community Server专题(转贴)

来源:互联网 发布:mysql索引创建查询 编辑:程序博客网 时间:2024/04/29 10:00

Community Server(CS)是一个非常优秀的Asp.net开源软件,目前官方发布的系统中包括三个部分:Asp.net Forums、DotText、Gallery。如果你是某个以CS构架网站的会员,你可以很容易的就拥有一个Blog、一个相册、还能在论坛上与他人一起进行讨论,这样就形成一个以User为中心的社区,这也就是起名为Community Server的意义所在了。

CS的构架很巧妙,三套原本不同的开源软件在Telligent Systems的努力下结合在了一起,统一进行用户管理与权限设置(Menbership)、统一进行异常处理、统一进行本地化资源管理(多语言实现)等等。虽然这不能完整地看成是Portal实现,但是从代码角度看已经非常模块化了,可以快速的进行扩展同时又能获得很好的性能。实现这些主要依靠工程中的两个项目:CommunityServerComponents与CommunityServerControls。

CommunityServerComponents中包含一些全局业务逻辑类,如:Globals、Context等、一些接口和用来继承的父类,如:Group、Section、Thread、Post等、还有就是实现Membership的实体类。异常处理与Url Rewrite是通过继承IHttpModule接口实现的,当然要实现IHttpModule的继承就一定要进行配置,该项目中通过类CSConfiguration实现了一些全局的配置等。HttpHandler也得到了运用,主要是处理一些不存在的Url,如读取用户头像的时候就是使用的HttpHandler。缓存作为Web程序提高运行效率最有效的方法之一在该项目中主要是在CSCache类中,该类没有什么高深的代码主要是对缓存方法进行包装,然后供全局统一管理。

CommunityServerControls侧重的是UI表现的业务逻辑,其中包含的很多公用的用户自定义控件,典型的就是Editor、ResourceLabel,ResourceLabel几个项目中的web页面下基本都有他的身影。该项目还有一个重要的目的就是提供Skin功能,TemplatedWebControl为Forums、Blog、Gallery几个项目提供Skin的基类,当然如果你扩展CS添加自己的项目,也是需要继承TemplatedWebControl,具体如何实现换肤后面会有专题进行单独的介绍,Asp.net Forums 原来换肤使用的是皮肤的全名(如:Skin-PostView.ascx),但是在现在的项目中不需要提供全名只在基类中提供“Skin-{0}.ascx”,之后用GetType().Name得到{0},组合后就是全名了。也就是说只要需要扩展皮肤类的类名和皮肤的{0}名字相同,就可以自动的找到他对应的Skin,小小的改进方便了许多。CS使用Membership统一用户与权限管理,而用户与权限管理作为所有扩展项目的基础,因此CommunityServerControls中实现了Membership的UI业务逻辑。

CommunityServerForums、CommunityServerGalleries、CommunityServerBlogs就是三个运用项目的实现了,三层结构,通过大量的继承,抽象等等完成的。CommunityServerGuestBook是一个简单的扩展项目,分析代码你会发现其实CS的扩展式非常容易的,而且高效。

CS在数据库方面也有一些优秀的设计,如全部使用存储过程,很多时候高手都会告诉你,在项目中全部使用存储过程是不理智的,但是CS确这样做。关键一点是他有一个SqlGenerator类和一些xx Query类,这些类可以根据要求产生SQL Text(主要是一些多变的Search和Post查询),然后这些SQL Text作为存储过程的参数被传入,最后使用EXEC执行它得到需要的结果。SQL Text比起存储过程来的灵活,但容易出现漏洞最后被利用出现SQL注入攻击,CS这样的做法一举两得,当然这需要更多的时间去编写代码。还有就是用存储过程实现的数据分页读取等。

CommunityServerWeb项目是所有webpage html、资源文件、配置文件、js等的集合。该项目本身没有逻辑代码,分析主要是目录的结构与安排。

CS与Asp.net 2.0的关系密切,Membership、Localization、MasterPage、Url Rewrite这些在Asp.net 2.0中眼熟的词汇在CS中你可以很容易看到它们的实现,不只是运用,你可以通过代码看到它们是如何实现的。

说了很多优点,最后说一下缺点:由于CS的前身是Asp.net Forums,在目前发布的版本中还可以很容易的看到Forums残留的影子,如果不了解其发展的人分析起来一些变量会让你摸不着头脑,另外基础构架部分也有一部分代码与Forums跌在了一起,不过我想随着下一个版本,或者下下个版本的发布CS会更有吸引力 ,我是非常希望CS下个版本发布的时候加入WebPart等更多的特性。

 
原文地址:http://ugoer.cnblogs.com/archive/2005/09/01/228097.html


在进行CS细节分析的之前,有必要先了解CS工程(解决方案)的组成,以及组成CS工程中项目的结构,本文分为三个部分:1、工程结构 2、三层构架 3、数据库构架。

1:工程结构


按此在新窗口打开图片

CS工程主要分为4个部分

a:系统底层构架项目CommunityServerComponents、CommunityServerControls,提供给其他项目父类、接口、全局变量、CS系统设置、公用用户自定义控件、用户与权限管理业务逻辑、异常处理等。

b:CommunityServerBlogs、CommunityServerForums、CommunityServerGalleries、CommunityServerDocuments、CommunityServerGuestBook。这些项目都是通过继承、调用全局方法等实现自己的业务逻辑并且抽象出自己的Data Provider,业务逻辑不同,但项目都是采用三层结构。

c:UI项目,这里指CommunityServerWeb。该项目中几乎不包含逻辑代码,只是简单的Html与对运用项目中的Skin(Skin是 *.ascx文件,但没有关联相应的*.cs,大致可以这样理解:如CommunityServerBlogs 中的Skin 文件*.ascx相关联的*.cs逻辑代码在CommunityServerBlogs项目中实现,并且不保存在与*.ascx文件相同的目录下,而是与CommunityServerBlogs中其他业务逻辑一起编译为CommunityServer.Blogs.dll)。同时UI项目中还保存了Languages文件与一些配置文件等。

d:DataProvider,目前只实现了SqlDataProvider,对SQL Server数据库进行操作。DataProvider实际上是对b部分中实体项目数据库操作抽象的具体实现。数据操作的Provider方式带来几个好处,不关心具体实现、支持多数据库、有利于团队协作分工等。

2、三层构架

在CommunityServerBlogs、CommunityServerForums、CommunityServerGalleries等几个项目中都采用了三层构架,如下图:


按此在新窗口打开图片

业务逻辑是穿插在Contorls与Components中,在单独的一个项目中Contorls与Components体现在namespace里,下面以CommunityServerGalleries项目为例讲述一下具体项目的三层结构:


按此在新窗口打开图片

为了便于文件的管理,项目中建立了Components与Contorls文件夹分别存放名字空间为CommunityServer.Galleries.Components与CommunityServer.Galleries.Controls。如果你是一个初学者或者对三层结构不是太了解,可能很多时候你会对三层构架感到困惑,其实这个层的概念没有绝对的划分界限,更不是用类作为最小的单位。这种划分是相对的,是一种为编写代码功能的划分。CommunityServerGalleries项目中没有直接编写对数据库的操作代码,而是使用了Provider的方式把操作的方法进行抽象:

例:public abstract Hashtable GetGalleries(bool mergePermissions);

抽象后的代码可以和普通方法一样被业务逻辑调用,由于使用了Provider的方式,使得数据层与业务层之间是松散耦合的,可以很容易的进行数据库更换(只需要更换对抽象数据操作类的具体实现方法,而不会影响到业务逻辑层的代码)。

业务逻辑包括几个部分:CommunityServer.Galleries.Components下所有的实体类,这些实体类大多数通过继承Post、IThread、PermissionBase等在CommunityServerComponents项目中定义过或者申明过的类与接口。CommunityServer.Galleries命名空间下的一些类,这些类用来处理业务逻辑运行过程中的数据,同时进行缓存和过滤等操作(过滤操作是通过在CommunityServerComponents项目中的CSApplication.cs类下定义委托与事件完成的,要理解这个过程需要对CS有一定的了解,后续我会做一个CS中委托与事件的专题)。还有一部分业务逻辑混淆在CommunityServer.Galleries.Controls命名空间下的一些类中,他们与UI表示层较为紧密,你很难准确的定义他们是属于业务逻辑还是表现层代码。

CS中表示层中的类大致可以分为三部分,1:是需要*.ascx的直接处理用户界面或者用户输入输出的代码,这些类都间接的继承CommunityServerControls项目中的TemplatedWebControl类。2:要进行换肤就少不了使用一些辅助的类,这些类提供一些基础服务,如:找到*.cs文件对应*.ascx所在路径等。3:是不需要*.ascx的用户自定义控件,一般继承自.Net提供的WebControls。这些类被放入Controls/Utility文件夹下面。

传统的Asp.net Web页面设计时在建立*.aspx或者*.ascx都会同时建立一个同名的*.cs文件,用来实现对页面中控件的操作,页面这个时候就像一个容器。通过Codebehind页面在运行时会自动找到对应的类(这个过程如何实现没有去分析过,但是我们可以通过反射达到同样的效果,同时可以获得更高的灵活性)。CS系统中的UI就是通过反射寻找到*.ascx对应的类从而实现相应的UI处理函数,而*.ascx只要保持名称和内容中控件的ID不变,具体Html代码如何更换并不影响到整个系统的功能,CS系统也正是通过这样的手段达到换肤的目的,同时加入MasterPage又可以减少Html代码中重复部分。最后Html与CSS样式表的结合你就可以很容易改变网站的皮肤的样式,包括文字样子和div的布局了。*.cs与*.ascx文件剥离后网站美工与程序设计人员就真正的分开了,有利于团队协作,发挥个人特长。

还有一点必须说明:在CS项目中很多*.aspx文件只是一个加入了MasterPage的框架页,甚至是一个什么都没有的空文件(如多数default.aspx页面),框架文件中嵌入了大量的类似于“<Galleries:GalleryAdmin id="GalleryAdmin" runat="server" />”这样的控件,其实这个控件对应于Skin-GalleryAdmin.ascx的皮肤。如果你能理解到这里,想看明白CS的大部分代码应该不会有问题。

3、数据库构架

先看一下DataProvider模型:


按此在新窗口打开图片

模型中可以看出抽象的DataProvider是与具体的数据库操作DataProvider分离的,在CS中Components与抽象的DataProvider被编译在一个项目中,而SQL Server DataProvider则被单独的编译出来。好处都可以看到那就是更换不同的DataProvider抽象实现不同的数据库操作,另外这种松散耦合的方式有利于团队开放。如何实现这样的DataProvider方式呢(我这里简述一些,具体的请关注后续的专题)?

先看抽象类

按此在新窗口打开图片

,抽象类被存放在相应项目的Providers目录下,以Gallery项目为例子,它的命名空间是CommunityServer.Galleries.Components

按此在新窗口打开图片

整个类都是public abstract class,这个很好理解,其实关键的是在“Instance”

部分,在 Instance里通过调用CommunityServerComponents项目DataProviders.cs类中的CreateInstance方法初始化一个GalleryDataProvider。

过程是先在Communityserver.config文件中找到

public static readonly string GalleryDataProviderName = "GalleryDataProvider";

中的“GalleryDataProvider”,这里为:

<add  name = "GalleryDataProvider" type = "CommunityServer.Data.GallerySqlDataProvider, CommunityServer.SqlDataProvider" connectionStringName = "SiteSqlServer" databaseOwnerStringName = "SiteSqlServerOwner"    />

根据“type”中的内容,运用Type.GetType与Activator.CreateInstance把CommunityServer.SqlDataProvider.dll程序集中对应的CommunityServer.Data.GallerySqlDataProvider类实例化,实例化后类似GalleryDataProvider.Instance().GetGalleries(true)的调用其实就是直接操作CommunityServer.SqlDataProvider.dll程序集中CommunityServer.Data.GallerySqlDataProvider类下的

public override Hashtable GetGalleries(bool mergePermissions)方法。这个过程可能比较难理解,但是理解只是时间问题。

数据访问层的中与数据库最紧密接触的就是SqlDataProvider(SqlDataProvider是对SQL Server数据库操作抽象的实现,你也可以对其他数据库进行抽象实现,目前CS只提供SQL Server实现),在SqlDataProvider里使用的是对存储过程的操作而没有使用SQL Text。在前一片专题中我写过这个做的好处,这里不再多说。主要说明的是对数据的缓存与序化:

缓存:我个人习惯是把缓存写在数据层里,而CS是把缓存管理写在业务逻辑层中,而且缓存的数量是很大的,如对CommunityServerGalleries项目中的读取单个Gallery方法:

public static Gallery GetGallery(string applicationKey, bool cacheable)

一般的做法是为这个方法写一个存储过程,然后当有数据操作的时候从数据库中调用相关数据,同时根据参数是否缓存数据,这看起来很好。我也总是觉得内存宝贵,能少缓存一点就少缓存一点,但是CS的做法是把全部Gallery读入Hashtable,缓存掉!要读取单个Gallery的时候从缓存中找,根本不去管数据库,更不要写存储过程(这倒是很方便)。当然了,CS中是对缓存定义了时间的。时间到期后缓存就自动被释放了,但是在缓存释放之前新的数据是不会被显示出来的,对于一些更新不是很快的数据集来说这算是一种比较好的解决方案(在SQL 2005中有更好的缓存解决方法,可以在新数据更新时更新缓存)。

数据序化:开发过CRM的朋友应该都有体会,很多字段需要预留在数据库中,因为你不了解使用CRM系统的客户会有一些什么样的存储要求,如:CRM用户需要保存他客户的年龄,但是CRM系统设计过程中不可能为这样一个问题特意的加入这个存储字段,通常的做法是给一些空字段,用户使用的时候相应的对他进行初始化。但是导致的结果就是CRM的数据库惨不忍睹。更可怕的是,如果要进行软件升级的时候如果需要添加一些原本没有的字段,非常的麻烦,从实体类到数据库操作的存储过程都需要更改。而数据序化可以解决这个问题,其实当我第一次看到CS这种做法的时候是非常兴奋的:第一,实现了添加字段不需要重新写数据操作类,更不需要对相关的存储过程进行修改。第二,存储的字段很工整,全部值都保存在两个字段中,如图:


按此在新窗口打开图片
先分析一下存储的数据,首先是PropertyNames字段,“EnableComments:S:0:4:ModerateComments:S:4:5:EnableRatings:S:9:4:” “EnableComments”其实是在实体类中定义的一个属性名称,“:”表示定义完毕,“S:0:4”表示在PropertyValues字段中的字符从0开始后面4位属于“EnableComments”的属性值,同理:“S:4:5”表示,从第四个字符开始,后面5个表示“ModerateComments”的属性值,以此类推可以获得PropertyNames所有的字段的值。(记得在Asp.net Forums时数据的序化是用Binary存储的,在CS中改为ntext可以对其进行搜索,解决序化后的数据搜索不便的问题。),关于如何进行序化等后续专题加以叙述。

在CS的最底层就是数据库和存储过程了,关键的几个表cs_Groups、cs_Sections、cs_Threads和cs_Posts表分别对应于CommuntyServer.Components命名空间下的Group、Section、Thread和Post类,Groups是分组,对应论坛来说就是“板块组”、版块”、“线索”和“帖子”,对应于Blog就是“博客分组”、“博客”“线索”、“随笔或者文章”。这个cs_Threads有点难理解,其实它是对相应Section下的Post相关信息的统计与跟踪,如最后回帖时间、评论总数等等。

上面大致分析了Community Server项目的体系结构,细节部分会在后续的专题中一一的分析。不管怎么说Community Server是一个相对庞大的工程,要完全的讲解与系统的分析还需要很多的文字。

原文地址:http://ugoer.cnblogs.com/archive/2005/09/02/228682.html

原创粉丝点击