当前位置: 首页 > article >正文

SpringMVC拦截器详解:原理、使用与配置

目录

         1. 什么是拦截器?

2. 拦截器与过滤器的区别

3. 拦截器方法详解

4. 单个拦截器执行流程

5. 使用拦截器实现用户登录权限验证

6. 多个拦截器的执行流程


1. 什么是拦截器?

在SpringMVC框架中,拦截器(Interceptor)是一种用于拦截用户请求并进行处理的机制,类似于Servlet中的过滤器(Filter)。拦截器主要用于:

  • 用户权限验证
  • 用户是否登录验证
  • 日志记录
  • 请求的预处理和后处理等

SpringMVC的拦截器机制是可插拔的,可以在配置文件中进行灵活配置,启用或禁用某个功能的拦截器。例如,如果需要权限验证,只需在配置文件中添加拦截器;如果不需要,只需将其移除。


2. 拦截器与过滤器的区别

        拦截器与过滤器在功能上相似,都是用于拦截请求并作相应处理,但它们的实现和执行流程有所不同。以下是它们的主要区别:

区别过滤器 (Filter)拦截器 (Interceptor)
依赖关系依赖于Servlet,工作在Servlet容器层属于SpringMVC,工作在SpringMVC层
作用范围对所有请求都有效仅对Controller层的请求有效
执行顺序过滤器先执行,拦截器后执行拦截器在Controller方法执行前和后都可执行

执行顺序:

  • 过滤器在请求进入Tomcat容器后、Servlet前执行。
  • 拦截器则是在请求到达Controller方法前执行,在请求返回视图前以及请求处理完后执行。

 


3. 拦截器方法详解

自定义拦截器需要实现SpringMVC的HandlerInterceptor接口,该接口定义了以下三个方法:

  • preHandle:在Controller方法执行之前执行。如果该方法返回false,请求会被拦截,不再执行后续的操作;如果返回true,则继续执行后续操作,包括Controller方法。

  • postHandle:在Controller方法执行之后、视图渲染之前执行。可以在此方法中修改返回的Model和View,例如添加一些数据或修改视图。

  • afterCompletion:在整个请求处理完毕之后执行,用于清理资源、记录日志等。

示例代码:

public class MyInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandle: 在Controller方法执行前");
        return true; // 继续执行后续操作
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle: 在Controller方法执行后,视图返回前");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("afterCompletion: 请求处理完成,视图渲染后");
    }
}

4. 单个拦截器执行流程

当请求到达SpringMVC时,拦截器的执行顺序如下:

  1. preHandle():首先执行preHandle()方法。如果返回false,请求会被拦截,后续操作不会执行;如果返回true,继续执行Controller方法。
  2. Controller方法:处理请求,进行相应的业务逻辑处理。
  3. postHandle():Controller方法执行后,执行postHandle()方法,此时可以操作Model和View。
  4. 视图渲染:DispatcherServlet将视图返回给客户端。
  5. afterCompletion():请求处理完毕后,执行afterCompletion()方法,进行资源清理、日志记录等操作。


5. 使用拦截器实现用户登录权限验证

        以下是一个实现用户登录验证的例子。在SpringMVC应用中,我们可以通过自定义拦截器来检查用户是否已登录,若未登录,则拦截请求并重定向到登录页面。

1. Controller层设计

@Controller
public class LoginController {

    /**
     * 跳转登录页
     * @return
     */
    @RequestMapping(value = "/login",method = RequestMethod.GET)
    public String loginPage(){
        System.out.println("跳转到login.html页面当中");
        return "login";
    }

    /**
     * 用户登录,成功到主页,失败回到登录页
     * @param user
     * @param model
     * @param session
     * @return
     */
    @RequestMapping(value = "/login",method = RequestMethod.POST)
    public String login(User user, Model model, HttpSession session){
        if(user.getUsername() !=null && user.getUsername().equals("admin")
                && user.getPassword() !=null && user.getPassword().equals("123456")){
            System.out.println("用户登录功能实现");
            //将用户添加到session保存
            session.setAttribute("user",user);
            return "/suc";
        }
        model.addAttribute("msg","账户或密码错误,请重新登录");
        return "login";
    }

    /**
     * 跳转到主页
     * @return
     */
    @RequestMapping("/index")
    public String indexPage(){
        System.out.println("跳转到主页");
        return "suc";
    }

    /**
     * 用户退出登录
     * @param session
     * @return
     */
    @RequestMapping("/logout")
    public String logout(HttpSession session){
        session.invalidate();//清除session
        System.out.println("用户退出登录");
        return "login";
    }

}

2. 登录拦截器设计


public class LoginInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String url = request.getRequestURI();
        
        // 如果是非登录请求,且用户未登录,跳转到登录页面
        if (!url.contains("login")) {
            if (request.getSession().getAttribute("user") != null) {
                return true; // 已登录,放行
            } else {
                request.setAttribute("msg", "您还未登录,请先登录");
                request.getRequestDispatcher("/login").forward(request, response);  // 跳转到登录页面
                return false; // 拦截请求
            }
        }
        return true; // 登录请求,放行
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        // 可用于对返回的视图做修改
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // 可用于清理资源、记录日志等
    }
}

3. 拦截器配置

springmvc.xml配置文件中配置拦截器:

<!--配置拦截器-->
<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/**"/> <!--/**表示所有url-->
        <bean class="com.qcby.Interceptor.LoginInterceptor"/>
    </mvc:interceptor>
</mvc:interceptors>

4. 登录页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录页面</title>
</head>
<body>
<h1> <font color="red"> <b th:text="${msg}"></b></font></h1>
<form action="/SSMDemo/login" method="post">
    账户:<input type="text" name="username"/>
    密码:<input type="password" name="password"/>
    <input type="submit" value="登录"/>
</form>
</body>
</html>

5.主页

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>Hello <b th:text="${msg}"></b></h1>
<a href="/SSMDemo/logout" >入门程序</a>
</body>
</html>

6. 多个拦截器的执行流程

当有多个拦截器同时工作时,它们的执行流程如下:

  • preHandle()方法按照配置的顺序执行。
  • postHandle()方法和afterCompletion()方法则是按照配置的逆序执行;
    即后配置的拦截器的postHandle()afterCompletion()方法先执行。

 

示例:

假设有两个拦截器Interceptor1Interceptor2,并且Interceptor1先配置在springmvc.xml中。它们的执行顺序如下:

  • Interceptor1preHandle()执行
  • Interceptor2preHandle()执行
  • Controller方法执行
  • Interceptor2postHandle()执行
  • Interceptor1postHandle()执行
  • Interceptor2afterCompletion()执行
  • Interceptor1afterCompletion()执行

总结

        SpringMVC的拦截器为我们提供了灵活的请求处理机制,能够在请求的生命周期中进行多方面的控制,如权限验证、日志记录、性能监控等。通过实现HandlerInterceptor接口并配置拦截器,可以轻松地在请求的不同阶段插入自定义逻辑,从而增强应用的功能和可维护性。


http://www.kler.cn/a/530553.html

相关文章:

  • 笔灵ai写作技术浅析(四):知识图谱
  • Cmake学习笔记
  • Spring Boot 实例解析:配置文件
  • 【最长上升子序列Ⅱ——树状数组,二分+DP,纯DP】
  • 玩转Docker | 使用Docker部署SSCMS内容管理系统
  • deep seek R1本地化部署及openAI API调用
  • 【Numpy核心编程攻略:Python数据处理、分析详解与科学计算】2.4 索引优化:避免意外复制的高效技巧
  • deepseek使用教程
  • 力扣 347. 前 K 个高频元素
  • Baklib赋能企业提升内容中台构建效率的全新路径解析
  • 基于人脸识别的课堂考勤系统
  • 【系统迁移】将系统迁移到新硬盘中(G15 5520)
  • 高清种子资源获取指南 | ✈️@seedlinkbot
  • 第六篇:事务与并发控制
  • 算法【混合背包】
  • 深入探索 Android 技术:从基础到前沿
  • 向上管理的必要性
  • 本地部署DeepSeek 多模态大模型Janus-Pro-7B
  • C++ 常用排序算法
  • 音视频入门基础:RTP专题(5)——FFmpeg源码中,解析SDP的实现
  • XML DOM 节点信息
  • 眼见着折叠手机面临崩溃,三星计划增强抗摔能力挽救它
  • 【LeetCode 刷题】回溯算法-分割问题
  • 如何本地部署DeepSeek?DeepThink R1 本地部署全攻略:零基础小白指南。
  • 蓝桥杯单片机第七届省赛
  • MySQL大表优化方案