滴滴面经分享:那个让我差点翻车的Spring面试题!

那个让我差点翻车的Spring面试题:拦截器和过滤器到底啥区别?🕵️♂️

朋友们,今天我想分享一个让我在面试中差点翻车的经历------说说Spring里的拦截器(Interceptor)和过滤器(Filter)有什么区别。

说实话,当时面试官问我的时候,我内心OS是:这不都差不多吗?结果支支吾吾半天没说明白,场面一度十分尴尬😅

从翻车到真香的心路历程

初识:我以为它们只是名字不同

刚开始学Spring的时候,我真的以为拦截器和过滤器是同一个东西的不同叫法。就像番茄和西红柿,土豆和马铃薯,本质上没啥区别嘛!

但后来在实际项目中踩了几个坑才发现,「它们根本不是一回事」

醒悟:原来差别这么大!

让我用一个生活化的例子来解释:

想象一下你去银行办业务:

  • 「过滤器」就像银行的「大门保安」 - 所有进出的人都要经过他检查(包括来存钱的、来取款的、甚至走错门的)
  • 「拦截器」就像银行的「柜台经理」 - 只有真正来办业务的人才会遇到他,而且他只在具体业务流程中介入

是不是突然有点感觉了?别急,咱们深入聊聊。

技术层面的深度剖析

过滤器(Filter):尽忠职守的门卫

过滤器是Servlet规范中的概念,它不依赖任何框架。也就是说,即使你不用Spring,只用最基础的Servlet,也能使用过滤器。

java 复制代码
// 过滤器示例:记录请求日志
@WebFilter("/*")
public class LogFilter implements Filter {
    
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, 
                       FilterChain chain) throws IOException, ServletException {
        
        long startTime = System.currentTimeMillis();
        System.out.println("过滤器:请求开始 - " + ((HttpServletRequest) request).getRequestURL());
        
        // 必须调用doFilter,否则请求就卡在这了
        chain.doFilter(request, response);
        
        long endTime = System.currentTimeMillis();
        System.out.println("过滤器:请求结束,耗时:" + (endTime - startTime) + "ms");
    }
}

「过滤器的特点」

  • 工作在Servlet层面,是所有请求的"第一道防线"
  • 可以获取原始的ServletRequest和ServletResponse
  • 对所有请求都有效,包括静态资源

拦截器(Interceptor):业务流程的监督员

拦截器是Spring MVC框架的一部分,它更懂Spring的"语言"。

java 复制代码
// 拦截器示例:权限验证
@Component
public class AuthInterceptor implements HandlerInterceptor {
    
    @Override
    public boolean preHandle(HttpServletRequest request, 
                           HttpServletResponse response, Object handler) throws Exception {
        
        String token = request.getHeader("Authorization");
        if (!isValidToken(token)) {
            response.sendError(401, "Token无效");
            return false; // 中断请求
        }
        System.out.println("拦截器:权限验证通过");
        return true; // 放行
    }
    
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, 
                         Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("拦截器:Controller执行完毕");
    }
    
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, 
                              Object handler, Exception ex) throws Exception {
        System.out.println("拦截器:请求完全结束");
    }
    
    private boolean isValidToken(String token) {
        // 实际的token验证逻辑
        return "valid-token".equals(token);
    }
}

// 配置拦截器
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new AuthInterceptor())
                .addPathPatterns("/api/**") // 只拦截api路径
                .excludePathPatterns("/api/public/**"); // 排除公开接口
    }
}

「拦截器的特点」

  • 可以精确控制拦截哪些路径
  • 能获取到Spring的Handler信息
  • 可以使用Spring的依赖注入

核心区别:一张图看懂

特性 过滤器(Filter) ❌ 拦截器(Interceptor) ✅
依赖框架 Servlet规范 Spring MVC
获取Spring Bean 不行 可以
执行时机 最早 在DispatcherServlet之后
路径匹配 相对简单 更灵活精确
访问Handler信息 不能 可以

那个让我豁然开朗的"啊哈"时刻

最让我震惊的发现是:「它们的执行顺序完全不同!」

一个请求的生命周期是这样的:

  1. ✅ 先经过过滤器
  2. ✅ 到达Spring的DispatcherServlet
  3. ✅ 再经过拦截器
  4. ✅ 最后才到我们的Controller

也就是说,过滤器是"外援",拦截器是"内部员工"。这下你明白为什么拦截器能享受Spring的各种福利(比如依赖注入),而过滤器不行了吧?

实际开发中怎么选?

经过这么多项目实践,我总结了一个简单原则:

  • 需要**「通用处理」(比如日志、编码转换):用「过滤器」**
  • 需要**「业务相关」处理(比如权限、参数校验):用「拦截器」**

举个栗子🌰:

  • 记录所有请求的访问日志 → 过滤器
  • 检查用户是否有权限访问某个API → 拦截器

写在最后

现在回想起来,那次面试翻车其实是件好事。正因为那次尴尬,我才真正搞懂了这个知识点,后来在团队里还成了这方面的"专家"。

所以说,朋友们,遇到不懂的问题不可怕,可怕的是不懂装懂。坦诚面对自己的知识盲区,然后狠狠地把它们补上,这才是我们程序员的成长之道啊!

「互动时间」:你在面试中遇到过哪些让你印象深刻的问题?欢迎在评论区分享你的故事~说不定下次我就写你提到的那个话题!😉


PS:如果这篇文章帮到了你,记得点赞收藏哦~下次见!

相关推荐
WoodWall5 小时前
WebServer 02 Reactor模式
c++·后端
再吃一根胡萝卜5 小时前
项目结构对比:Flask vs Django
后端
间彧5 小时前
LongAdder和AtomicLong的区别与使用场景选择
后端
间彧5 小时前
LongAdder支持高并发,为什么还要使用AtomicLong,直接使用LongAdder不就行了?(实则不然)
后端
WoodWall5 小时前
WebServer 00 重要前置知识
c++·后端
LCG元5 小时前
Docker容器化实战:将你的SpringBoot应用一键打包部署,告别环境不一致的烦恼!#第一部分
后端·docker
天南星5 小时前
23种设计模式-深度讲解-7. 装饰器模式 (Decorator)
后端·设计模式
初级程序员Kyle5 小时前
Java复习日记 - 第一天:重拾Java基础
后端
oak隔壁找我5 小时前
SpringBoot 开发必备基础工具类实现(纯JWT认证,无SpringSecurity)
java·后端