一、前言
一直想着写一篇关于过滤器和拦截器
,记得之前面试,面试官突然问了一个谈谈过滤器和拦截器的区别。
当时脑瓜子嗡嗡的,这个没准备过,咋办,支支吾吾的说了先到过滤器在到拦截器。
直接被说,你连请求来了经历那些都不知道,怎么能行呢?
虽然这个是八股文,但是还是比较有内容的,在项目中会使用到,在鉴权、日志记录等!
从此之后,面试前第一件事,就是把过滤器和拦截器看一遍。
今天好好总结一下,不需要在看别人写的了!
不能为了面试而学习,咱们是为了掌握好他们,咱们今天从概念--->场景--->实战--->面试题。
一步步层层递进,不让大家白白点开,一定是有所收获!
执行顺序总体图:
二、过滤器
1、概念
过滤器是一种在 Java Web 应用中用于处理请求和响应的组件。它可以拦截客户端发起的请求,也可以拦截服务器返回的响应,对它们进行处理或者修改。
过滤器属于Servlet规范的一部分,过滤器是用于执行过滤任务的对象,它可以在请求到达 Servlet 之前或响应发送给客户端之前执行一些额外的逻辑。
2、应用场景
日志记录: 过滤器常用于记录请求和响应的日志,包括请求的路径、参数、处理时间等信息。
身份验证和授权: 过滤器可以用于实现身份验证和授权逻辑,例如检查用户是否已登录,是否具有足够的权限访问某个资源。
防御性编程: 过滤器可以用于对请求进行安全检查,防止潜在的攻击,比如阻止恶意请求、XSS(跨站脚本攻击)等。
性能监控: 过滤器可以用于收集请求的处理时间、资源使用等信息,用于性能监控和优化。
3、核心方法
先说一下过滤器的三个核心方法:init 方法:在过滤器被创建并添加到容器时调用,在过滤器的生命周期中只被调用一次。doFilter 方法:是过滤器的核心方法,用于处理请求和响应。可以进行前置处理、请求转发或链的调用,以及后置处理。(FilterChain.doFilter)destroy 方法:在过滤器被销毁前调用,用于进行资源释放和清理工作。在过滤器的生命周期中只被调用一次。
4、实战
编写自己的过滤器配置类: 会把web开头的请求率先通过我们定义的过滤器,我们可以在里面进行权限的校验、记录日志等。
多个过滤器,需要有执行顺序可以使用Spring注解@Order,也可以使用@WebFilter(urlPatterns="/web/order/"),通过请求去到下一个符合条件的过滤器!
咱们使用的注解,需要在启动类加上扫描,不然过滤器是不会生效的!
@ServletComponentScan。
/**
* @author wangzhenjun
* @date 2023/11/22 15:34
*/
@Slf4j
@WebFilter("/web/*")
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
Filter.super.init(filterConfig);
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
log.info("用户已经认证,继续处理");
log.info("用户有权限,继续处理");
chain.doFilter(request, response);
log.info("处理完成,放行之后");
}
@Override
public void destroy() {
Filter.super.destroy();
}
}
测试访问,经过了过滤器,来到我们的Controller,最后重新会到过滤器内的doFilter方法!
三、拦截器
1、概念
拦截器(Interceptor)是一种在应用程序处理请求和响应的过程中,插入自定义处理逻辑的组件。拦截器是一种常见的设计模式,它允许在核心处理逻辑之前或之后执行额外的操作。
一般出现在Spring MVC中,Spring MVC 中的拦截器实现原理主要基于 Spring 框架的 AOP和 HandlerInterceptor 接口。
2、应用场景
敏感字检测:过滤器可以用于检测请求中的文本内容,包括表单提交、请求参数等,以查找是否包含敏感字。异常处理: 拦截器可以用于捕获和处理在请求处理过程中发生的异常。这使得开发者可以集中处理异常情况,返回合适的错误响应或记录异常信息。日志记录: 拦截器可用于记录请求和响应的日志信息,包括请求参数、响应状态码、执行时间等。国际化和本地化: 拦截器可以用于根据请求的语言或地区设置合适的国际化或本地化信息,以提供多语言支持。
其实过滤器和拦截器很多场景他们两个都能实现。待会我们说一下区别在那里,都能实现一般采用什么方式去实现!
3、核心方法
先说一下拦截器接口的三个核心方法:
preHandle 方法: 在请求被处理之前调用。该方法在整个请求处理过程中是第一个被调用的方法。
如果该方法返回 true,则请求继续进行后续的处理;如果返回 false,则中断请求处理,不会进入控制器方法。
postHandle 方法: 在请求处理后、视图渲染前调用。在这个方法中,可以进行一些后置处理,如对ModelAndView的修改等。
afterCompletion方法: 在整个请求完成后调用,即在视图渲染完毕或在处理过程中发生异常后调用。这个方法在请求完成后,不论请求处理过程中是否发生异常都会被调用。
4、实战
先创建自己的拦截器类:MyInterceptor、
/**
* @author wangzhenjun
* @date 2023/11/23 9:17
*/
@Slf4j
@Component
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
log.info("===>拦截器拦截器拦截器