SpringBoot 拦截器(Interceptor)的使用

本文深入讲解了Spring MVC中拦截器Interceptor的使用方法,包括自定义拦截器的步骤、继承HandlerInterceptor及实现preHandle方法等内容,并提供了注册拦截器的具体示例。

拦截器intercprot  和 过滤器 Filter 其实作用类似

在最开始接触java 使用struts2的时候,里面都是filter

后来springmvc时就用interceptor

没太在意过区别,反正就是起检查作用的,

仔细阅读 过滤器(filter)和拦截器(interceptor)的区别 后明白了不少

最重要的要记住他们的执行顺序: 先filter 后 interceptor

过滤前-拦截前-action执行-拦截后-过滤后

 

在了解上面的信息后,本文讲interceptor的使用

自己定义的interceptor都需要继承HandlerInterceptor 并实现对应方法preHandle   postHandle来实现拦截功能

同时需要根据拦截规则进行注册

实例如下:

复制代码
package com.xiao.config;

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

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

import com.alibaba.fastjson.JSON;
import com.xiao.common.result.Error;
import com.xiao.common.result.Result;

@Configuration
public class InterceptorConfig extends WebMvcConfigurerAdapter {

@Bean
public InterfaceAuthCheckInterceptor getInterfaceAuthCheckInterceptor() {
    return new InterfaceAuthCheckInterceptor();
}

@Override
public void addInterceptors(InterceptorRegistry registry) {
    // 多个拦截器组成一个拦截器链
    // addPathPatterns 用于添加拦截规则
    // excludePathPatterns 用户排除拦截
    registry.addInterceptor(getInterfaceAuthCheckInterceptor()).addPathPatterns("/api/**");
    // registry.addInterceptor(new InterfaceAuthCheckInterceptor()).addPathPatterns("/api/**");
    // 如果interceptor中不注入redis或其他项目可以直接new,否则请使用上面这种方式
    super.addInterceptors(registry);
}


/**
 * 微服务间接口访问密钥验证
 * @author xiaochangwei
 *
 */
class InterfaceAuthCheckInterceptor implements HandlerInterceptor {

    private Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @Override
    public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
            throws Exception {

    }

    @Override
    public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
            throws Exception {

    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object obj)
            throws Exception {
        String key = request.getParameter("key");
        if (StringUtils.isEmpty(key)) {
            response.setContentType("application/json;charset=utf-8");
            response.getWriter().write(JSON.toJSONString(new Result(Error.INCOMPLETE_API_AUTHEN_INFO.getCode(), Error.INCOMPLETE_API_AUTHEN_INFO.getMessage())));
            return false;
        } else {
            logger.info("test redis import :" + stringRedisTemplate.opsForValue().get(key));
            // TODO 验证逻辑
            return true;
        }
    }

}

}

复制代码

其中要注意注册时的区别

registry.addInterceptor(getInterfaceAuthCheckInterceptor()).addPathPatterns("/api/**"); 这种方式无论什么情况都可以

registry.addInterceptor(new InterfaceAuthCheckInterceptor()).addPathPatterns("/api/**");这种情况时,自定义的interceptor中不能注入其他内容,比如redis或者其他service,如果要注入,必须使用上面这种方法
<think> 首先,用户的问题是:“我想了解Spring Boot拦截器Interceptor的执行顺序 请问Spring Boot拦截器Interceptor的执行顺序” 参考了几个引用: - 引用[1]:提到拦截器在请求处理前后执行逻辑,如日志、权限校验等。 - 引用[2]:解释了拦截器的执行流程,过滤器拦截器的区别,包括拦截范围不同。 - 引用[3]:提到拦截器用于AOP,执行如日志、权限检查等任务。 用户明确询问拦截器的执行顺序。我需要基于这些引用我的知识来回答。 回想拦截器Spring Boot中的执行顺序: - 拦截器实现`HandlerInterceptor`接口。 - 接口有三个关键方法: 1. `preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)`:在控制器方法执行前调用。返回true继续执行后续拦截器控制器,返回false则中断。 2. `postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)`:在控制器方法执行后、视图渲染前调用。 3. `afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)`:在请求完成后调用,无论是否有异常。 执行顺序: 1. 所有拦截器的`preHandle`方法按注册顺序执行。 2. 如果所有`preHandle`返回true,控制器方法执行。 3. 控制器方法执行后,所有拦截器的`postHandle`方法按注册顺序的逆序执行。 4. 最后,所有拦截器的`afterCompletion`方法按注册顺序的逆序执行。 注册顺序:在配置类中通过`addInterceptor()`添加拦截器时的顺序决定了它们的执行顺序。 从引用中提取有用信息: - 引用[2]提到:“拦截器的执行流程”,但没有详细说明顺序。它说:“通过执行流程分析,大家应该已经清楚了过滤器拦截器之间的区别”,但焦点在区别上。 - 我需要补充知识,确保回答真实可靠。 回答结构: 1. 解释拦截器的作用,基于引用。 2. 详细描述执行顺序。 3. 给出示例或伪代码。 4. 根据系统指令: - 使用中文回答。 - 行内数学表达式用$...$,但这里可能没有数学表达式。 - 独立公式用$$...$$,但同样可能不适用。 - 生成相关问题。 - 引用的段落末尾添加引用标识,如[^1]。 引用标识:我需要标明引用来源。用户提供了引用[1]、[2]、[3],所以我应该引用它们。 例如,在描述时,可以说:“根据引用[1],拦截器用于在请求处理前后执行特定逻辑如日志记录[^1]。” 回答结构清晰: - 先介绍拦截器。 - 然后解释执行顺序。 - 最后生成相关问题。 生成相关问题:在最后添加“§§相关问题§§”部分,列出3-5个相关问题。 完整回答大纲: 1. 介绍拦截器:简述是什么用途。 2. 执行顺序详细说明:分步解释preHandle, postHandle, afterCompletion的顺序。 3. 注册顺序的影响:如何控制顺序。 4. 示例:简单代码或伪代码展示。 5. 相关问题。 确保语言自然,使用中文。 最终回答格式: - 内容分段。 - 必要时添加代码块。 - 结尾添加相关问题。 </think> ### Spring Boot拦截器Interceptor的执行顺序 在Spring Boot中,拦截器Interceptor)是实现`HandlerInterceptor`接口的组件,用于在Web请求处理的不同阶段插入自定义逻辑,如日志记录、权限验证或性能监控[^1][^3]。拦截器的执行顺序由其在配置类中的注册顺序决定,主要包括三个阶段:`preHandle`、`postHandle``afterCompletion`。以下是详细的执行流程说明,基于核心概念实际实现原理。 #### 拦截器的执行顺序详解 拦截器的执行顺序分为以下步骤,每个步骤对应`HandlerInterceptor`接口的方法: 1. **`preHandle`方法(在控制器方法执行前调用)**: - 所有拦截器的`preHandle`方法按照注册顺序依次执行。 - 每个拦截器的`preHandle`方法返回一个布尔值:如果返回`true`,则继续执行后续拦截器或控制器;如果返回`false`,则中断整个请求处理链。 - 例如,如果有两个拦截器`InterceptorA``InterceptorB`注册在顺序中(先A后B),执行顺序为:`InterceptorA.preHandle()` → `InterceptorB.preHandle()`。 2. **控制器方法执行**: - 如果所有`preHandle`方法都返回`true`,Spring Boot会调用目标控制器(Controller)的请求处理方法。 - 这一阶段不涉及拦截器逻辑,但属于整体请求处理流程的一部分。 3. **`postHandle`方法(在控制器方法执行后、视图渲染前调用)**: - 控制器方法执行完成后,所有拦截器的`postHandle`方法按照注册顺序的**逆序**执行。 - 例如,对于注册顺序为`InterceptorA` → `InterceptorB`,执行顺序为:`InterceptorB.postHandle()` → `InterceptorA.postHandle()`。 - 此方法常用于处理模型数据或添加额外日志[^1][^3]。 4. **`afterCompletion`方法(在请求完成后调用,无论是否有异常)**: - 在请求处理结束(包括视图渲染完成或发生异常)后,所有拦截器的`afterCompletion`方法按照注册顺序的**逆序**执行。 - 同样,以`InterceptorA``InterceptorB`为例,执行顺序为:`InterceptorB.afterCompletion()` → `InterceptorA.afterCompletion()`。 - 此阶段适合执行资源清理或最终日志记录[^1][^2]。 #### 注册顺序如何影响执行 在Spring Boot配置类中,你需要通过`WebMvcConfigurer`的`addInterceptor()`方法注册拦截器拦截器的注册顺序直接决定了`preHandle`的顺序`postHandle`/`afterCompletion`的逆序。以下是一个简单的代码示例: ```java @Configuration public class WebConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { // 注册拦截器,顺序决定了执行优先级 registry.addInterceptor(new LoggingInterceptor()).order(1); // 先注册,preHandle先执行 registry.addInterceptor(new AuthInterceptor()).order(2); // 后注册,preHandle后执行 } } // 自定义拦截器示例 public class LoggingInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { System.out.println("LoggingInterceptor: preHandle"); return true; // 继续执行 } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) { System.out.println("LoggingInterceptor: postHandle"); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { System.out.println("LoggingInterceptor: afterCompletion"); } } // 另一个拦截器 public class AuthInterceptor implements HandlerInterceptor { // 类似实现... } ``` 执行输出示例: - `preHandle`顺序:LoggingInterceptor → AuthInterceptor - `postHandle``afterCompletion`逆序:AuthInterceptor → LoggingInterceptor #### 关键区别与注意事项 - **与过滤器的区别**:拦截器只拦截Spring环境中的资源(如Controller请求),而过滤器(Filter)会拦截所有Servlet请求,包括静态资源[^2]。拦截器的执行顺序更精细,更适合Spring Boot的上下文管理。 - **中断逻辑**:如果某拦截器的`preHandle`返回`false`,后续拦截器控制器不会执行,但已执行的拦截器的`afterCompletion`方法仍会调用以清理资源[^1]。 - **性能影响**:多个拦截器可能增加请求延迟,建议逻辑简单以避免瓶颈[^3]。 通过合理配置注册顺序,你可以灵活控制拦截器链,实现如先验证权限后记录日志的流水线处理[^1][^3]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值