【Spring Boot 拦截器介绍】

一、Spring Boot 拦截器是什么?

拦截器允许开发者在处理 HTTP 请求的生命周期的不同阶段—即请求处理之前、之后以及请求完成后—执行特定的操作。这些操作可以包括日志记录、身份验证、权限检查、事务管理等。

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

理解拦截器之前,有必要区分两个经常被混用的概念:拦截器(Interceptor)和过滤器(Filter)。

过滤器(Filter)

过滤器是 Java Servlet 规范的一部分,它在 Servlet 层面上提供了一种方式来处理请求和响应。过滤器可以对几乎所有的请求进行拦截,因为它们工作在请求的前端(在请求达到控制器之前)和后端(在响应被发送回客户端之前)。过滤器主要用于请求的预处理、响应的后处理,以及请求链中的请求/响应转换。

拦截器(Interceptor)

与过滤器相比,拦截器是 Spring MVC 提供的,它提供了更精细的控制。拦截器仅作用于处理器映射到的方法。这意味着,它们可以访问控制器执行的上下文,包括执行的控制器本身和控制器方法的元数据。拦截器可以在以下三个阶段执行操作:

  • preHandle:在 Controller 方法调用之前执行。可以进行身份验证、权限检查等操作,并决定是否中断执行链,即是否将请求传递给控制器处理。
  • postHandle:在 Controller 方法调用之后,但在视图被渲染之前执行。可以对模型数据进行操作或对视图进行处理。
  • afterCompletion:在整个请求结束后执行,即在视图渲染完毕后。这里可以进行资源清理等操作。

拦截器提供了一种更为灵活和强大的方式来插入跨越请求处理生命周期的逻辑。相比之下,过滤器更适合处理如请求日志记录、请求和响应的通用处理(比如设置响应头)等跨应用程序的共通行为。

二、Spring Boot 拦截器的使用场景

身份验证和授权

身份验证和授权是几乎每个应用必须处理的关键安全问题。通过拦截器,在请求到达目标控制器之前,可以检查用户的认证状态和权限。如果用户未经认证或缺乏访问特定资源的权限,拦截器可以阻止请求继续处理并直接返回一个错误响应或重定向到登录页面。这样的处理确保了应用的安全性,同时保持了控制器逻辑的清晰和专注。

日志记录

日志记录是开发和维护过程中的一个重要方面,它帮助开发者了解应用的运行状态,以及在出现问题时进行调试。通过拦截器,可以在请求处理的前后记录下请求路径、请求参数、用户身份等详细信息。这不仅有助于监控应用的健康状况,也为故障排查和性能分析提供了宝贵信息。

性能监测

在性能敏感的应用中,监测和优化请求的处理时间是提高用户体验的关键。拦截器可以用于监控请求的处理时间,通过记录请求开始和完成的时间,可以计算出处理每个请求所需的时间。这些数据可以用于识别性能瓶颈,指导后续的优化工作。

通用行为的应用

在多个控制器或请求处理流程中需要应用的通用行为,如跨域资源共享(CORS)设置、语言偏好处理、时区信息设置等,都可以通过拦截器以统一和非侵入式的方式实现。例如可以在拦截器中统一处理跨域请求的头信息,或根据请求头或参数调整语言和时区设置,从而提高代码的复用性和维护性。

三、如何实现 Spring Boot 拦截器

1. 创建拦截器类

首先需要定义一个类实现 HandlerInterceptor 接口或继承 HandlerInterceptorAdapter 类。这个接口定义了三个方法:preHandlepostHandleafterCompletion,分别对应于请求处理的前、中、后三个阶段。

  • preHandle:在请求处理之前进行调用(Controller方法调用之前)。这里可以进行权限验证、日志记录等操作。如果返回值为false,Spring MVC将不会继续处理这个请求。
  • postHandle:在请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后)。可以通过这个方法对模型数据进行处理或对视图进行处理。
  • afterCompletion:在整个请求结束之后被调用,也就是在DispatcherServlet渲染了对应的视图之后执行(主要用于进行资源清理工作)。
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 {
        // 在Controller执行之前调用
        // 这里可以进行权限验证、日志记录等
        return true; // 返回true则继续执行下一个拦截器或处理器
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        // 在Controller执行之后调用,但在视图渲染之前
        // 这里可以对模型数据进行处理或对视图进行处理
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // 在请求完全结束后调用,可用于清理资源等
    }
}

2. 注册拦截器

创建拦截器类之后,需要将其注册到 Spring MVC 的拦截器链中以启用其功能。可以通过实现 WebMvcConfigurer 接口并重写 addInterceptors 方法来完成。

WebMvcConfigurer 中可以定义拦截器的应用规则,比如指定拦截器应该拦截哪些URL路径。通过调用 InterceptorRegistryaddInterceptor 方法,并通过 addPathPatterns 方法来指定路径模式,可以非常灵活地配置拦截器的应用范围。

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 MyInterceptor myInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 注册拦截器,并指定拦截的路径
        registry.addInterceptor(myInterceptor).addPathPatterns("/**");
        // 你也可以通过addPathPatterns添加多个匹配模式,或通过excludePathPatterns排除某些模式
    }
}

四、高级配置

1. 拦截器链

在 Spring Boot 应用中,可以通过配置多个拦截器来形成一个拦截器链。Spring MVC 会按照拦截器注册的顺序依次调用这些拦截器,执行它们的 preHandlepostHandleafterCompletion 方法。

配置拦截器链

WebMvcConfigurer 的实现类中,可以通过调用 addInterceptors 方法多次添加多个拦截器,从而形成一个链。每个拦截器可以定义自己的拦截路径模式,也可以有共同的路径模式。

@Override
public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(new FirstInterceptor()).addPathPatterns("/**");
    registry.addInterceptor(new SecondInterceptor()).addPathPatterns("/api/**");
}

这个例子中,所有请求都会被 FirstInterceptor 拦截,而只有 /api/** 路径的请求会被 SecondInterceptor 拦截。

2. 动态拦截器

动态拦截器允许开发者根据请求的动态信息,如 URL、Header 等,来决定是否执行拦截器。可以通过在 preHandle 方法中添加逻辑来实现。

实现动态拦截

public class DynamicInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 根据请求的 URL 或 Header 决定是否进行拦截
        String headerValue = request.getHeader("X-Intercept");
        if ("true".equals(headerValue)) {
            // 执行某些操作
            return true; // 继续执行拦截器链
        } else {
            // 跳过当前拦截器,不对请求进行处理
            return false; // 中断执行,这将阻止控制器方法的执行
        }
    }
}

这个例子中,拦截器会检查请求头 X-Intercept 的值,根据这个值来决定是否进行后续操作。

3. 异常处理

在拦截器中处理异常

拦截器本身并不直接处理异常。相反,应当将异常信息传递给 Spring MVC 的异常处理机制。

@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    if (ex != null) {
        // 记录异常信息,或者使用其他方式处理异常
        // 例如,可以将异常信息包装后抛出自定义异常
        throw new CustomException("Interceptor error", ex);
    }
}

在这个例子中,如果 afterCompletion 方法接收到异常,它会记录异常信息或抛出自定义异常。应用中应该有全局异常处理器(如使用 @ControllerAdvice 注解的类)来进一步处理这些异常,例如返回一个友好的错误响应给用户。

Spring Boot中,可以使用拦截器来对请求进行拦截和处理。拦截器是一种AOP(面向切面编程)的技术,在请求到达控制器之前或之后对请求进行处理。拦截器可以用于实现一些通用的功能,如日志记录、权限验证、参数校验等。 在Spring Boot中定义拦截器需要以下步骤: 1. 创建一个拦截器类,该类需要实现HandlerInterceptor接口。可以在拦截器中重写preHandle、postHandle和afterCompletion等方法来实现请求的前置处理、后置处理和完成处理。 2. 创建一个拦截器配置类,该类需要实现WebMvcConfigurer接口,并重写addInterceptors方法。在该方法中,可以注册拦截器类,并为其定义拦截规则。 在配置类中,可以通过使用addPathPatterns方法来定义需要拦截的请求路径,也可以使用excludePathPatterns方法来排除某些请求路径不被拦截。 拦截器与过滤器在功能和使用上有一些区别: 1. 归属不同:过滤器属于Servlet技术,而拦截器属于SpringMVC技术。 2. 内容不同:过滤器对所有访问进行增强,而拦截器仅针对SpringMVC的访问进行增强。 通过上述步骤定义和配置拦截器,可以在Spring Boot应用中实现对请求的拦截和处理。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [Spring-Boot 拦截器](https://blog.csdn.net/PeterMrWang/article/details/123916751)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [Springboot——拦截器](https://blog.csdn.net/weixin_51351637/article/details/128058053)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

武帝为此

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值