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

拦截器 Interceptor 详解

想象一下,你正在指挥一场复杂的交响乐演出。作为指挥家,你需要在乐曲演奏过程中,精准地控制每个声部的演奏时机和节奏变化。在软件开发领域,Interceptor 就像一位经验丰富的指挥家,它能够在不改变程序原有结构的情况下,灵活地拦截程序的执行流程,并在关键节点插入额外的处理逻辑,就像指挥家在乐谱上添加一些精妙的装饰音,让程序的演奏更加优雅动听。

一、Interceptor 概念

1.1 什么是 Interceptor?

在 Web 应用中,用户的请求就像一张张乐谱,而 Controller 方法则是演奏乐曲的各个声部。Interceptor 就像一位掌控全局的指挥家,它能够拦截住用户的每一个请求,并在请求到达目标 Controller 方法之前或之后,执行一些预先安排好的动作,例如检查用户是否登录、记录请求日志、修改请求参数等等。

1.2 Interceptor 的作用
  • 预处理请求 (preHandle): 就像指挥家在乐曲演奏之前,需要先确定每个声部的演奏顺序和节奏一样,Interceptor 可以在请求到达目标 Controller 方法之前,执行一些预处理逻辑,例如:

    • 检查用户是否登录: 就像核对演奏者身份一样,确保只有授权用户才能访问特定资源。

    • 校验请求参数: 就像检查乐器的音准一样,确保输入数据的合法性和安全性,避免出现“走调”的情况。

    • 记录请求日志: 就像记录演奏时间和曲目一样,方便日后追踪问题和分析用户行为。

  • 后处理响应 (postHandle): 如同指挥家在乐章结束后,需要对演奏效果进行点评一样,Interceptor 可以在目标 Controller 方法执行完毕后,对响应进行一些后处理操作,例如:

    • 统一处理异常: 就像及时纠正演奏中的错误一样,避免将程序异常直接暴露给用户,提供更加友好的提示信息。

    • 对响应数据进行加密或压缩: 就像对录音进行后期处理一样,提高数据传输效率和安全性。

    • 记录响应时间: 就像统计乐曲演奏时间一样,监控系统性能,找出程序的“瓶颈”所在。

  • 最终处理 (afterCompletion): 如同指挥家在整场演出结束后,需要对舞台进行清理和整理一样,Interceptor 可以在视图渲染完毕后,执行一些最终的清理工作,例如:

    • 释放资源: 关闭数据库连接、释放文件句柄等,避免资源泄露。

    • 记录最终的响应状态码和响应时间: 方便监控系统运行状况。

1.3 Interceptor 与 Filter 的区别

虽然 Interceptor 和 Filter 都可以拦截请求,但它们就像指挥家和舞台监督一样,负责不同的工作:

  • 拦截目标不同: Filter 位于 Servlet 容器级别,就像舞台监督一样,负责管理所有演员(Servlet 和 JSP)的进出场顺序;而 Interceptor 位于 Spring MVC 框架内部,就像指挥家一样,只负责指挥演奏者(Controller)的演奏过程。

  • 工作机制不同: Filter 基于回调函数机制,就像舞台监督通过广播通知演员一样;而 Interceptor 基于 Java 反射机制,就像指挥家通过指挥棒直接控制演奏者一样。

  • 使用场景不同: Filter 通常用于处理与 Servlet API 相关的通用逻辑,例如设置字符编码、Gzip 压缩等,就像舞台监督负责舞台灯光和音响效果一样;而 Interceptor 更适合处理与业务逻辑相关的通用逻辑,例如权限验证、日志记录等,就像指挥家负责乐曲的艺术表现力一样,属于spring 框架提供的。

二、Spring MVC Interceptor

2.1 三大核心方法

Spring MVC Interceptor 提供了三个核心方法,就像指挥家的指挥棒一样,可以灵活地控制程序的执行流程:

  • preHandle(HttpServletRequest request, HttpServletResponse response, Object handler): 这是演奏开始前的准备工作,就像指挥家在乐章开始前,需要先确定演奏的节奏和速度一样,该方法在 Controller 方法执行之前被调用,可以用于预处理请求,例如:

    • 判断用户是否登录:如果未登录,则可以重定向到登录页面,并返回 false,阻止请求继续执行;如果已登录,则返回 true,允许请求继续执行。

    • 校验请求参数:如果参数不合法,则可以设置错误信息,并返回 false,阻止请求继续执行;如果参数合法,则返回 true,允许请求继续执行。

  • postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView): 这是乐章演奏后的点评环节,就像指挥家在乐章结束后,需要对演奏效果进行点评一样,该方法在 Controller 方法执行完毕后,但在视图渲染之前被调用,可以用于修改 ModelAndView 对象,例如:

    • 添加模型数据:例如,可以添加一些通用的页面元素,例如网站标题、用户信息等等。

    • 修改视图名称:例如,可以根据用户的角色,跳转到不同的页面。

  • afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex): 这是演出结束后的谢幕时间,就像指挥家在整场演出结束后,需要向观众谢幕一样,该方法在视图渲染完毕后被调用,可以用于资源清理、记录响应日志等。

简而言之:

        1.preHandle方法:目标资源方法执行前执行。 返回true:放行 返回false:不放行

        2.postHandle方法:目标资源方法执行后执行

        3.afterCompletion方法:视图渲染完毕后执行,最后执行

2.2 代码示例
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class MyInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 预处理逻辑,例如打印请求路径
        System.out.println("Interceptor - preHandle: " + request.getRequestURI());

        // 执行权限检查逻辑...
        boolean hasPermission = checkPermission(request); 
        if (!hasPermission) {
            // 如果没有权限,设置响应状态码为403,并返回false阻止请求继续执行
            response.setStatus(HttpServletResponse.SC_FORBIDDEN);
            return false;
        }

        // 返回 true,表示放行,继续执行下一个拦截器或目标 Controller 方法
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        // 后处理逻辑,例如添加模型数据
        System.out.println("Interceptor - postHandle");
        if (modelAndView != null) {
            modelAndView.addObject("message", "来自拦截器的问候!");
        }
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // 资源清理、记录响应日志等操作
        System.out.println("Interceptor - afterCompletion");
    }

    // 模拟权限检查方法
    private boolean checkPermission(HttpServletRequest request) {
        // ... 检查用户是否具有访问权限 ...
        return true;
    }
}

2.3 配置 Interceptor
  • 基于 Java 代码配置: 我们可以通过实现 WebMvcConfigurer 接口,并重写 addInterceptors() 方法来注册自定义的拦截器。

@Configuration
public class MyWebMvcConfigurer implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new MyInterceptor())
                .addPathPatterns("/**") // 设置拦截路径,例如拦截所有请求
                .excludePathPatterns("/login", "/register"); // 设置排除路径,例如排除登录和注册请求
    }
}

  • 基于 XML 文件配置: 我们也可以在 Spring MVC 的配置文件中使用 <mvc:interceptors> 元素来注册自定义的拦截器。

<mvc:interceptors>
    <bean class="com.example.MyInterceptor">
        <property name="mappedPatterns">
            <list>
                <value>/**</value> <!-- 设置拦截路径 -->
            </list>
        </property>
        <property name="excludedPatterns">
            <list>
                <value>/login</value> <!-- 设置排除路径 -->
                <value>/register</value>
            </list>
        </property>
    </bean>
</mvc:interceptors>

三、实战演练:Interceptor 实现登录校验

3.1 需求分析

假设我们正在开发一个电商网站,用户需要登录才能进行下单操作。为了保证网站安全,我们需要使用 Interceptor 对所有下单请求进行拦截,检查用户是否登录,如果未登录,则跳转到登录页面。

3.2 代码实现
@Component
public class LoginInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 获取用户信息
        User user = (User) request.getSession().getAttribute("user");

        // 判断用户是否登录
        if (user == null) {
            // 未登录,跳转到登录页面
            response.sendRedirect("/login");
            return false; // 拦截请求
        }

        // 已登录,放行请求
        return true;
    }
}

3.3 配置 Interceptor
@Configuration
public class MyWebMvcConfigurer implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LoginInterceptor())
                .addPathPatterns("/order/**"); // 拦截所有以 /order/ 开头的请求
    }
}

四、总结:

Interceptor 是构建灵活、可扩展 Web 应用的利器,它能够帮助我们优雅地处理横切关注点,提高代码复用性,降低系统耦合度。掌握 Interceptor 的使用,能够让我们开发出更加健壮、易于维护的 Web 应用,就像一位经验丰富的指挥家,能够指挥乐团演奏出美妙动听的乐章。

以上就是关于拦截器Interceptor的详解,希望对各位有所帮助,感谢各位看官的观看,谢谢~


http://www.kler.cn/news/329668.html

相关文章:

  • react中的ref三种形式
  • C# Windows EventHandler事件的使用
  • 足球青训俱乐部管理:Spring Boot技术驱动
  • 两个圆形 一个z里面一个z外面,z里面的大,颜色不同 html
  • 通信工程学习:什么是FTP文件传输协议
  • C++系列-继承补充
  • 【Redis 源码】7RDB持久化
  • 迈德斯特升降桌使用说明
  • 5个python多线程简单示例
  • 封装轮播图 (因为基于微博小程序,语法可能有些出入,如需使用需改标签)
  • [Day 77] 區塊鏈與人工智能的聯動應用:理論、技術與實踐
  • java往word中添加水印,往excel中添加图片
  • kafka 换盘重平衡副本 操作流程
  • Java面试——操作系统篇
  • 【PCB工艺】表面贴装技术中常见错误
  • 【高效管理集合】并查集的实现与应用
  • springboot3通过HttpRequest请求soap
  • 躺平成长:微信小程序运营日记第二天
  • C0005.Clion中移动ui文件到新目录后,报错问题的解决
  • 『功能项目』宠物的召唤跟随【79】
  • 有关Python时间戳的计算
  • OpenAI全新多模态内容审核模型上线:基于 GPT-4o,可检测文本和图像
  • lstm实践
  • 如何在 Windows 10 上恢复未保存/删除的 Word 文档
  • C++ 学习,标准库
  • 结构光编解码—正反格雷码解码代码
  • SQL_create_view
  • VR、AR、MR、XR 领域最新科研资讯获取指南
  • CSS链接
  • 查找与排序-快速排序