持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第6天,点击查看活动详情
过滤器(Filter)和拦截器(Interceptor)都是基于 AOP(Aspect Oriented Programming,面向切面编程)思想实现。
过滤器
过滤器使用 Servlet 3.0 提供的 @WebFilter 注解,配置过滤的 URL 规则,然后再实现 Filter 接口,重写接口中的 doFilter 方法,具体实现代码
@Component
public class TestInterceptor implements HandlerInterceptor {
/**
* @Author: Take-off
* @Description: //TODO 在请求方法 执行前 被调用,比如验证登录信息
* @Date: 4:52 PM 2022/10/18
**/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("拦截器:执行 preHandle 方法。");
return true;
}
/**
* @Author: Take-off
* @Description: //TODO 在请求方法之后执行,但会在 DispatcherServlet 进行渲染视图之前被执行
* @Date: 4:53 PM 2022/10/18
**/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("拦截器:执行 postHandle 方法。");
}
/**
* @Author: Take-off
* @Description: //TODO 会在整个请求结束之后再执行
* @Date: 5:00 PM 2022/10/18
**/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("拦截器:执行 afterCompletion 方法。");
}
}
void init(FilterConfig filterConfig):容器启动(初始化 Filter)时会被调用,整个程序运行期只会被调用一次。用于实现 Filter 对象的初始化。
void doFilter(ServletRequest request, ServletResponse response,FilterChain chain):具体的过滤功能实现代码,通过此方法对请求进行过滤处理,其中 FilterChain 参数是用来调用下一个过滤器或执行下一个流程。
void destroy():用于 Filter 销毁前完成相关资源的回收工作。
拦截器
1.创建一个普通的拦截器,实现 HandlerInterceptor 接口,并重写接口方法
@Component
public class TestInterceptor implements HandlerInterceptor {
/**
* @Author: Take-off
* @Description: //TODO 在请求方法 执行前 被调用,比如验证登录信息
* @Date: 4:52 PM 2022/10/18
**/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("拦截器:执行 preHandle 方法。");
return true;
}
/**
* @Author: Take-off
* @Description: //TODO 在请求方法之后执行,但会在 DispatcherServlet 进行渲染视图之前被执行
* @Date: 4:53 PM 2022/10/18
**/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("拦截器:执行 postHandle 方法。");
}
/**
* @Author: Take-off
* @Description: //TODO 会在整个请求结束之后再执行
* @Date: 5:00 PM 2022/10/18
**/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("拦截器:执行 afterCompletion 方法。");
}
}
boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handle):
在请求方法执行前被调用,也就是调用目标方法之前被调用。比如我们在操作数据之前先要验证用户的登录信息,就可以在此方法中实现,如果验证成功则返回 true,继续执行数据操作业务;否则就返回 false,后续操作数据的业务就不会被执行了。
void postHandle(HttpServletRequest request, HttpServletResponse response, Object handle, ModelAndView modelAndView):
调用请求方法之后执行,但它会在 DispatcherServlet 进行渲染视图之前被执行。
void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handle, Exception ex):
会在整个请求结束之后再执行,也就是在 DispatcherServlet 渲染了对应的视图之后再执行。
2,将上一步创建的拦截器加入到 Spring Boot 的配置文件中
@Configuration
public class AppConfig implements WebMvcConfigurer {
@Autowired
private TestInterceptor testInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
//添加拦截器
registry.addInterceptor(testInterceptor)
.addPathPatterns("/*");
}
}
两者区别
1.出身不同
过滤器来自于Servlet,而拦截器来自于 Spring 框架。
2.触发时机不同
请求的执行顺序是:请求进入容器 > 进入过滤器 > 进入 Servlet > 进入拦截器 > 执行控制器
3.实现不同
过滤器是基于方法回调实现的。当我们要执行下一个过滤器或下一个流程时,需要调用 FilterChain 对象的 doFilter 方法进行回调执行
拦截器是基于动态代理(底层是反射)实现的。
4.支持的项目类型不同
过滤器是 Servlet 规范中定义的,所以过滤器要依赖 Servlet 容器,它只能用在 Web 项目中;而拦截器是 Spring 中的一个组件,因此拦截器既可以用在 Web 项目中,同时还可以用在 Application 或 Swing 程序中。
5.使用的场景不同
因为拦截器更接近业务系统,所以拦截器主要用来实现项目中的业务判断,比如:登陆判断、权限判断、日志记录等业务。而过滤器通常是用来实现通用功能过滤的,比如:敏感词过滤、字符集编码设置。