在DRP项目中,多次提到了Filter,它解决了字符集的统一设置以及统一控制简单WebCache,从中我们可以体会到,它给我们带来的好处不仅仅是减少代码量这么简单,它的出现避免了我们每个页面重复的编写相同的代码,减少了我们的工作量,而且给维护带来了极大的便利,那么它是如何实现统一管理的呢?既然它能统一管理某些重复的操作,那么它和AOP有什么关系呢?
Filter简介
ServletAPI中提供了一个Filter接口,开发web应用时,如果编写的Java类实现了这个接口,则把这个java类称之为过滤器Filter。
通过Filter技术,开发人员可以实现用户在访问某个目标资源之前,对访问的请求和响应进行拦截。简单说,就是可以实现web容器对某资源的访问前截获进行相关的处理,还可以在某资源向web容器返回响应前进行截获进行处理。
下图是filter调用关系的UML图:
一个filter必须实现javax.servlet.Filter。
三个方法
1. voidsetFilterConfig(FilterConfig config) //设置filter 的配置对象;
2. FilterConfiggetFilterConfig() //返回filter的配置对象;
3. voiddoFilter(ServletRequest req,ServletResponse res,FilterChain chain) //执行filter的工作
Filter实现拦截的原理
Filter接口中有一个doFilter方法,当开发人员编写好Filter类实现doFilter方法,并配置对哪个web资源进行拦截后,WEB服务器每次在调用web资源的service方法之前(服务器内部对资源的访问机制决定的),都会先调用一下filter的doFilter方法。
应用举例:
批量设置请求编码
xml配置代码
如上的代码完成的功能为,无论进入那个页面,都要先执行EncodingFilter类的dofilter方法设置字符集
其中,doFilter()方法类似于Servlet接口的service()方法。当客户端请求目标资源的时候,容器就会调用与这个目标资源相关联的过滤器的doFilter()方法。
参数 request, response 为web 容器或 Filter 链的上一个 Filter 传递过来的请求和相应对象;参数 chain 代表当前 Filter 链的对象。
对于FilterChain接口,代表当前Filter链的对象。由容器实现,容器将其实例作为参数传入过滤器对象的doFilter()方法中。
过滤器对象使用FilterChain对象调用过滤器链中的下一个过滤器,或者目标Servlet 程序去处理,也可以直接向客户端返回响应信息,或者利用RequestDispatcher的forward()和include()方法,以及HttpServletResponse的sendRedirect()方法将请求转向到其他资源。
这个方法的请求和响应参数的类型是 ServletRequest和ServletResponse,也就是说,过滤器的使用并不依赖于具体的协议。
Filter生命周期
和Servlet一样,Filter的创建和销毁也是由WEB服务器负责。
与Servlet区别的是
1>在应用启动的时候就进行装载Filter类而servlet是在请求时才创建(但filter与Servlet的load-on-startup配置效果相同)。
2>容器创建好Filter对象实例后,调用init()方法。接着被Web容器保存进应用级的集合容器中去了等待着,用户访问资源。
3>当用户访问的资源正好被Filter的url-pattern拦截时,容器会取出Filter类调用doFilter方法,下次或多次访问被拦截的资源时,Web容器会直接取出指定Filter对象实例调用doFilter方法(Filter对象常驻留Web容器了)。
4>当应用服务被停止或重新装载了,则会执行Filter的destroy方法,Filter对象销毁。
Filter工作原理(执行流程)
当客户端发出Web资源的请求时,Web服务器根据应用程序配置文件设置的过滤规则进行检查,若客户请求满足过滤规则,则对客户请求/响应进行拦截,对请求头和请求数据进行检查或改动,并依次通过过滤器链,最后把请求/响应交给请求的Web资源处理。
请求信息在过滤器链中可以被修改,也可以根据条件让请求不发往资源处理器,并直接向客户机发回一个响应。当资源处理器完成了对资源的处理后,响应信息将逐级逆向返回。同样在这个过程中,用户可以修改响应信息,从而完成一定的任务。
过滤链的好处是,执行过程中任何时候都可以打断,只要不执行chain.doFilter()就不会再执行后面的过滤器和请求的内容。
针对多个过滤器来说,例如,EncodingFilter负责设置编码,SecurityFilter负责控制权限,服务器会按照web.xml中过滤器定义的先后循序组装成一条链,然后一次执行其中的doFilter()方法,在实际使用时,就要特别注意过滤链的执行顺序问题,像EncodingFilter就一定要放在所有Filter之前,这样才能确保在使用请求中的数据前设置正确的编码。
总结:
对于filter的应用相信大家已经明白了,它主要的作用就是用户在访问某个目标资源之前,对访问的请求和响应进行拦截,做一些处理,然后再调用目标程序,这样做的好处是可以对一些公共的操作进行抽象,就拿设置字符集来说,如果不使用这种方式,我们每个页面都要写设置字符集的语句。不但麻烦而且维护困难,但是如果使用filter的话,只需要添加一个类,在xml中配置一下,如果不想使用了,将配置文件中的内容去除即可。
其实这就是一种AOP(Aspect OrientedProgramming),面向切面编程。它的主要的意图是:将日志记录,性能统计,安全控制,事务处理,异常处理等代码从业务逻辑代码中划分出来,通过对这些行为的分离,我们希望可以将它们独立到非指导业务逻辑的方法中,进而改变这些行为的时候不影响业务逻辑的代码。
对于设置字符集来说,它并非是业务逻辑的内容,对于这些内容的处理我们就可以提取出来,使用filter进行整体设置,这种方式相当于对类中的内容做进一步的抽象,使我们的系统更加灵活,更加能应对变化!
解疑:
由于上篇博客介绍的动态代理,就是一种符合AOP的一种体现,现在我们又说Filter也符合AOP,那么大家一定会有一个疑问,动态代理和Filter处理问题的区别在哪里呢?First既然都符合AOP思想,那么一定都可以进行统一处理(其实核心就是做进一步抽象)。那么区别呢?
从表现形式上来说,两者确实很相似,同样可以在你写的jsp、servlet代码的前后加入其它的动作,但是两者是有本质区别的。
1、 filter基于回调函数,我们需要实现的filter接口中doFilter方法就是回调函数,而动态代理则基于java本身的反射机制,如果对这种形式不了解,可以去看看动态代理实现过程,这是aop的基础。这是两者最本质的区别。
2、 filter是依赖于servlet容器的,即只能在servlet容器中执行,很显然没有servlet容器就无法来回调doFilter方法。而动态代理与servlet容器无关。
在DRP项目中,多次提到了Filter,它解决了字符集的统一设置以及统一控制简单WebCache,从中我们可以体会到,它给我们带来的好处不仅仅是减少代码量这么简单,它的出现避免了我们每个页面重复的编写相同的代码,减少了我们的工作量,而且给维护带来了极大的便利,那么它是如何实现统一管理的呢?既然它能统一管理某些重复的操作,那么它和AOP有什么关系呢?
Filter简介
ServletAPI中提供了一个Filter接口,开发web应用时,如果编写的Java类实现了这个接口,则把这个java类称之为过滤器Filter。
通过Filter技术,开发人员可以实现用户在访问某个目标资源之前,对访问的请求和响应进行拦截。简单说,就是可以实现web容器对某资源的访问前截获进行相关的处理,还可以在某资源向web容器返回响应前进行截获进行处理。
下图是filter调用关系的UML图:
一个filter必须实现javax.servlet.Filter。
三个方法
1. voidsetFilterConfig(FilterConfig config) //设置filter 的配置对象;
2. FilterConfiggetFilterConfig() //返回filter的配置对象;
3. voiddoFilter(ServletRequest req,ServletResponse res,FilterChain chain) //执行filter的工作
Filter实现拦截的原理
Filter接口中有一个doFilter方法,当开发人员编写好Filter类实现doFilter方法,并配置对哪个web资源进行拦截后,WEB服务器每次在调用web资源的service方法之前(服务器内部对资源的访问机制决定的),都会先调用一下filter的doFilter方法。
应用举例:
批量设置请求编码
xml配置代码
如上的代码完成的功能为,无论进入那个页面,都要先执行EncodingFilter类的dofilter方法设置字符集
其中,doFilter()方法类似于Servlet接口的service()方法。当客户端请求目标资源的时候,容器就会调用与这个目标资源相关联的过滤器的doFilter()方法。
参数 request, response 为web 容器或 Filter 链的上一个 Filter 传递过来的请求和相应对象;参数 chain 代表当前 Filter 链的对象。
对于FilterChain接口,代表当前Filter链的对象。由容器实现,容器将其实例作为参数传入过滤器对象的doFilter()方法中。
过滤器对象使用FilterChain对象调用过滤器链中的下一个过滤器,或者目标Servlet 程序去处理,也可以直接向客户端返回响应信息,或者利用RequestDispatcher的forward()和include()方法,以及HttpServletResponse的sendRedirect()方法将请求转向到其他资源。
这个方法的请求和响应参数的类型是 ServletRequest和ServletResponse,也就是说,过滤器的使用并不依赖于具体的协议。
Filter生命周期
和Servlet一样,Filter的创建和销毁也是由WEB服务器负责。
与Servlet区别的是
1>在应用启动的时候就进行装载Filter类而servlet是在请求时才创建(但filter与Servlet的load-on-startup配置效果相同)。
2>容器创建好Filter对象实例后,调用init()方法。接着被Web容器保存进应用级的集合容器中去了等待着,用户访问资源。
3>当用户访问的资源正好被Filter的url-pattern拦截时,容器会取出Filter类调用doFilter方法,下次或多次访问被拦截的资源时,Web容器会直接取出指定Filter对象实例调用doFilter方法(Filter对象常驻留Web容器了)。
4>当应用服务被停止或重新装载了,则会执行Filter的destroy方法,Filter对象销毁。
Filter工作原理(执行流程)
当客户端发出Web资源的请求时,Web服务器根据应用程序配置文件设置的过滤规则进行检查,若客户请求满足过滤规则,则对客户请求/响应进行拦截,对请求头和请求数据进行检查或改动,并依次通过过滤器链,最后把请求/响应交给请求的Web资源处理。
请求信息在过滤器链中可以被修改,也可以根据条件让请求不发往资源处理器,并直接向客户机发回一个响应。当资源处理器完成了对资源的处理后,响应信息将逐级逆向返回。同样在这个过程中,用户可以修改响应信息,从而完成一定的任务。
过滤链的好处是,执行过程中任何时候都可以打断,只要不执行chain.doFilter()就不会再执行后面的过滤器和请求的内容。
针对多个过滤器来说,例如,EncodingFilter负责设置编码,SecurityFilter负责控制权限,服务器会按照web.xml中过滤器定义的先后循序组装成一条链,然后一次执行其中的doFilter()方法,在实际使用时,就要特别注意过滤链的执行顺序问题,像EncodingFilter就一定要放在所有Filter之前,这样才能确保在使用请求中的数据前设置正确的编码。
总结:
对于filter的应用相信大家已经明白了,它主要的作用就是用户在访问某个目标资源之前,对访问的请求和响应进行拦截,做一些处理,然后再调用目标程序,这样做的好处是可以对一些公共的操作进行抽象,就拿设置字符集来说,如果不使用这种方式,我们每个页面都要写设置字符集的语句。不但麻烦而且维护困难,但是如果使用filter的话,只需要添加一个类,在xml中配置一下,如果不想使用了,将配置文件中的内容去除即可。
其实这就是一种AOP(Aspect OrientedProgramming),面向切面编程。它的主要的意图是:将日志记录,性能统计,安全控制,事务处理,异常处理等代码从业务逻辑代码中划分出来,通过对这些行为的分离,我们希望可以将它们独立到非指导业务逻辑的方法中,进而改变这些行为的时候不影响业务逻辑的代码。
对于设置字符集来说,它并非是业务逻辑的内容,对于这些内容的处理我们就可以提取出来,使用filter进行整体设置,这种方式相当于对类中的内容做进一步的抽象,使我们的系统更加灵活,更加能应对变化!
解疑:
由于上篇博客介绍的动态代理,就是一种符合AOP的一种体现,现在我们又说Filter也符合AOP,那么大家一定会有一个疑问,动态代理和Filter处理问题的区别在哪里呢?First既然都符合AOP思想,那么一定都可以进行统一处理(其实核心就是做进一步抽象)。那么区别呢?
从表现形式上来说,两者确实很相似,同样可以在你写的jsp、servlet代码的前后加入其它的动作,但是两者是有本质区别的。
1、 filter基于回调函数,我们需要实现的filter接口中doFilter方法就是回调函数,而动态代理则基于java本身的反射机制,如果对这种形式不了解,可以去看看动态代理实现过程,这是aop的基础。这是两者最本质的区别。
2、 filter是依赖于servlet容器的,即只能在servlet容器中执行,很显然没有servlet容器就无法来回调doFilter方法。而动态代理与servlet容器无关。