SSM 框架之 SpringMVC 拦截器全解析:原理、实现与实战

JSON 2026-01-26 16:06:37 265

一、拦截器核心概念

1. 什么是 SpringMVC 拦截器

SpringMVC 拦截器是基于 AOP 思想设计的请求拦截组件,仅作用于 SpringMVC 接管的 Controller 请求,可在请求处理的不同阶段插入自定义业务逻辑。它是 SpringMVC 框架专属组件,与 Spring 容器深度集成,能直接调用容器中的 Service、Mapper 等 Bean,灵活性远高于 Servlet 过滤器。

2. 拦截器的核心应用场景

  • 登录状态校验:拦截未登录用户访问受保护的页面 / 接口,跳转至登录页;
  • 权限精细化控制:根据用户角色拦截非法访问(如普通用户访问管理员接口);
  • 请求日志记录:记录请求 URL、请求参数、执行耗时、响应状态等;
  • 参数预处理 / 后处理:统一格式化请求参数、封装响应数据;
  • 资源清理:请求完成后释放连接、关闭流等资源。

3. 拦截器与 Servlet 过滤器(Filter)的核心区别

特性SpringMVC 拦截器Servlet 过滤器
所属规范SpringMVC 框架Servlet 规范
拦截范围仅拦截 Controller 请求拦截所有请求(含静态资源)
Spring 集成度可直接注入 Service/Bean需通过容器上下文获取 Spring Bean
执行时机DispatcherServlet 调度后DispatcherServlet 调度前

二、拦截器核心接口与方法

SpringMVC 通过HandlerInterceptor接口定义拦截器的核心行为,该接口包含 3 个核心方法,对应请求处理的不同阶段,开发者可按需重写:

方法名执行时机返回值 / 核心作用
preHandle请求到达 Controller 之前boolean 类型:true放行,false拦截
postHandleController 执行完成、视图渲染之前可修改 ModelAndView(如添加公共数据)
afterCompletion视图渲染完成后(请求完全结束)用于资源清理、日志收尾

其中,preHandle是最常用的方法,几乎所有核心拦截逻辑(如登录验证)都在此实现。

三、拦截器完整实现步骤(登录验证实战)

以下以 “登录状态校验” 为例,完整演示 SSM 拦截器的实现流程。

步骤 1:自定义拦截器类(实现 HandlerInterceptor 接口)

创建拦截器类并实现HandlerInterceptor接口,重写核心方法完成登录校验逻辑:  

import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 自定义登录拦截器:校验用户是否已登录
 */
public class LoginInterceptor implements HandlerInterceptor {

    // 核心方法:请求到达Controller前执行(登录校验核心逻辑)
    @Override
    public boolean preHandle(HttpServletRequest request, 
                             HttpServletResponse response, 
                             Object handler) throws Exception {
        // 1. 从Session中获取登录用户标识
        Object loginUser = request.getSession().getAttribute("loginUser");
        
        // 2. 未登录:拦截请求,跳转至登录页并提示
        if (loginUser == null) {
            request.setAttribute("msg", "请先登录后再访问!");
            request.getRequestDispatcher("/login").forward(request, response);
            return false; // 返回false表示拦截请求
        }
        
        // 3. 已登录:放行请求,继续执行Controller逻辑
        return true;
    }

    // Controller执行完成、视图渲染前执行(可选)
    @Override
    public void postHandle(HttpServletRequest request, 
                           HttpServletResponse response, 
                           Object handler, 
                           org.springframework.web.servlet.ModelAndView modelAndView) throws Exception {
        // 示例:给所有视图添加公共参数(如系统时间)
        if (modelAndView != null) {
            modelAndView.addObject("sysTime", System.currentTimeMillis());
        }
    }

    // 视图渲染完成后执行(可选,用于资源清理/日志收尾)
    @Override
    public void afterCompletion(HttpServletRequest request, 
                                HttpServletResponse response, 
                                Object handler, 
                                Exception ex) throws Exception {
        // 示例:记录请求完成日志
        System.out.println("请求完成,URL:" + request.getRequestURI() + ",异常:" + (ex == null ? "无" : ex.getMessage()));
    }
}

步骤 2:在 SpringMVC 配置文件中注册拦截器

拦截器需在 SpringMVC 配置文件(通常为spring-mvc.xml)中注册,并通过mappingexclude-mapping精准控制拦截范围(避免拦截登录页、静态资源导致死循环):  

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!-- 开启SpringMVC注解驱动(必备) -->
    <mvc:annotation-driven/>

    <!-- 配置拦截器 -->
    <mvc:interceptors>
        <mvc:interceptor>
            <!-- 拦截所有层级的请求:/** 表示拦截所有请求 -->
            <mvc:mapping path="/**"/>
            <!-- 排除不需要拦截的路径 -->
            <mvc:exclude-mapping path="/login"/>    <!-- 登录页 -->
            <mvc:exclude-mapping path="/doLogin"/>  <!-- 登录接口 -->
            <mvc:exclude-mapping path="/static/**"/> <!-- 静态资源(css/js/img) -->
            
            <!-- 注册自定义拦截器类 -->
            <bean class="com.example.interceptor.LoginInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>

    <!-- 基础配置:Controller组件扫描 + 视图解析器 -->
    <context:component-scan base-package="com.example.controller"/>
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/pages/"/> <!-- JSP文件路径前缀 -->
        <property name="suffix" value=".jsp"/> <!-- JSP文件后缀 -->
    </bean>

    <!-- 静态资源放行(可选,避免静态资源被拦截) -->
    <mvc:default-servlet-handler/>
</beans>

步骤 3:编写测试 Controller 验证拦截器

创建登录相关 Controller,验证拦截器的拦截效果:  

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

@Controller
public class LoginController {

    // 跳转到登录页(不被拦截)
    @GetMapping("/login")
    public String toLogin() {
        return "login"; // 对应/WEB-INF/pages/login.jsp
    }

    // 登录逻辑处理(不被拦截)
    @PostMapping("/doLogin")
    public String login(@RequestParam("username") String username,
                        @RequestParam("password") String password,
                        HttpSession session) {
        // 模拟登录校验(实际项目中需查询数据库)
        if ("admin".equals(username) && "123456".equals(password)) {
            session.setAttribute("loginUser", username); // 登录成功,存入用户信息
            return "redirect:/index"; // 跳转至首页
        } else {
            request.setAttribute("msg", "用户名或密码错误!");
            return "login"; // 登录失败,返回登录页
        }
    }

    // 系统首页(需登录才能访问,未登录会被拦截)
    @GetMapping("/index")
    public String index() {
        return "index"; // 对应/WEB-INF/pages/index.jsp
    }
}

四、关键补充知识点

1. 多拦截器的执行顺序

若配置多个拦截器,方法执行顺序遵循以下规则:

  • preHandle:按配置顺序执行(先配置的拦截器先执行);
  • postHandle/afterCompletion:按配置逆序执行(后配置的拦截器先执行)。

例如配置拦截器 A、B,执行顺序为:A.preHandle()B.preHandle() → Controller 执行 → B.postHandle()A.postHandle() → 视图渲染 → B.afterCompletion()A.afterCompletion()

2. 静态资源的拦截处理

默认情况下,SpringMVC 拦截器不会拦截静态资源(如 CSS、JS、图片),若需拦截静态资源,需在配置文件中通过<mvc:resources>指定资源路径,并取消<mvc:default-servlet-handler/>配置。

3. 拦截器与过滤器的选择原则

  • 需拦截 Controller 请求 + 依赖 Spring Bean → 优先使用拦截器;
  • 需拦截静态资源、请求编码统一处理等全局场景 → 优先使用过滤器;
  • 复杂业务逻辑(如权限校验)→ 拦截器(集成 Spring 生态更便捷)。

五、总结

  1. SpringMVC 拦截器基于HandlerInterceptor接口实现,preHandle是核心方法,通过返回true/false控制请求是否放行;
  2. 拦截器需在 SpringMVC 配置文件中注册,通过mapping/exclude-mapping精准控制拦截范围,避免拦截登录页、静态资源;
  3. 拦截器是 SSM 开发中实现登录验证、权限控制的首选方案,相比 Servlet 过滤器,它与 Spring 生态深度集成,使用更灵活;
  4. 多拦截器的执行顺序有明确规则,需根据业务逻辑合理配置顺序。

版权所属:SO JSON在线解析

原文地址:https://www.sojson.com/blog/571.html

转载时必须以链接形式注明原始出处及本声明。

本文主题:

如果本文对你有帮助,那么请你赞助我,让我更有激情的写下去,帮助更多的人。

关于作者
一个低调而闷骚的男人。
相关文章
Shiro 教程,Ajax请求拦截跳转页面方案
CDN 请求返回 connection reset by peer,被拦截请求解决方案
如何查询域名是否被QQ或者微信拦截
SQL外连接剖
Java 完美解析.plist & 生成plist ,Android 解析.plist
nodejs开发网站用哪个框架?有什么优势?
json 解析与生成工具类 ,JSON操作讲解(附件)
如何解析JSON数据(详细解答)
DNS健康检测的原理?它是如何实现的?
掩码计算原理?它是怎么计算的?
最新文章
文件上传漏洞与防御 4058
前端构建工具选型指南:Webpack、Vite、Rollup、esbuild 深度对比 1444
物联网时代2026年时序数据库选型指南 1151
SaaS行业面临AI挑战:从“无限复用”到“灵活适应” 1269
神经网络:从构造到模型训练全链路解析 1168
一文吃透 Redis 核心存储结构:ziplist、listpack 与哈希表扩容 / 并发查询 1593
Linux sudo提权完整指南:从基础用法到生产级安全配置 691
XSS 和 CSRF 的本质区别及开发防御全解析 772
JVM垃圾回收(GC)全维度解析:从原理到调优实战 813
Linux动静态库与ELF加载全解析:从实操制作到底层原理 912
最热文章
免费天气API,天气JSON API,不限次数获取十五天的天气预报 783114
最新MyEclipse8.5注册码,有效期到2020年 (已经更新) 711464
苹果电脑Mac怎么恢复出厂系统?苹果系统怎么重装系统? 679993
Jackson 时间格式化,时间注解 @JsonFormat 用法、时差问题说明 562673
我为什么要选择RabbitMQ ,RabbitMQ简介,各种MQ选型对比 512621
Elasticsearch教程(四) elasticsearch head 插件安装和使用 484794
Jackson 美化输出JSON,优雅的输出JSON数据,格式化输出JSON数据... ... 302947
Java 信任所有SSL证书,HTTPS请求抛错,忽略证书请求完美解决 247433
Elasticsearch教程(一),全程直播(小白级别) 233097
谈谈斐讯路由器劫持,你用斐讯路由器,你需要知道的事情 228329
支付扫码

所有赞助/开支都讲公开明细,用于网站维护:赞助名单查看

查看我的收藏

正在加载... ...