程序员scholar 程序员scholar
首页
  • Java 基础

    • JavaSE
    • JavaIO
    • JavaAPI速查
  • Java 高级

    • JUC
    • JVM
    • Java新特性
    • 设计模式
  • Web 开发

    • Servlet
    • Java网络编程
  • Web 标准

    • HTML
    • CSS
    • JavaScript
  • 前端框架

    • Vue2
    • Vue3
    • Vue3 + TS
    • 微信小程序
    • uni-app
  • 工具与库

    • jQuery
    • Ajax
    • Axios
    • Webpack
    • Vuex
    • WebSocket
    • 第三方登录
  • 后端与语言扩展

    • ES6
    • Typescript
    • node.js
  • Element-UI
  • Apache ECharts
  • 数据结构
  • HTTP协议
  • HTTPS协议
  • 计算机网络
  • Linux常用命令
  • Windows常用命令
  • SQL数据库

    • MySQL
    • MySQL速查
  • NoSQL数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • RabbitMQ
  • 服务器

    • Nginx
  • Spring框架

    • Spring6
    • SpringMVC
    • SpringBoot
    • SpringSecurity
  • SpringCould微服务

    • SpringCloud基础
    • 微服务之DDD架构思想
  • 日常必备

    • 开发常用工具包
    • Hutoll工具包
    • IDEA常用配置
    • 开发笔记
    • 日常记录
    • 项目部署
    • 网站导航
    • 产品学习
    • 英语学习
  • 代码管理

    • Maven
    • Git教程
    • Git小乌龟教程
  • 运维工具

    • Docker
    • Jenkins
    • Kubernetes
  • 算法笔记

    • 算法思想
    • 刷题笔记
  • 面试问题常见

    • 十大经典排序算法
    • 面试常见问题集锦
关于
GitHub (opens new window)
首页
  • Java 基础

    • JavaSE
    • JavaIO
    • JavaAPI速查
  • Java 高级

    • JUC
    • JVM
    • Java新特性
    • 设计模式
  • Web 开发

    • Servlet
    • Java网络编程
  • Web 标准

    • HTML
    • CSS
    • JavaScript
  • 前端框架

    • Vue2
    • Vue3
    • Vue3 + TS
    • 微信小程序
    • uni-app
  • 工具与库

    • jQuery
    • Ajax
    • Axios
    • Webpack
    • Vuex
    • WebSocket
    • 第三方登录
  • 后端与语言扩展

    • ES6
    • Typescript
    • node.js
  • Element-UI
  • Apache ECharts
  • 数据结构
  • HTTP协议
  • HTTPS协议
  • 计算机网络
  • Linux常用命令
  • Windows常用命令
  • SQL数据库

    • MySQL
    • MySQL速查
  • NoSQL数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • RabbitMQ
  • 服务器

    • Nginx
  • Spring框架

    • Spring6
    • SpringMVC
    • SpringBoot
    • SpringSecurity
  • SpringCould微服务

    • SpringCloud基础
    • 微服务之DDD架构思想
  • 日常必备

    • 开发常用工具包
    • Hutoll工具包
    • IDEA常用配置
    • 开发笔记
    • 日常记录
    • 项目部署
    • 网站导航
    • 产品学习
    • 英语学习
  • 代码管理

    • Maven
    • Git教程
    • Git小乌龟教程
  • 运维工具

    • Docker
    • Jenkins
    • Kubernetes
  • 算法笔记

    • 算法思想
    • 刷题笔记
  • 面试问题常见

    • 十大经典排序算法
    • 面试常见问题集锦
关于
GitHub (opens new window)
npm

(进入注册为作者充电)

  • 后端开发

    • Spring Boot多模块项目开发
    • Spring Boot图片资源返回
    • Spring Boot文件上传
    • Spring Boot文件下载
    • 对接第三方文件上传
    • Servlet 原生API
    • HttpServletResponse 和 ResponseEntity
    • 后端解决跨域问题
    • 后端拦截器
      • 一、Spring Boot 中的拦截器概述
      • 二、实现拦截器的几种方式
        • 1. 基于 HandlerInterceptor 接口实现自定义拦截器
        • 2. 注册拦截器
        • 3. 基于 HandlerInterceptorAdapter(已过时)
      • 三、拦截器中的常用 API 和参数说明
      • 四、拦截器的应用场景
        • 1. 用户认证与权限验证拦截器
        • 2. 请求日志记录拦截器
        • 3. 数据加密与解密拦截器
        • 4. 全局异常处理拦截器
        • 5. 拦截器的注册与配置
      • 五、拦截器与过滤器的区别
    • SpringBoot+Vue实现邮件发送与验证码验证
    • 谷歌验证码
    • 利用hutool工具类实现图片验证码
    • 统一返回格式
    • 通用 普通 登录模块
    • 通用 JWT 登录认证模块
    • 通用 普通 注册模块
    • 基于 MyBatis curd
    • 基于 MyBatis-Plus curd
    • Java 常见对象模型
    • 开发枚举的使用
    • MyBatis与MyBatis-Plus日期类型处理
    • 接口日志拦截基础版
    • 接口日志拦截进阶版
    • 文件操作工具类
    • Spring Boot 数据校验
    • 幂等性
  • 前端开发

  • 开发笔记
  • 后端开发
scholar
2024-12-27
目录

后端拦截器

# Spring Boot 中的拦截器

前言

在 Spring Boot 中,拦截器(Interceptor)是一种用于拦截和处理 HTTP 请求的机制,可以在请求到达 Controller 之前或响应返回之前进行处理。拦截器可以用于记录日志、权限校验、修改请求或响应数据等。

# 一、Spring Boot 中的拦截器概述

Spring 提供了基于 HandlerInterceptor 接口的拦截器机制。拦截器可以在以下三个阶段进行处理:

  1. preHandle:在请求处理之前进行调用(Controller 方法调用之前)。
  2. postHandle:在请求处理之后调用(Controller 方法调用之后,但在视图渲染之前)。
  3. afterCompletion:在整个请求结束之后调用(视图渲染之后),常用于资源清理。

# 二、实现拦截器的几种方式

# 1. 基于 HandlerInterceptor 接口实现自定义拦截器

代码示例:

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

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

@Component
public class MyInterceptor implements HandlerInterceptor {

    // 在请求处理之前进行拦截
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("Pre Handle method is Calling");
        // 返回 true 表示继续处理请求,返回 false 则中断请求
        return true;
    }

    // 在请求处理之后,但在视图渲染之前进行拦截
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("Post Handle method is Calling");
    }

    // 在请求处理完成之后调用,常用于资源清理
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception exception) throws Exception {
        System.out.println("Request and Response is completed");
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

关键点:

  • preHandle 方法:用于在请求进入 Controller 之前进行处理,返回 true 表示继续处理请求,返回 false 则中断请求。
  • postHandle 方法:用于在请求处理完毕后但在视图渲染之前进行处理,可用于修改模型数据或视图。
  • afterCompletion 方法:用于在整个请求处理完成后进行处理,适合用于资源清理、日志记录等操作。

# 2. 注册拦截器

在 Spring Boot 中,拦截器需要通过配置类进行注册。

代码示例:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class InterceptorConfig implements WebMvcConfigurer {

    @Autowired
    private MyInterceptor myInterceptor; // 注入自定义拦截器

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 注册自定义拦截器,并指定拦截路径
        registry.addInterceptor(myInterceptor)
                .addPathPatterns("/api/**") // 拦截的路径
                .excludePathPatterns("/api/login", "/api/register"); // 排除的路径
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

关键配置项:

  • addInterceptor:注册自定义拦截器。
  • addPathPatterns:指定需要拦截的路径模式。
  • excludePathPatterns:指定不需要拦截的路径。

# 3. 基于 HandlerInterceptorAdapter(已过时)

HandlerInterceptorAdapter 是 Spring 早期提供的简化拦截器实现的适配器类,但在 Spring 5.3 之后被标记为已过时。现在推荐直接实现 HandlerInterceptor 接口。

# 三、拦截器中的常用 API 和参数说明

  1. HttpServletRequest 和 HttpServletResponse:

    • 可以通过这两个对象获取请求参数、请求头、Session、响应状态码等信息。
    • request.getRequestURI():获取请求的 URI。
    • request.getMethod():获取请求方法(如 GET、POST)。
    • response.setStatus(int status):设置响应状态码。
  2. Object handler:

    • 代表当前请求的处理器(Controller 方法),可以用于判断当前请求的目标。
  3. ModelAndView(在 postHandle 中使用):

    • 可以通过 ModelAndView 修改视图和模型数据。

# 四、拦截器的应用场景

在企业级应用中,拦截器(Interceptor)广泛用于以下几种常见场景:

  1. 用户认证与权限验证:在处理请求前验证用户是否登录,是否有访问权限。
  2. 请求日志记录:记录每次请求的详细信息,方便后续分析和排查问题。
  3. 数据加密与解密:在请求到达 Controller 前对敏感数据进行解密,响应返回前进行加密。
  4. 全局异常处理:统一捕获和处理应用中的异常,并返回友好的错误提示。

# 1. 用户认证与权限验证拦截器

在处理请求前验证用户是否已登录,并根据用户的角色或权限判断是否可以访问目标资源。

代码示例:

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

/**
 * 用户认证与权限验证拦截器。
 */
@Component
public class AuthenticationInterceptor implements HandlerInterceptor {

    /**
     * 处理请求前的认证逻辑。
     * @param request 当前的 HttpServletRequest 对象
     * @param response 当前的 HttpServletResponse 对象
     * @param handler 目标处理器对象
     * @return 返回 true 表示继续处理请求,false 表示请求被拦截
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 模拟获取 Token,并验证是否有效
        String token = request.getHeader("Authorization");
        if (token == null || !isValidToken(token)) {
            // 如果 Token 无效,返回未授权状态码
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            response.getWriter().write("未授权,禁止访问!");
            return false;
        }
        // 如果认证通过,继续处理请求
        return true;
    }

    /**
     * 校验 Token 是否有效(示例方法)。
     * @param token 待校验的 Token
     * @return Token 是否有效
     */
    private boolean isValidToken(String token) {
        // 在实际应用中,这里应校验 Token 的有效性,如解析 JWT、查询 Redis 等
        return "valid-token".equals(token);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

关键点:

  • request.getHeader("Authorization"):获取请求头中的认证信息。
  • response.setStatus(HttpServletResponse.SC_UNAUTHORIZED):当用户未通过认证时,返回 401 状态码。
  • 应用场景:适用于保护需要认证的 API 资源。

# 2. 请求日志记录拦截器

记录每次请求的详细信息,包括请求时间、请求路径、请求参数、处理耗时等。

代码示例:

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.LocalDateTime;
import java.util.Enumeration;
import java.util.logging.Logger;

/**
 * 请求日志记录拦截器。
 */
@Component
public class LoggingInterceptor implements HandlerInterceptor {

    private static final Logger logger = Logger.getLogger(LoggingInterceptor.class.getName());

    /**
     * 记录请求开始时间。
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 记录请求开始时间
        request.setAttribute("startTime", System.currentTimeMillis());
        logger.info("请求开始: " + LocalDateTime.now());
        logger.info("请求路径: " + request.getRequestURI());
        logger.info("请求方法: " + request.getMethod());

        // 记录请求头信息
        Enumeration<String> headers = request.getHeaderNames();
        while (headers.hasMoreElements()) {
            String headerName = headers.nextElement();
            logger.info(headerName + ": " + request.getHeader(headerName));
        }

        return true;
    }

    /**
     * 记录请求完成时间及耗时。
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        long startTime = (Long) request.getAttribute("startTime");
        long endTime = System.currentTimeMillis();
        long duration = endTime - startTime;

        logger.info("请求结束: " + LocalDateTime.now());
        logger.info("请求耗时: " + duration + " ms");

        if (ex != null) {
            logger.severe("请求异常: " + ex.getMessage());
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

关键点:

  • request.getRequestURI():获取请求的路径。
  • request.setAttribute("startTime", System.currentTimeMillis()):记录请求的开始时间,用于计算处理耗时。
  • 应用场景:适用于记录请求日志,帮助分析请求性能或排查问题。

# 3. 数据加密与解密拦截器

在请求进入 Controller 前,对敏感数据进行解密;在响应返回前,对敏感数据进行加密。

代码示例:

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

/**
 * 数据加密与解密拦截器。
 */
@Component
public class EncryptionInterceptor implements HandlerInterceptor {

    /**
     * 请求前解密处理。
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 获取请求中的加密数据,并进行解密
        String encryptedData = request.getParameter("data");
        if (encryptedData != null) {
            String decryptedData = decrypt(encryptedData);
            // 将解密后的数据放回请求中,供后续处理
            request.setAttribute("decryptedData", decryptedData);
        }
        return true;
    }

    /**
     * 响应前加密处理。
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        // 获取响应数据并进行加密
        String responseData = (String) request.getAttribute("responseData");
        if (responseData != null) {
            String encryptedData = encrypt(responseData);
            response.getWriter().write(encryptedData);
        }
    }

    /**
     * 数据解密逻辑(示例方法)。
     */
    private String decrypt(String data) {
        // 实际开发中应使用加密算法解密数据
        return "解密后的数据: " + data;
    }

    /**
     * 数据加密逻辑(示例方法)。
     */
    private String encrypt(String data) {
        // 实际开发中应使用加密算法加密数据
        return "加密后的数据: " + data;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55

关键点:

  • request.getParameter("data"):获取请求参数中的加密数据。
  • response.getWriter().write(encryptedData):将加密后的响应数据写入响应体。
  • 应用场景:适用于对涉及敏感数据的接口进行安全处理。

# 4. 全局异常处理拦截器

统一捕获系统中的异常,返回统一格式的错误响应。

代码示例:

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

/**
 * 全局异常处理拦截器。
 */
@Component
public class GlobalExceptionInterceptor implements HandlerInterceptor {

    /**
     * 处理请求完成后的异常。
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        if (ex != null) {
            // 设置响应状态码
            response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
            // 返回统一格式的错误消息
            response.setContentType("application/json;charset=UTF-8");
            response.getWriter().write("{\"error\":\"服务器内部错误\",\"message\":\"" + ex.getMessage() + "\"}");
            response.getWriter().flush();
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

关键点:

  • response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value()):设置 HTTP 500 状态码。
  • response.setContentType("application/json;charset=UTF-8"):设置响应内容类型为 JSON 格式。
  • 应用场景:适用于统一处理全局异常,提升用户体验。

# 5. 拦截器的注册与配置

在 Spring Boot 中,拦截器需要通过配置类进行注册,确保在合适的请求路径上生效。

代码示例:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * 拦截器配置类,用于注册全局拦截器。
 */
@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Autowired
    private AuthenticationInterceptor authenticationInterceptor;
    
    @Autowired
    private LoggingInterceptor loggingInterceptor;
    
    @Autowired    private EncryptionInterceptor encryptionInterceptor;
    
    @Autowired
    private GlobalExceptionInterceptor globalExceptionInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 注册认证拦截器
        registry.addInterceptor(authenticationInterceptor)
                .addPathPatterns("/api/**") // 拦截所有 /api/** 路径下的请求
                .excludePathPatterns("/api/public/**"); // 排除不需要拦截的路径

        // 注册日志拦截器
        registry.addInterceptor(loggingInterceptor)
                .addPathPatterns("/**"); // 拦截所有请求

        // 注册加密拦截器
        registry.addInterceptor(encryptionInterceptor)
                .addPathPatterns("/api/secure/**"); // 只拦截特定路径

        // 注册全局异常处理拦截器
        registry.addInterceptor(globalExceptionInterceptor)
                .addPathPatterns("/**"); // 拦截所有请求
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

关键点:

  • registry.addInterceptor():注册拦截器。
  • addPathPatterns():指定需要拦截的路径。
  • excludePathPatterns():指定不需要拦截的路径。
  • 应用场景:配置不同的拦截器,确保在适当的路径上生效。

# 五、拦截器与过滤器的区别

  • 执行顺序:过滤器是 Servlet 规范的一部分,优先于拦截器执行;拦截器是在 Spring MVC 中的执行流程。
  • 使用范围:过滤器可以处理所有进入 Spring 容器的请求,而拦截器主要用于拦截进入 Spring MVC 的请求。

总结

  1. 拦截器是 Spring Boot 中非常强大的功能,适用于多种场景的请求预处理、后处理和资源清理。
  2. 通过实现 HandlerInterceptor 接口,并在配置类中进行注册,可以灵活地对请求进行拦截和处理。
  3. 拦截器可以在 Controller 之前、之后,甚至在视图渲染之后进行处理,具有很大的灵活性。
编辑此页 (opens new window)
上次更新: 2025/03/16, 22:19:39
后端解决跨域问题
SpringBoot+Vue实现邮件发送与验证码验证

← 后端解决跨域问题 SpringBoot+Vue实现邮件发送与验证码验证→

Theme by Vdoing | Copyright © 2019-2025 程序员scholar
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式