反射实现动态初始化责任链

本文涉及的产品
函数计算FC,每月15万CU 3个月
简介:

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

clip_image002[7]

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

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

public   FilterChain   Add ( Filter   filter ) 

{ 
     filterChain . Add ( filter ) ; 
     return   this ; 
} 
7

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

FilterChain   fc   =   new   FilterChain ( ) ; 
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,问题解决了。

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

怎么做?

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

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

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

1   private   FilterChain   DynamicAdd ( ) 
2  
3   { 
4        string   fileContent   =   File . ReadAllText ( " Filter.config " ) ;

 


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

 


6        Assembly   ass   =   Assembly . GetExecutingAssembly ( ) ;

 


7        Type [ ]   types   =   ass . GetTypes ( ) ;

 


8        object   obj   =   null ;

9        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> 类型,然后在类构造器而不是实例构造器中去动态初始化它。这样在过滤时就完全不需要去考虑初始化过滤链的事儿了。当过滤需求放生变化时,只需修改配置文件,然后重启一下服务即可。进而摆脱频繁修改代码的烦恼。


本文转自HDDevTeam 51CTO博客,原文链接:http://blog.51cto.com/hddev/622944,如需转载请自行联系原作者

相关文章
|
1月前
|
存储 Java
JVM知识体系学习四:排序规范(happens-before原则)、对象创建过程、对象的内存中存储布局、对象的大小、对象头内容、对象如何定位、对象如何分配
这篇文章详细地介绍了Java对象的创建过程、内存布局、对象头的MarkWord、对象的定位方式以及对象的分配策略,并深入探讨了happens-before原则以确保多线程环境下的正确同步。
57 0
JVM知识体系学习四:排序规范(happens-before原则)、对象创建过程、对象的内存中存储布局、对象的大小、对象头内容、对象如何定位、对象如何分配
|
3月前
|
缓存 前端开发 Java
反射加缓存,解决不同的业务下调用不同的实现
反射加缓存,解决不同的业务下调用不同的实现
34 0
|
5月前
new 一个对象的过程中发生了什么
new 一个对象的过程中发生了什么
|
6月前
|
编译器 数据安全/隐私保护 C++
【类与对象】封装&对象的初始化及清理
【类与对象】封装&对象的初始化及清理
|
6月前
|
设计模式 缓存 安全
代理模式:解析对象间的间接访问与控制
代理模式:解析对象间的间接访问与控制
|
设计模式 Java 数据库连接
JAVA设计模式8:装饰模式,动态地将责任附加到对象上,扩展对象的功能
JAVA设计模式8:装饰模式,动态地将责任附加到对象上,扩展对象的功能
|
存储 安全 Java
一文解读类的加载过程(类的生命周期)(上)
一文解读类的加载过程(类的生命周期)
|
缓存 Java 开发者
一文解读类的加载过程(类的生命周期)(下)
一文解读类的加载过程(类的生命周期)(下)
|
设计模式 JavaScript 前端开发
从【if...else...】到【责任链】再到【composeAOP】,顺带把【传参】解决了~
从【if...else...】到【责任链】再到【composeAOP】,顺带把【传参】解决了~
从【if...else...】到【责任链】再到【composeAOP】,顺带把【传参】解决了~
|
设计模式 前端开发 C#
C#开发中使用委托的作用和好处
先看概念,什么是委托? 从程序的角度来讲:你就可以把委托看成是用来执行方法(函数)的一个“指针” 通俗的说就是:通过委托,我们可以把方法当成参数传递。 这里我举个例子:“设想,如果我们写了一个厨师做菜的方法,里面有拿菜、切菜、配菜、炒菜四个步骤,但编写此方法代码的人想让配菜这个环节让调用方法的人来实现,换句话说,就是想把方法作为参数来传递,那么怎么来实现呢? 方法1:使用接口,这里不是我们讨论的。
7540 0