一、过滤器(Filter)
过滤器的配置比较简单,直接实现Filter
接口即可,也可以通过@WebFilter
注解实现对特定URL
的拦截,Filter
接口中定义了三个方法:
- init(): 该方法在容器启动初始化过滤器时被调用,它在过滤器的整个生命周期只会被调用一次;
- doFilter(): 容器中的每一次请求都会调用该方法,其中的FilterChain用来调用下一个过滤器;
- destory(): 当容器销毁过滤器实例时调用该方法,在过滤器的整个生命周期也只会被调用一次。
@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 后置");
}
}
二、拦截器(Interceptor)
拦截器它是链式调用,一个应用中可以同时存在多个拦截器,一个请求也可以触发多个拦截器,而每个拦截器的调用会依据它的声明顺序依次执行。
实现HandlerInterceptor
接口,该接口定义了三个方法:
- preHandle(): 这个方法将在请求处理之前调用,如果该方法返回
false
,将视为当前请求结束; - postHandle(): 在
Controller
中的方法调用之后,DispatcherServlet
返回渲染视图之前被调用; - afterComplete(): 在整个请求结束之后,
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 后置");
}
}
三、二者区别
过滤器和拦截器均体现了SpringAOP
的编程思想,二者区别如下:
- 实现原理不同:过滤器基于函数回调,
Filter
接口中需要实现的doFilter()
方法就是回调函数;拦截器则是基于Java反射机制(动态代理)实现。 - 使用范围不同:过滤器依赖于
Servlet
容器,只能在Servlet
容器中执行;拦截器是一个Spring
组件,由Spring
容器管理,并不依赖Servlet
容器。 - 拦截请求范围不同: 过滤器可以对几乎所有的请求起作用;拦截器只对action请求起作用。
- 触发时机不同: 过滤器是在请求进入容器后,在进入
servlet
之前进行预处理,在servlet
处理完以后请求结束;拦截器是在请求进入servlet
后,在进入Controller
之前进行预处理的,Controller
中渲染视图之后请求结束。 - 可否获取Bean: 过滤器不能获取Bean;拦截器可获取IOC容器中的Bean,这点很重要,在拦截器中注入一个service,可以调用业务逻辑。
四、应用场景
回调函数指的是一个通过函数指针调用的函数,也就是被作为参数传递的函数。
Spring MVC中每个控制器(Controller)中可以定义多个请求处理方法,我们把这种请求处理方法简称为Action。