过滤器(Filter)和拦截器(Interceptor)都是基于AOP(AspectOrientedProgramming,面向切面编程)的思想实现的,两个“工具”,用来解决项目中某一类问题,但是两者有着明显的差距,我们一起来看看吧。过滤器和拦截器的实现首先我们来看一下两者在SpringBoot项目中的具体实现,这对理解两者的区别会有很大的帮助。1、实现过滤器过滤器可以使用Servlet3.0提供的@WebFilter注解配置过滤URL规则,然后实现Filter接口,重写接口中的doFilter方法。具体实现代码如下:importorg.springframework.stereotype.Component;importjavax.servlet.*;importjavax.servlet.annotation.WebFilter;importjava.io.IOException;@Component@WebFilter(urlPatterns="/*")publicclassTestFilterimplementsFilter{@Overridepublicvoidinit(FilterConfigfilterConfig)throwsServletException{System.out.println("Filter:Executetheinitmethod.");}@OverridepublicvoiddoFilter(ServletRequestservletRequest,ServletResponseservletResponse,FilterChainfilterChain)throwsIOException,ServletException("filterFilter:开始执行doFilter方法。");//请求释放filterChain.doFilter(servletRequest,servletResponse);System.out.println("Filter:doFilter方法结束执行。");}@Overridepublicvoiddestroy(){System.out.println("Filter:执行destroy方法。");}}其中:voidinit(FilterConfigfilterConfig):容器启动时会调用(初始化Filter),整个程序运行期间只会调用一次。用于实现Filter对象的初始化voiddoFilter(ServletRequestrequest,ServletResponseresponse,FilterChainchain):具体的过滤函数实现代码,通过它对请求进行过滤,FilterChain参数用于调用下一个过滤器或执行下一个流程voiddestroy():用于在Filter销毁前完成相关资源的回收2.实现拦截器拦截器的实现分为两步,第一步是创建一个common整数erceptor,实现HandlerInterceptor接口,重写接口中的相关方法;第二步,将上一步创建的拦截器添加到SpringBoot配置文件中。接下来首先创建一个普通的拦截器,实现HandlerInterceptor接口并重写preHandle/postHandle/afterCompletion方法,具体实现代码如下:importorg.springframework.web.servlet.ModelAndView;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;@ComponentpublicclassTestInterceptorimplementsHandlerInterceptor{@OverridepublicbooleanpreHandle(HttpServletRequest请求,HttpServletResponse响应,对象处理器)throwsException{System.out.println("拦截器:执行preHandle方法。");返回真;}@OverridepublicvoidpostHandle(HttpServletRequestrequest,HttpServletResponseresponse,Objecthandler,ModelAndViewmodelAndView)throwsException{System.out.println("拦截器:执行postHandle方法。");}@OverridepublicvoidafterCompletion(HttpServletRequestrequest,HttpServletResponseresponse,Objecthandler,Exceptionex)throwsException{System.out.println("Interceptor:executeafterCompletionmethod.");}}其中:booleanprequestHandle(HttpServletRerequest,HttpServletResponseresponse,Objecthandle):在request方法执行之前被调用,也就是在目标方法调用之前被调用。比如我们在操作数据之前需要验证用户的登录信息,可以是在该方法中实现,如果验证成功则返回true,继续执行数据操作业务;否则返回false,不执行后续数据操作业务。ModelAndViewmodelAndView):在调用request方法之后执行,但是会在DispatcherServlet渲染视图之前执行。voidafterCompletion(HttpServletRequestrequest,HttpServletResponseresponse,Objecthandle,Exceptionex):会在整个请求结束后执行,也就是DispatcherServlet渲染对应视图后执行。最后,我们将上面的拦截器注入到项目配置文件中,并设置相应的拦截规则。具体实现代码如下:importorg.springframework.beans.factory.annotation.Autowired;导入org.springframework.context.annotation.Configuration;导入org.springframework.web.servlet.config.annotation.InterceptorRegistry;导入org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@ConfigurationpublicclassAppConfigimplementsWebMvcConfigurer{//注入拦截器@AutowiredprivateTestInterceptortestInterceptor;OverridepublicvoidaddInterceptors(InterceptorRegistryregistry){registry.addInterceptor(testInterceptor)//添加Interceptor.addPathPatterns("/*");//拦截所有地址}}了解了两者的使用之后,我们再来看看两者的区别。FilterVSInterceptor过滤器和拦截器的区别主要体现在以下五点:来源不同;不同的触发时机;不同的实现;不同的支持项目类型;以及不同的使用场景。接下来,让我们一一来看。1.背景不同过滤器来自Servlet,而拦截器来自Spring框架。从上面的代码我们也可以看出,过滤器在实现的时候会导入Servlet相关的包,如下图:而拦截器在执行的时候,会导入Spring相关的包,如下图图:2.不同请求在触发时机的执行顺序为:请求进入容器>进入过滤器>进入Servlet>进入拦截器>执行控制器(Controller),如下图:所以执行过滤器和拦截器的时机也不同。首先会执行过滤器,然后执行拦截器,最后进入实际要调用的方法。3.不同过滤器的实现是基于方法回调的。我们在上面实现过滤器的时候会发现,当我们要执行下一个过滤器或者下一个流程时,需要调用FilterChain对象的doFilter方法进行回调执行。如下图所示:可以看出,过滤器的实现是基于方法回调的。拦截器是基于动态代理(底层是反射)实现的,其实现如下图:代理调用效果如下图:4.支持的item类型不同。过滤器是在Servlet规范中定义的,所以过滤器拦截器依赖于Servlet容器,只能在Web项目中使用;而拦截器是Spring中的一个组件,所以拦截器既可以用在Web项目中,也可以用在Application或Swing程序中。5、使用的场景不同。因为拦截器更贴近业务系统,所以拦截器在项目中主要用于实现业务判断,比如:登录判断,权限判断,日志记录等业务。过滤器通常用于实现通用的功能过滤,如敏感词过滤、字符集编码设置、响应数据压缩等。下载本项目源码https://gitee.com/mydb/springboot-examples/tree/master/spring-boot-filter总结过滤器和拦截器是基于AOP的思想实现的,统一处理一个功能,但两者有5点不同:背景不同、触发时机不同、实现方式不同、支持的项目类型不同、使用场景不同。过滤器通常用于全局过滤,而拦截器用于实现某些业务的拦截。参考&感谢blog.csdn.net/wo541075754/article/details/111661213zhuanlan.zhihu.com/p/340397290
