10-SpringMVC拦截器

1. 什么是拦截器?一个生动的比喻 🎭

想象一下你去电影院看电影的流程:

  1. 检票员检查票(preHandle)- 没有票就不能进去
  2. 你看电影(Controller处理请求)
  3. 散场时工作人员引导(postHandle)- 电影结束后的处理
  4. 你离开影院,清洁工打扫(afterCompletion)- 最后的收尾工作

拦截器就是这个"检票员+工作人员+清洁工"的组合,它在请求处理的不同阶段执行一些操作。

2. 拦截器的三个重要方法 📋

拦截器有三个关键方法,对应三个不同时间点:

public class MyInterceptor implements HandlerInterceptor {
    
    // 方法1:控制器执行前调用 - 像检票员
    public boolean preHandle(HttpServletRequest request,
                            HttpServletResponse response, 
                            Object handler) throws Exception {
        System.out.println("❶ 检票员:正在检查你的票...");
        return true; // true=通过, false=拒绝
    }
    
    // 方法2:控制器执行后调用 - 像散场工作人员
    public void postHandle(HttpServletRequest request,
                         HttpServletResponse response, 
                         Object handler,
                         ModelAndView modelAndView) throws Exception {
        System.out.println("❷ 工作人员:电影结束了,请慢慢离场...");
    }
    
    // 方法3:整个请求完成后调用 - 像清洁工
    public void afterCompletion(HttpServletRequest request,
                              HttpServletResponse response, 
                              Object handler, Exception ex) throws Exception {
        System.out.println("❸ 清洁工:观众已离场,开始打扫卫生...");
    }
}

3. 如何配置拦截器? 🛠️

方式1:XML配置(传统但清晰)

springmvc.xml文件中添加:

<!-- 告诉SpringMVC我们要使用拦截器 -->
<mvc:interceptors>
    <!-- 定义一个拦截器 -->
    <mvc:interceptor>
        <!-- 拦截所有请求 -->
        <mvc:mapping path="/**"/>
        <!-- 指定使用哪个拦截器类 -->
        <bean class="com.example.MyInterceptor"/>
    </mvc:interceptor>
</mvc:interceptors>

方式2:Java配置(现代推荐)

@Configuration
public class WebConfig implements WebMvcConfigurer {
    
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new MyInterceptor())
                .addPathPatterns("/**"); // 拦截所有路径
    }
}

4. 实际应用:登录检查 🔐

让我们看一个最常用的例子:检查用户是否登录

public class LoginInterceptor implements HandlerInterceptor {
    
    @Override
    public boolean preHandle(HttpServletRequest request, 
                           HttpServletResponse response, 
                           Object handler) throws Exception {
        
        // 获取Session中的用户信息
        HttpSession session = request.getSession();
        Object user = session.getAttribute("user");
        
        // 如果用户未登录
        if (user == null) {
            // 重定向到登录页面
            response.sendRedirect(request.getContextPath() + "/login");
            return false; // 中断请求,不让它继续执行
        }
        
        return true; // 用户已登录,放行
    }
}

配置这个登录拦截器:

<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/user/**"/>    <!-- 拦截用户相关路径 -->
        <mvc:mapping path="/admin/**"/>   <!-- 拦截管理相关路径 -->
        <mvc:exclude-mapping path="/login"/> <!-- 不拦截登录页面 -->
        <bean class="com.example.LoginInterceptor"/>
    </mvc:interceptor>
</mvc:interceptors>

5. 多个拦截器的执行顺序 🔢

如果有多个拦截器,它们的执行顺序是这样的:

请求 → 拦截器1.preHandle → 拦截器2.preHandle → Controller
     → 拦截器2.postHandle → 拦截器1.postHandle → 视图渲染
     → 拦截器2.afterCompletion → 拦截器1.afterCompletion → 响应

记忆技巧:

  • preHandle:按配置顺序执行(1→2→3)
  • postHandleafterCompletion:按配置逆序执行(3→2→1)

6. 拦截器 vs 过滤器:有什么区别? 🤔

特性 拦截器 (Interceptor) 过滤器 (Filter)
工作层面 SpringMVC层面 Servlet层面
依赖 依赖Spring框架 只依赖Servlet API
使用场景 业务逻辑处理 通用功能(编码、安全等)
获取Bean 可以获取Spring容器中的Bean 不能直接获取

简单说:过滤器是"大门保安",拦截器是"楼层管理员"。

7. 常见问题及解决方案 ❓

问题1:静态资源也被拦截了

解决方案: 排除静态资源路径

<mvc:interceptor>
    <mvc:mapping path="/**"/>
    <mvc:exclude-mapping path="/css/**"/>   <!-- 排除CSS -->
    <mvc:exclude-mapping path="/js/**"/>    <!-- 排除JS -->
    <mvc:exclude-mapping path="/images/**"/><!-- 排除图片 -->
    <bean class="com.example.MyInterceptor"/>
</mvc:interceptor>

问题2:拦截器不生效

检查清单:

  1. 拦截器配置路径是否正确
  2. 拦截器类是否被Spring管理
  3. 是否有多個拦截器冲突

8. 总结 🎯

概念 说明 类比
preHandle 控制器执行前调用,返回boolean 检票员
postHandle 控制器执行后,视图渲染前调用 散场工作人员
afterCompletion 整个请求完成后调用 清洁工
路径配置 使用/**拦截所有路径 设置安检区域
排除配置 使用exclude-mapping排除路径 VIP通道免检

拦截器的核心价值: 在不修改原有代码的情况下,为请求处理添加额外功能。

posted on 2025-09-14 21:36  笨忠  阅读(14)  评论(0)    收藏  举报