简介
这几天在回顾Spring的AOP时,对过滤器,拦截器,AOP的关系有点好奇,故记录做以备份。在实现一些公共逻辑的时候,很多功能通过过滤器,拦截器,AOP都能实现,但是不同的方式有不同的效率。具体有什么区别,看下文描述。
概念
过滤器
过滤器拦截的是URL
假如客户端要想访问servlet1的时候,先进入服务器软件内核—-进入过滤器Filter1—如果还有符合拦截条件的过滤器就还进入别的过滤器——到达servlet1
如果任何一个过滤器没有放行,那么request就没有传入到servlet里面
过滤器工作流程:客户端发起请求之后,在请求到达服务端之前,有一个东西先把他们拦截下来过滤一下,符合我们条件的放行,不符合条件的不放行,不符合的也可以改造一下再放行.
过滤器可以在客户端发起请求之后,请求到达目标资源之前,先对requset和response做一些预处理。然后把处理之后的request和response放行,最终到达目标资源。
Filter技术也是Servlet规范和的一种,开发模式和步骤和Servlet的开发步骤非常相似。
Filter技术:符合条件允许放行,不符合条件不允许放行,主要是用来对浏览器的请求进行过滤的
Spring中自定义过滤器(Filter)一般只有一个方法,返回值是void,当请求到达web容器时,会探测当前请求地址是否配置有过滤器,有则调用该过滤器的方法(可能会有多个过滤器),然后才调用真实的业务逻辑,至此过滤器任务完成。过滤器并没有定义业务逻辑执行前、后等,仅仅是请求到达就执行。
特别注意:过滤器方法的入参有request,response,FilterChain,其中FilterChain是过滤器链,使用比较简单,而request,response则关联到请求流程,因此可以对请求参数做过滤和修改,同时FilterChain过滤链执行完,并且完成业务流程后,会返回到过滤器,此时也可以对请求的返回数据做处理。
拦截器
拦截器拦截的是URL
拦截器有三个方法,相对于过滤器更加细致,有被拦截逻辑执行前、后等。Spring中拦截器有三个方法:preHandle,postHandle,afterCompletion。分别表示如下
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o)表示被拦截的URL对应的方法执行前的自定义处理
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView)表示此时还未将modelAndView进行渲染,被拦截的URL对应的方法执行后的自定义处理,。
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e)表示此时modelAndView已被渲染,执行拦截器的自定义处理。
AOP(面向切面)
面向切面拦截的是类的元数据(包、类、方法名、参数等)
相对于拦截器更加细致,而且非常灵活,拦截器只能针对URL做拦截,而AOP针对具体的代码,能够实现更加复杂的业务逻辑。具体类型参照其他博客。
另外一种思路来实现应用系统中的公共服务.
1. 比如每个业务调用的权限管理:在用户调用方法之前判断用户是否有权限调用方法
2. 每个方法的调用审计,记录谁调用了什么业务和方法,传入参数以及操作是否成功
3. 对业务方法返回的数据进行缓存,下次调用时候,如果参数不变的话,直接从缓存里面获取数据,从而不再调用应用方法
在没有AOP之前这些应用程序都需要程序员在实现上面代码方法,有了AOP在方法调用前后”织入”一些公共代码.从而提供系统的公共服务.
三者使用场景
三者功能类似,但各有优势,从过滤器—》拦截器—》切面,拦截规则越来越细致,执行顺序依次是过滤器、拦截器、切面。
一般情况下数据被过滤的时机越早对服务的性能影响越小,因此我们在编写相对比较公用的代码时,优先考虑过滤器,然后是拦截器,最后是aop。
比如权限校验,一般情况下,所有的请求都需要做登陆校验,此时就应该使用过滤器在最顶层做校验,拦截器也可以使用;
日志记录,一般日志只会针对部分逻辑做日志记录,而且牵扯到业务逻辑完成前后的日志记录,因此使用过滤器不能细致地划分模块,此时应该考虑拦截器,然而拦截器也是依据URL做规则匹配,因此相对来说不够细致,因此我们会考虑到使用AOP实现,AOP可以针对代码的方法级别做拦截,很适合日志功能。
过滤器
1.对文字进行过滤,比如论坛发帖涉及到敏感词汇问题
2如果页面报出500或者404 会连接指向指定的页面,比如报404时候会指定跳转到一个提示页面.
3.进行权限控制
4.提取公共代码,比如多个servlet代码都是重复的,就可以提取出来放在过滤器里面
5.可以拦截请求,对request和response对象进行预处理。比如对request的方法进行功能增强(比如.getpost请求乱码问题,)
三者区别
拦截的地方
l Filter过滤器:拦截web访问url地址。 这个比拦截器范围广,过滤器是大集合,拦截器是大集合中的小集合。而且任何url是先经过过滤器后才进入拦截器的。
l Interceptor拦截器:拦截url以action结尾或者没有后缀的,没有后缀拦截器会认为是.action结尾。。 如:struts2拦截器、spring拦截器
l Spring AOP拦截器:只能拦截Spring管理Bean的访问(业务层Service),就是说执行某个bean容器中方法时进行拦截,而不是对url。
区别
1. 拦截器与过滤器的区别 :
1. 拦截器是基于java的反射机制的,而过滤器是基于函数回调。
2. 拦截器不依赖与servlet容器,过滤器依赖与servlet容器。
3. 拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用。
4. 拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问。
5. 在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一
6.拦截器可以获取IOC容器中的各个bean,而过滤器就不行,这点很重要,在拦截器里注入一个service,可以调用业务逻辑,这点很重要,拦截器可以获取ioc中的bean, 实现业务逻辑
*
效率
触发时机
1.过滤器和拦截器触发时机不一样:
过滤器是在请求进入容器后,但请求进入servlet之前进行预处理的。请求结束返回也是,是在servlet处理完后,返回给前端之前
总结:过滤器包裹住servlet,servlet包裹住拦截器。
2.过滤器的触发时机是容器后,servlet之前,所以过滤器的doFilter(
ServletRequest request, ServletResponse response, FilterChain chain
)的入参是ServletRequest ,而不是httpservletrequest。因为过滤器是在httpservlet之前。
前后端交互基本逻辑