过滤器跟拦截器的区别
过滤器跟拦截器的区别
1、过滤器(Filter)
过滤器的配置比较简单,直接实现 Filter 接口即可,也可以通过 @WebFilter 注解实现对特定URL 拦截, 看到Filter 接口中定义的三个方法。
1、init(); 该方法在容器启动初始化过滤器时被调用,它在Filter 的整个生命周期只会被调用一次。
2、doFilter(); 容器中的每一次请求都会调用该方法,FilterChain 用来调用下一个过滤器 Filter。
3、destroy(); 当容器销毁 过滤器实例时调用该方法,一般在方法中销毁或关闭资源,在过滤器 Filter 的整个生命周期也只会被调用一次。
@Component
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("Filter 前置");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("Filter 处理中");
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
public void destroy() {
System.out.println("Filter 后置");
}
}
2、拦截器(Interceptor)
拦截器时链式调用,一个应用可以同时存在多个拦截器Interceptor,一个请求也可以触发多个拦截器,顺序依调用顺序依次进行。
1、preHandle(); 这个方法将在请求处理之前进行调用。 如果该方法返回值为false,将视为请求结束。
2、postHandle(); 只有在preHandle() 方法返回值为true时才会执行。会在Controller 方法请求后调用,DispatcherServlet 返回渲染视图之前被调用。
3、afterCompletion(); 在preHandle() 方法返回值为true 才会执行,在整个请求结束后, DispatcherServlet 返回渲染视图之后被调用。
@Component
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("Interceptor 前置");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("Interceptor 处理中");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("Interceptor 后置");
}
}
两者都体现了AOP(面向切面编程)的编程思想。
3、两者不同之处
-
实现原理不同
过滤器 基于函数回调。
拦截器 基于java的反射机制(动态代理)。
-
使用范围不同
过滤器: 实现 javax.servlet.Filter 接口,而这个接口实在Servlet 规范中定义的, 依赖于Tomcat 服务器。只能在 web 程序中使用。
拦截器:spring组件,由spring管理,并不依赖于Tomcat等容器,可以单独使用。
-
触发时机不同
过滤器(Filter):进入容器之后,在进入servlet 之前进行预处理,请求结束时在servlet 出完之后。
拦截器(Interceptor):进入servlet 后,在进入controller 之前进行预处理。
-
拦截的请求范围不同
-
注入bean情况不同
过滤器:对于服务可正常使用
拦截器:加载的时间点在springcontext之前,Bean又是由spring进行管理。所以我们如果由需要在拦截器中使用注入的服务必须手动将Interceptor 进行注入。
@Configuration public class MyMvcConfig implements WebMvcConfigurer { @Bean public MyInterceptor getMyInterceptor(){ System.out.println("注入了MyInterceptor"); return new MyInterceptor(); } @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(getMyInterceptor()).addPathPatterns("/**"); } }
-
控制执行顺序不同