过滤器和拦截器的区别是啥?执行顺序是啥?以及实现原理的区别
过滤器(Filter)和拦截器(Interceptor)在 Java Web 开发里是常用的组件,二者都能对请求进行预处理和后处理。
过滤器(Filter)
定义:过滤器是 Servlet 规范的一部分,属于 Servlet 容器提供的功能。它能够对所有进入 Servlet 容器的请求进行过滤,也能对响应进行处理。过滤器在请求到达 Servlet 之前或响应返回客户端之前执行特定操作。
作用
1、请求预处理:可以对请求进行字符编码设置、请求参数过滤、请求头修改等操作,确保请求数据的正确性和安全性。
2、响应后处理:对响应进行压缩、加密等处理,优化响应内容。
3、权限控制:在请求进入 Servlet 之前进行权限验证,阻止未授权的请求访问资源。
拦截器(Interceptor)
定义::拦截器通常是 Spring 框架(如 Spring MVC)提供的功能,用于对 Spring MVC 的请求进行拦截和处理。它可以在请求处理的不同阶段执行特定的逻辑。
作用
1、请求预处理:在请求进入 Controller 方法之前进行权限验证、日志记录、参数校验等操作。
2、请求后处理:在 Controller 方法执行完毕后,对 ModelAndView 进行修改,添加一些通用的数据到视图中。
3、完成处理:在视图渲染完成后,进行资源清理、日志记录等操作。
区别
1、 所有规范和应用范围
过滤器:过滤器是 Servlet 规范的一部分,属于 Servlet 容器提供的功能。它可以对所有进入 Servlet 容器的请求进行过滤,不仅可以用于 Web 应用,还可以在任何基于 Servlet 的应用中使用。
拦截器:拦截器通常是 Spring 框架(如 Spring MVC)提供的功能,它只能在 Spring 框架的应用中使用,主要用于对 Spring MVC 的请求进行拦截和处理。
2、实现接口不同
过滤器:需要实现javax.servlet.Filter接口,该接口定义了init、doFilter和destroy三个方法。
拦截器:在 Spring MVC 中,需要实现org.springframework.web.servlet.HandlerInterceptor接口,该接口定义了preHandle、postHandle和afterCompletion三个方法。
3、粒度不同
过滤器:粒度较粗,它可以对所有请求进行过滤,不管请求是否会被 Spring MVC 处理。
拦截器:粒度较细,它只能对 Spring MVC 的请求进行拦截,即只有当请求进入 Spring MVC 的处理流程时才会起作用。
4、对请求对象的修改能力
过滤器:可以对ServletRequest和ServletResponse进行修改,例如可以对请求的字符编码进行设置。
拦截器:可以对HandlerMethod进行操作,例如可以获取方法的注解信息,但对请求和响应对象的修改能力相对较弱。
执行顺序
在一个同时使用了过滤器和拦截器的 Web 应用中,它们的执行顺序
过滤器的doFilter方法开始执行:当请求进入 Servlet 容器时,首先会经过过滤器的doFilter方法,在该方法中可以进行一些全局的预处理操作,如字符编码设置、请求参数过滤等。
拦截器的preHandle方法执行:如果请求被 Spring MVC 处理,那么在进入具体的 Controller 方法之前,会先执行拦截器的preHandle方法,该方法可以用于权限验证、日志记录等操作。如果preHandle方法返回false,则请求将被拦截,不再继续执行后续的拦截器和 Controller 方法。
Controller 方法执行:如果拦截器的preHandle方法返回true,则请求会进入具体的 Controller 方法进行处理。
拦截器的postHandle方法执行:在 Controller 方法执行完毕后,会执行拦截器的postHandle方法,该方法可以对 ModelAndView 进行修改,如添加一些通用的数据到视图中。
拦截器的afterCompletion方法执行:在视图渲染完成后,会执行拦截器的afterCompletion方法,该方法可以用于资源清理、日志记录等操作。
过滤器的doFilter方法后续代码执行:最后,会继续执行过滤器doFilter方法中剩余的代码,完成请求的后处理操作。
实现原理的区别
过滤器的实现原理:过滤器是基于 Servlet 容器的FilterChain机制实现的。当请求进入 Servlet 容器时,容器会根据过滤器的配置顺序依次调用过滤器的doFilter方法。在doFilter方法中,通过调用FilterChain的doFilter方法将请求传递给下一个过滤器或 Servlet。如果没有下一个过滤器,则请求会到达目标 Servlet 进行处理。
import javax.servlet.*;
import java.io.IOException;
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// 初始化操作
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// 预处理操作
System.out.println("Before filter");
chain.doFilter(request, response);
// 后处理操作
System.out.println("After filter");
}
@Override
public void destroy() {
// 销毁操作
}
}
拦截器的实现原理:拦截器是基于 Spring MVC 的HandlerExecutionChain机制实现的。当请求进入 Spring MVC 的处理流程时,会根据请求的 URL 匹配到相应的HandlerMapping,并获取对应的HandlerExecutionChain对象。HandlerExecutionChain对象中包含了处理该请求的Handler和一系列的拦截器。在请求处理过程中,会依次调用拦截器的preHandle、postHandle和afterCompletion方法。
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
// 预处理操作
System.out.println("Before interceptor");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
// 后处理操作
System.out.println("After controller");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
// 完成处理操作
System.out.println("After view");
}
}