Spring Boot拦截器(Interceptor)与过滤器(Filter)详细教程

蹦跑的蜗牛 2025-03-03 10:37:54编程技术
348

在Spring Boot应用中,拦截器(Interceptor)和过滤器(Filter)是两种常用的组件,用于处理请求和响应的生命周期。拦截器主要用于处理控制器(Controller)之前或之后的逻辑,而过滤器则用于处理请求和响应的预处理和后处理。理解和掌握拦截器和过滤器的使用方法,对于构建高效、安全的Web应用至关重要。本文将详细介绍Spring Boot中的拦截器和过滤器的原理、配置和应用场景,帮助读者更好地使用这两个组件。

1. 概述

1.1 什么是拦截器(Interceptor)?

拦截器是 Spring MVC 框架的组件,基于 AOP(面向切面编程) 实现。它允许在请求处理的不同阶段(如Controller方法执行前后)插入自定义逻辑。

1.2 什么是过滤器(Filter)?

过滤器是 Java Servlet规范 定义的组件,作用于所有进入容器的请求(如Tomcat)。它可以在请求到达Servlet前或响应返回客户端前进行预处理和后处理。

1.3 核心区别

特性 拦截器(Interceptor) 过滤器(Filter)
所属框架 Spring MVC Servlet API
作用范围 仅Spring MVC管理的请求 所有请求(包括静态资源)
依赖 依赖Spring容器 依赖Servlet容器(如Tomcat)
执行时机 Controller方法前后 Servlet处理前后
获取Bean 支持(通过Spring上下文) 不支持(需通过其他方式注入)

2. 使用场景

2.1 拦截器的典型应用

  • 日志记录:记录请求参数、响应时间。

  • 权限验证:检查用户是否登录或拥有权限。

  • 事务管理:在Controller方法前后开启/提交事务。

  • 性能监控:统计接口耗时。

2.2 过滤器的典型应用

  • 全局字符编码:统一设置请求/响应的编码(如UTF-8)。

  • 跨域处理:添加CORS响应头。

  • XSS防御:过滤请求参数中的恶意脚本。

  • 请求压缩:对响应内容进行GZIP压缩。

3. 实现步骤

3.1 创建拦截器

步骤:

  1. 实现 HandlerInterceptor 接口,重写以下方法:

    • preHandle():在Controller方法执行前调用。

    • postHandle():在Controller方法执行后、视图渲染前调用。

    • afterCompletion():在请求完成后调用(视图渲染后)。

  2. 注册拦截器到Spring MVC配置。

代码示例:

public class AuthInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        // 检查用户是否登录
        if (request.getSession().getAttribute("user") == null) {
            response.sendRedirect("/login");
            return false; // 中断请求
        }
        return true;
    }
}

注册拦截器:

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new AuthInterceptor())
                .addPathPatterns("/**")
                .excludePathPatterns("/login", "/static/**");
    }
}

注册多个拦截器:

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 第一个拦截器:日志(优先级高)
        registry.addInterceptor(new LogInterceptor())
                .addPathPatterns("/**")       // 拦截所有路径
                .excludePathPatterns("/static/**"); // 排除静态资源

        // 第二个拦截器:权限(优先级低)
        registry.addInterceptor(new AuthInterceptor())
                .addPathPatterns("/api/**");  // 仅拦截/api路径
    }
}

关键配置选项

配置方法 说明
addPathPatterns("/api") 指定拦截的路径(支持Ant风格)
excludePathPatterns("/login") 排除特定路径
order(1) 显式设置顺序(默认按注册顺序)

若要手动指定顺序,可添加:

registry.addInterceptor(new LogInterceptor()).order(1);
registry.addInterceptor(new AuthInterceptor()).order(2);

3.2 创建过滤器

步骤:

  1. 实现 javax.servlet.Filter 接口,重写 doFilter 方法。

  2. 注册过滤器到Servlet容器(通过注解或配置类)。

代码示例:

@WebFilter(urlPatterns = "/*")
public class LoggingFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 
            throws IOException, ServletException {
        System.out.println("请求开始: " + ((HttpServletRequest) request).getRequestURI());
        chain.doFilter(request, response); // 继续执行后续过滤器或Servlet
        System.out.println("请求结束");
    }
}

注册过滤器(若未使用@WebFilter):

@Configuration
public class FilterConfig {
    @Bean
    public FilterRegistrationBean<LoggingFilter> loggingFilter() {
        FilterRegistrationBean<LoggingFilter> bean = new FilterRegistrationBean<>();
        bean.setFilter(new LoggingFilter());
        bean.addUrlPatterns("/*");
        bean.setOrder(1); // 设置执行顺序
        return bean;
    }
}

注意: 确保主类添加 @ServletComponentScan 以启用 @WebFilter 注解。

4. 执行顺序与流程

4.1 执行顺序

  1. 过滤器(FilterChain) → 2. 拦截器(preHandle) → 3. Controller方法 → 4. 拦截器(postHandle) → 5. 视图渲染 → 6. 拦截器(afterCompletion) → 7. 过滤器后续处理

4.2 流程图

客户端 → Filter.doFilter() → Interceptor.preHandle()
       → Controller → Interceptor.postHandle()
       → 视图渲染 → Interceptor.afterCompletion()
       → Filter.doFilter()后续处理 → 客户端

5. 常见问题与解决方案

Q1:如何控制多个拦截器/过滤器的执行顺序?

  • 拦截器:通过 registry.addInterceptor() 的顺序决定。

  • 过滤器:通过 FilterRegistrationBean.setOrder() 设置优先级(值越小越先执行)。

Q2:拦截器中如何获取Spring管理的Bean?

直接从Spring容器注入:

public class AuthInterceptor implements HandlerInterceptor {
    @Autowired
    private UserService userService; // 直接注入
}

Q3:过滤器中如何修改请求参数?

通过自定义 HttpServletRequestWrapper:

public class ModifyRequestWrapper extends HttpServletRequestWrapper {
    // 重写getParameter等方法以修改参数
}

// 在Filter中替换Request对象
chain.doFilter(new ModifyRequestWrapper(request), response);

Q4:拦截器和过滤器执行时出现异常如何处理?

  • 拦截器:在 afterCompletion 中处理异常。

  • 过滤器:使用 try-catch 包裹 chain.doFilter()。

Q5:如何让某个拦截器全局生效?

使用 addPathPatterns("/**"):

registry.addInterceptor(new LogInterceptor())
        .addPathPatterns("/**");

Q6:如何跳过特定拦截器的执行?

在 preHandle 中返回 false:

@Override
public boolean preHandle(...) {
    if (跳过条件) {
        return false; // 后续拦截器和Controller不会执行
    }
    return true;
}

Q7:拦截器之间如何共享数据?

通过 request.setAttribute 传递:

// 在第一个拦截器中存储数据
request.setAttribute("key", "value");

// 在后续拦截器中获取
String value = (String) request.getAttribute("key");

6. 总结

  • 选择拦截器还是过滤器?

    • 需要访问Spring上下文或Controller信息 → 拦截器。

    • 需处理所有请求(包括静态资源) → 过滤器。

  • 最佳实践

    • 优先使用拦截器处理业务相关逻辑。

    • 使用过滤器处理底层Servlet容器的任务(如编码、压缩)。

本文详细介绍了Spring Boot中的拦截器和过滤器的原理、配置和应用场景。通过本文的学习,读者不仅掌握了拦截器和过滤器的基本概念和使用方法,还学会了如何在实际项目中应用这两个组件,提升Web应用的性能和安全性。希望本文的内容对你有所帮助,期待你在实际项目中应用这些知识,创造出更加优秀的Spring Boot应用。

Spring Boot 拦截器 Interceptor 过滤器 Filter
THE END
蜜芽
故事不长,也不难讲,四字概括,毫无意义。

相关推荐

SpringBoot整合EasyExcel实现文件导入导出示例代码详解
Spring Boot作为一种流行的微服务框架,结合EasyExcel这一高性能的Excel处理库,可以实现快速、便捷的文件导入导出功能。本文将通过详细的示例代码,深入解析如何在Spring Bo...
2025-05-21 编程技术
670

Spring Boot中@RequestMapping、@PostMapping、@GetMapping的使用方法及区别详解
在Spring Boot框架中,@RequestMapping、@PostMapping和@GetMapping是处理HTTP请求的核心注解。它们用于定义控制器(Controller)中方法的映射规则,明确不同HTTP请求与后端逻...
2025-05-08 编程技术
741

EXCEL中FILTER函数的使用方法及实例详解
在Excel的数据处理与分析领域,FILTER函数是一个强大且实用的工具。它能够根据特定条件从数据集中筛选出符合要求的数据,极大地提高了数据处理的效率和准确性。本文ZHANID工具...
2025-04-20 电脑知识
814

快速理解Spring 和 Spring Boot 的核心区别
在Java开发领域,Spring和Spring Boot是两个非常流行的框架。它们都旨在简化企业级应用的开发过程,但各自有着不同的设计理念和应用场景。对于初学者来说,理解Spring和Sprin...
2025-02-28 编程技术
424

Spring Boot中GET请求和POST请求接收参数的详细示例解析
Spring Boot因其简洁性和高效性而广受欢迎。处理HTTP请求是Web应用的核心功能之一,其中GET和POST请求是最常用的两种类型。了解如何在Spring Boot中正确接收和处理这两种请求...
2025-01-01 编程技术
564

JS中filter()方法的使用示例代码详解
在JavaScript中,filter()方法是一个非常强大且常用的数组方法。它允许你创建一个新数组,该数组的元素是通过检查指定数组中符合条件的所有元素。简言之,filter()方法用于筛...
2024-12-17 编程技术
691