有一个DNS服务器项目(其实是最近在做的一个智能DNS项目)的过滤模块,现有如下需求:1.能准确判断出用户IP地址是否合法,及用户IP是否位于黑名单中;2.用户请求查询的主机名是否合法,机主机名是否位于黑名单中。要实现对以上用户请求过滤。后期可能还要实现对ddos***请求的过滤。由于前一段时间了解了一下责任链模式,所以决定用责任链模式实现该模块。类结构图如下所示(图画的不一定准确,凑合着看吧):

clip_p_w_picpath002[7]

图中有一个抽象类Filter,他有一个抽象方法Validate(),用于实现对请求的过滤。其他类均继承自Filter类。其中IPFilter实现对IP过滤,DomainNameFilter实现对主机名的过滤。DDOsFilter实现对DDOs请求过滤,暂时未使用。FilterChain中有一个List<Filter> 类型对象filterChain用于存放各个过滤器。还有一个Add()方法用来向filterChain中添加过滤器。

现在由于没有新的需求,采用的是静态的去初始化filterChain。方法如下:

1 public   FilterChain   Add ( Filter   filter )
2
3 {
4     filterChain . Add ( filter ) ;
5     return   this ;
6 }
7

然后,可以像下面一样去调用这个方法:

1 FilterChain   fc   =   new   FilterChain ( ) ;
2 fc . Add ( new   IPFilter ( ) ) . Add ( new   DomainNameFilter ( ) ) . Add ( new   DDosFilter ( ) ) ;
3

OK,现在只需调用fc.Validate(),就可以实现对IP和主机名的过滤。

似乎,我们已经实现该模块的功能了,而且用着也挺简单,调用时完全不需要知道过滤具体是怎么实现的。很完美,所以经测试之后我们将系统发布到服务器上开始工作。

但是,我们似乎忽略了一点。假如现在我们发现有用户发送恶意请求企图***我们的服务器,导致我们的服务器不能正常的为其他用户提供服务。我们当然不能容忍这种行为,更不能让***者得逞。所以我们要将DDosFilter也投入使用来时我们的系统更加强壮。

What should we do?

我们需要修改代码。如上面的fc.Add().Add().Add(),我们可以再在后面加一个Add().

OK,问题解决了。

假如,现在又有新的需求,主机名过滤不在那么重要了,要将其去掉。

怎么做?

正如上面我们需要修改代码来完成工作。但是慢慢的我们会发现,我们每次都需要修改代码,而且每次只是需要修改一丁点儿的代码。但是我们的系统已经正式发布了,每次只为这么一点小事就修改代码,会显示出我们的系统不够强壮。而且每次的一丁点的修改,也使我们的工作看起来似乎没什么意义。

我们寻求更加简便的方法来完成对系统的更改。于是我们想到了配置文件。我们可以将要使用的过滤器写入配置文件中,这样只需修改配置文件就可以完成对系统的更改,而无需修改代码。

最近,看了看反射(虽然课堂上老师说只是了解即可,可我的直觉告诉我这个东西可以多了解一些,它很有用),它完全可胜任这一工作。当然还会有其他方法。但本文只探讨用反射机制实现。于是产生了如下面的代码:

private   FilterChain   DynamicAdd ( )

{
    string   fileContent   =   File . ReadAllText ( " Filter.config " ) ;

 


    string [ ]   filters   =   fileContent . Trim ( ) . Split ( ' ; ' ) ;

 


    Assembly   ass   =   Assembly . GetExecutingAssembly ( ) ;

 


    Type [ ]   types   =   ass . GetTypes ( ) ;

 


    object   obj   =   null ;

    foreach   ( var   item   in   filters )
10         {

 


11         try
12             {

 


13                 obj   =   ass . CreateInstance ( item . Trim ( ) ) ;

 


14             }

 


15         catch   ( Exception )
16             {

 


17                   continue ;

 


18             }
19             if   ( obj   ! =   null )
                    {

 


20                        filterChain . Add ( ( Filter ) obj ) ;
21                 }
            }

22                 return   this ;
23       }
24

其中,需要加载的过滤器放在filter.config这个文件中。格式如下:

Filter.IPFilter;Filter.DomainNameFilter;Filter.DDosFilter

      从配置文件中可以读出过滤器的名称,然后通过反射构造出对应过滤器的对象,然后将对象加入filterChain中,从而实现filterChain的动态初始化。

      对于过滤规则,一个系统有一组就够了,所以可以进一步将filterChain声明为 private static List<Filter> 类型,然后在类构造器而不是实例构造器中去动态初始化它。这样在过滤时就完全不需要去考虑初始化过滤链的事儿了。当过滤需求放生变化时,只需修改配置文件,然后重启一下服务即可。进而摆脱频繁修改代码的烦恼。