背景
在程序实现的过程中我们往往碰到类似于这样的问题:为了防止后台接收数据不能乱码,我们需要在处理的Servlet中设置请求字符集,就会在每一个Servlet中加上这样的代码:
request.setCharacterEncoding("GB18030");
这样的代码就是在程序中写死了的,设置字符集的功能是不利于维护的,如果将来要修改为另外一种字符集类型,需要在每个Servlet中进行修改。如果要进行封装,同样面临每个Servlet都要调用的问题,而往往这种方法调用是与具体业务需求关系不大的。在这种情况下,是无法用正常的编程方式解决的。针对于此类问题,引入了类似于AOP思想的Filter技术。
基本介绍
Filter是Servlet2.3规范新增加的功能。使开发人员可以在用户请求到达Servlet之前改变request或者在Response离开Servlet是改变Response。
Filter作用示意图:
1.原始架构实现图
2.加入Filter
我们在Tomcat与Servlet之间加入了Filter类,在Web-Info配置中加入匹配规则以及相应配置,即可实现在Tomcat启动时,调用Filter的init方法进行初始化,在客户端进行操作时,对符合规则的操作,则Tomcat自动调用doFilter方法进行拦截处理,类似的道理,我们也可以对response对象进行操作。
<!--Filter配置,与Filter具体实现类对应--> <filter> <!--filter名称--> <filter-name>CharsetEncodingFilter</filter-name> <!--对应具体实现类类--> <filter-class>com.tgb.drp.util.filter.CharsetEncodingFilter</filter-class> <!--初始化参数,类似于键值对方式存取--> <init-param> <param-name>encoding</param-name> <param-value>GBK</param-value> </init-param> </filter> <!--匹配规则配置--> <filter-mapping> <filter-name>CharsetEncodingFilter</filter-name> <url-pattern>*.jsp</url-pattern> </filter-mapping>
Filter与职责链模式
前面讨论了单个Filter的具体使用情况,那它具体是怎样体现职责链模式的呢?我们先回顾一下职责链模式的结构图:
职责链模式中,通过Client端设置具体处理者类的上家与下家,通过实现抽象类的抽象方法HandleRequest来具体处理某一个具体情况内的请求,如果不在处理范围内,则调用上家进行处理。
在Filter技术的应用中,Filter接口则对应了Handler抽象类,而我们不必调用SetSuccessor方法,在web.xml中就可以指定Filter的上下级调用关系,因此在doFilter方法中直接调用chain.doFilter方法即可执行继任者的doFilter方法,由此可见,Filter技术是职责链模式的更高级应用的体现。
Filter与Servelt
由以上内容可以看出,Filter与Servlet之间是层层包裹的关系,它通过拦截用户对Servlet的请求来提前或置后处理一些request或response的数据信息。
总结
Filter常用于权限控制、记录日志、转换编码格式、加密等与具体业务处理耦合性不高的功能上,我们可以认为它是一个执行过滤的插件,也可以形象的看作是滤网、过滤器。它提供了一种声明式的服务,具有着可插拔的能力,达到了更好的复用。
参考资料
Java中Filter、Servlet、Listener的学习