过滤器和拦截器在我们的开发过程中,使用到的是相当多的。下面就从实现方式,依赖关系,执行顺序,作用范围,注入Bean几个方面来说说它们的不同。
过滤器和拦截器的概念
过滤器(Filter)是拦截请求和响应的web组件。Web项目中通常用它来处理中文参数乱码问题。
拦截器(Interceptor)是一种用于在请求进入Controller之前对其进行预处理,或者在请求离开Controller之后对其进行后处理的组件。拦截器可以用来记录请求的日志信息,处理异常,检查用户的登录状态,等等。
实现方式
过滤器(Filter)的实现方式通常是实现 javax.servlet.Filter 接口,并重写 doFilter 方法。下面是一个简单的例子:
import javax.servlet.*;
import java.io.IOException;
public class MyFilter implements Filter {
private ServletContext servletContext;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
this.servletContext = filterConfig.getServletContext();
}
@Override
public void destroy() {}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
// 在这里可以做一些预处理,例如读取请求参数,修改请求参数,等等
// 调用下一个过滤器或Controller
chain.doFilter(request, response);
// 在这里可以做一些后处理,例如写入响应体,等等
}
}
在这个例子中,我们实现了 javax.servlet.Filter 接口,并实现了 doFilter 方法。在 doFilter 方法中,我们可以做一些预处理和后处理,例如读取请求参数,写入响应体,等等。注意,我们需要调用 chain.proceed() 方法来继续执行后续的处理步骤。
拦截器(Interceptor)的实现方式通常是实现HandlerInterceptor接口,下面是一个简单的例子:
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("MyInterceptor: Pre-handle request");
// 如果返回false,请求将被中断,后续的Controller不会执行
// 这里返回true表示允许请求继续执行
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
// 后处理阶段,在请求处理之后,视图渲染之前执行
System.out.println("MyInterceptor: Post-handle request");
// 可以在此处修改模型数据或视图
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
// 整个请求完成后执行,主要用于资源清理、记录请求耗时等工作
System.out.println("MyInterceptor: After completion");
// 如果在preHandle阶段抛出了异常,ex参数会携带异常信息
}
}
依赖关系
过滤器和拦截器之间存在一种依赖关系。一般来说,过滤器会在拦截器之前执行,也就是说,请求先经过过滤器的处理,然后再经过拦截器的处理。
这种依赖关系主要是因为过滤器和拦截器的功能不同造成的。过滤器主要用于在请求进入容器之前对其进行预处理,例如读取请求参数,修改请求参数,等等。而拦截器主要用于在请求进入Controller之前对其进行预处理,例如记录日志信息,处理异常,检查用户登录状态,等等。
另外,过滤器和拦截器的执行顺序也是可以配置的。在Spring MVC中,可以通过在web.xml文件中配置过滤器的执行顺序,来改变过滤器的执行顺序。同样,也可以通过在application-context.xml文件中配置拦截器的执行顺序,来改变拦截器的执行顺序。
执行顺序
过滤器和拦截器的执行顺序是可以配置的。在Spring MVC中,可以通过在web.xml文件中配置过滤器的执行顺序,来改变过滤器的执行顺序。同样,也可以通过在application-context.xml文件中配置拦截器的执行顺序,来改变拦截器的执行顺序。
在Spring MVC中,默认情况下,过滤器的执行顺序是按照它们在web.xml文件中配置的顺序执行的。例如,如果有两个过滤器A和B,A在B前面,那么A将会先执行,然后才是B。
同样,拦截器的执行顺序也是按照它们在application-context.xml文件中配置的顺序执行的。例如,如果有两个拦截器C和D,C在D前面,那么C将会先执行,然后才是D。
当然,这只是一个默认的执行顺序,实际上,我们完全可以根据我们的需求来调整过滤器和拦截器的执行顺序。
作用范围
过滤器 实现的是 javax.servlet.Filter
接口,而这个接口是在Servlet
规范中定义的,也就是说过滤器Filter
的使用要依赖于Tomcat
等容器,导致它只能在web
程序中使用。
拦截器(Interceptor
) 它是一个Spring
组件,并由Spring
容器管理,并不依赖Tomcat
等容器,是可以单独使用的。
一般来说,过滤器的作用范围更广,可以覆盖整个请求处理过程,包括请求的输入和输出。而拦截器的作用范围相对较小,只能覆盖请求的输入,即请求的预处理。
具体来说,过滤器可以用来读取和修改请求的参数,例如读取请求的URL参数,读取请求的POST参数,修改请求的POST参数,等等。过滤器还可以用来修改请求的响应,例如修改响应的编码,修改响应的头部,等等。
相比之下,拦截器的作用范围要小得多。拦截器主要用于在请求进入Controller之前对其进行预处理,例如记录日志信息,处理异常,检查用户登录状态,等等。拦截器不能修改请求的输入,也不能修改请求的输出。
注入Bean
如果我们需要在过滤器和拦截器中使用到业务逻辑,通常会注入一些Service来帮助我们完成这些任务。然而,这两种方式的注入方式有所不同。
过滤器中注入service
,一切正常!
拦截器中注入service
,注入的service
是Null,原因:
这是因为加载顺序导致的问题,拦截器
加载的时间点在springcontext
之前,而Bean
又是由spring
进行管理。解决方案也很简单,我们在注册拦截器之前,先将Interceptor
手动进行注入。