8、截取过滤器
截取过滤器(intercepting filter)主要用于对于用户请求的之前处理和之后处理,也就是说它对于客户的请求使用了额外的操作。比如说,servlet可以处理一个网站的所有客户请求并提供一个核心的认证机制。
这种模式主要工作于表示层,负责处理不同类型的请求,同时也需要进行多种不同的处理。在这些请求中,有一些请求会直接传送给后端模块处理,而另外一些请求则先会在过滤器里解释或补充内容,之后才能传送给后端模块。这种模式的提出主要是由于一个客户的Web访问和系统响应都需要一定的预处理和后处理,例如用户身份、用户环境信息、用户请求的合法性等。通常这些处理的结果都会决定用户的请求是否能够进行,或是系统的响应应该用什么格式来表示。
对于这种预处理和后处理问题,传统上,开发人员会设计一系列额外的检测程序模块,也就是一整套if/else语句,并且指定如果其中任何一个检测失败,所有的处理工作都会退出。显然,这种方法是存在很大弊端的,即代码的可读性、可维护性都会被大大降低,同时将检测工作融于一般的程序模块,使得整个程序的模块性难以保证。
解决这种问题的关键在于,设计一种简单的技术,以能够添加或移除额外处理的模块,而这些模块通常都能够完成一定的检测和过滤功能。根据以上的讨论,J2EE研究人员提出了设计模式----截取过滤器作为解决方案,这种模式可以在不影响核心处理模块的情况下,实现可插入的过滤器来执行一般的处理功能。
从理论上来说,这种过滤器可以截取客户请求和系统响应,并进行相应的预处理和后处理;同时开发人员也可以随时根据需要移除这些过滤器,并不用担心会改变任何其他模块。
我们这里所说的预处理和后处理功能,通常是指一些基本的系统服务,如安全、登录,系统调试等。执行这些功能的过滤器通常是需要与核心模块分开的,并且由于系统职能或规则的变化,这些模块随时可能被添加或删除。
下面提供一些关于截取过滤器的图示,以帮助大家更好地理解这种设计模式,并合理地加以运用。图19表示了截取过滤器模式的整体结构,图19显示了截取过滤器中的参与模块和相互之间的联系。

图19 截取过滤器模式

图20 截取过滤器序列图
下面我们分别来说明图20中的各个模块:
(1)过滤管理器(Filter Manager)。过滤管理器负责过滤器的主要处理工作,即创建过滤器链对象以及相应的过滤器组建,并初始化整个处理过程。
(2)过滤器链(Filter Chain)。过滤器链是一组互不依赖的过滤器有序集合。
(3)过滤器1,过滤器2,过滤器3(FilterOne,FilterTwo,FilterThree)。这些都是提供不同服务的过滤器,而过滤器链则负责它们的协调工作。
通过采用这种设计模式,应用系统可以取得更方便的中心控制,这是由于过滤器可以提供处理多种请求的中心模块,并能根据后端的处理模块而解释和润色用户的请求,使得该请求能更好地与处理模块所提供的功能匹配。另外,过滤器通常可以将不同种类的服务聚集在一起,并提供相当灵活的服务组合,应用系统可以通过使用截取过滤器提高其重用性,过滤器可以随时根据需要从其他程序模块中插入或移除,并且由于它们通常具有标准的接口,开发人员可以使用一组类似的过滤器,并在不同的情况下进行全组的重用。
采用这种设计模式也会带来一定的问题,即在过滤器之间共享信息将变得非常困难,这是由于根据其定义和需求,每个过滤器的设计和开发都大相径庭。因而如果在不同的过滤器之间需要共享信息的话,其代价将是非常昂贵的。
作者:务实,多年从事J2EE网站及应用系统项目的开发和应用。
参考资料:
《J2EE设计开发编程指南》Rod Johnson 电子工业出版社
《J2EE参考大全》Jim Keogh 电子工业出版社
《实用J2EE设计模式编程指南》Craig A.Berry 电子工业出版社
