SpringBoot web中过滤器Filter的使用方法

发布时间:2021-09-28 09:14:42 作者:柒染
来源:亿速云 阅读:194
# SpringBoot Web中过滤器Filter的使用方法

## 目录
- [一、过滤器(Filter)概述](#一过滤器filter概述)
  - [1.1 什么是过滤器](#11-什么是过滤器)
  - [1.2 过滤器与拦截器的区别](#12-过滤器与拦截器的区别)
  - [1.3 过滤器的应用场景](#13-过滤器的应用场景)
- [二、SpringBoot中Filter的实现方式](#二springboot中filter的实现方式)
  - [2.1 实现Filter接口](#21-实现filter接口)
  - [2.2 使用@WebFilter注解](#22-使用webfilter注解)
  - [2.3 通过FilterRegistrationBean注册](#23-通过filterregistrationbean注册)
- [三、Filter的生命周期与核心方法](#三filter的生命周期与核心方法)
  - [3.1 init()初始化方法](#31-init初始化方法)
  - [3.2 doFilter()过滤逻辑](#32-dofilter过滤逻辑)
  - [3.3 destroy()销毁方法](#33-destroy销毁方法)
- [四、Filter的配置详解](#四filter的配置详解)
  - [4.1 URL模式匹配](#41-url模式匹配)
  - [4.2 过滤器执行顺序](#42-过滤器执行顺序)
  - [4.3 初始化参数配置](#43-初始化参数配置)
- [五、实战案例](#五实战案例)
  - [5.1 请求日志记录过滤器](#51-请求日志记录过滤器)
  - [5.2 权限验证过滤器](#52-权限验证过滤器)
  - [5.3 XSS防护过滤器](#53-xss防护过滤器)
  - [5.4 跨域处理过滤器](#54-跨域处理过滤器)
- [六、高级应用](#六高级应用)
  - [6.1 过滤器链工作原理](#61-过滤器链工作原理)
  - [6.2 异步请求处理](#62-异步请求处理)
  - [6.3 异常处理机制](#63-异常处理机制)
- [七、常见问题与解决方案](#七常见问题与解决方案)
  - [7.1 过滤器不生效问题](#71-过滤器不生效问题)
  - [7.2 执行顺序问题](#72-执行顺序问题)
  - [7.3 性能优化建议](#73-性能优化建议)
- [八、总结与最佳实践](#八总结与最佳实践)

## 一、过滤器(Filter)概述

### 1.1 什么是过滤器

过滤器(Filter)是Java Web开发中的核心组件之一,它可以在请求到达Servlet之前或响应返回客户端之前对HTTP请求和响应进行预处理和后处理。在Spring Boot应用中,过滤器仍然扮演着重要角色,主要用于处理与业务逻辑无关的横切关注点。

过滤器的主要特点包括:
- 在请求到达Controller前进行预处理
- 在响应返回客户端前进行后处理
- 可以拦截多个请求,实现代码复用
- 通过配置可以灵活控制过滤范围

### 1.2 过滤器与拦截器的区别

| 特性         | 过滤器(Filter)                          | 拦截器(Interceptor)                   |
|--------------|----------------------------------------|---------------------------------------|
| 作用范围     | Servlet规范,任何Web框架可用           | Spring MVC特有                        |
| 执行时机     | 在DispatcherServlet之前                | 在DispatcherServlet之后,Controller之前|
| 依赖         | 依赖Servlet容器                        | 依赖Spring框架                        |
| 获取上下文   | 只能获取Servlet API对象                | 可以获取Spring上下文和业务对象        |
| 使用场景     | 字符编码、跨域处理、XSS防护等          | 权限验证、日志记录、参数预处理等      |

### 1.3 过滤器的应用场景

1. **安全相关**:XSS防护、CSRF防护、权限验证
2. **日志记录**:请求/响应日志、访问统计
3. **性能监控**:接口耗时统计、QPS监控
4. **编码处理**:统一字符编码设置
5. **跨域处理**:CORS跨域资源共享配置
6. **数据压缩**:响应内容GZIP压缩
7. **缓存控制**:HTTP缓存头设置

## 二、SpringBoot中Filter的实现方式

### 2.1 实现Filter接口

这是最基础的实现方式,创建一个类实现`javax.servlet.Filter`接口:

```java
import javax.servlet.*;
import java.io.IOException;

public class CustomFilter implements Filter {
    
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // 初始化逻辑
    }
    
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, 
                         FilterChain chain) throws IOException, ServletException {
        // 前置处理
        System.out.println("Before filter processing");
        
        // 放行请求
        chain.doFilter(request, response);
        
        // 后置处理
        System.out.println("After filter processing");
    }
    
    @Override
    public void destroy() {
        // 销毁逻辑
    }
}

2.2 使用@WebFilter注解

Spring Boot支持Servlet 3.0的@WebFilter注解,可以简化配置:

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

@WebFilter(urlPatterns = "/*", filterName = "customFilter")
public class CustomFilter implements Filter {
    // 实现方法同上
}

还需要在启动类添加@ServletComponentScan注解:

@SpringBootApplication
@ServletComponentScan
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

2.3 通过FilterRegistrationBean注册

这是Spring Boot推荐的方式,提供了更灵活的配置:

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class FilterConfig {
    
    @Bean
    public FilterRegistrationBean<CustomFilter> customFilterRegistration() {
        FilterRegistrationBean<CustomFilter> registration = 
            new FilterRegistrationBean<>();
        registration.setFilter(new CustomFilter());
        registration.addUrlPatterns("/*");
        registration.setOrder(1); // 设置执行顺序
        registration.setName("customFilter");
        return registration;
    }
}

三、Filter的生命周期与核心方法

3.1 init()初始化方法

init方法在过滤器实例创建后立即执行,用于初始化操作:

@Override
public void init(FilterConfig filterConfig) throws ServletException {
    // 获取初始化参数
    String param = filterConfig.getInitParameter("paramName");
    // 初始化资源
    this.someResource = initResource();
    log.info("Filter initialized with param: {}", param);
}

3.2 doFilter()过滤逻辑

doFilter是过滤器的核心方法,处理请求和响应:

@Override
public void doFilter(ServletRequest request, ServletResponse response, 
                     FilterChain chain) throws IOException, ServletException {
    // 1. 前置处理
    long startTime = System.currentTimeMillis();
    HttpServletRequest httpRequest = (HttpServletRequest) request;
    
    // 2. 业务逻辑处理
    if (shouldFilter(httpRequest)) {
        // 可以修改请求或响应
        CustomRequestWrapper wrappedRequest = new CustomRequestWrapper(httpRequest);
        // 继续过滤器链
        chain.doFilter(wrappedRequest, response);
    } else {
        chain.doFilter(request, response);
    }
    
    // 3. 后置处理
    long duration = System.currentTimeMillis() - startTime;
    log.info("Request {} processed in {} ms", httpRequest.getRequestURI(), duration);
}

3.3 destroy()销毁方法

destroy在Web应用关闭时调用,用于释放资源:

@Override
public void destroy() {
    // 释放资源
    if (this.someResource != null) {
        this.someResource.close();
    }
    log.info("Filter destroyed");
}

四、Filter的配置详解

4.1 URL模式匹配

Spring Boot支持多种URL匹配模式:

registration.addUrlPatterns(
    "/api/*",          // 匹配/api路径下的所有请求
    "*.html",          // 匹配所有html文件
    "/admin/**",       // 匹配/admin及其子路径
    "/public/resources/*.css" // 匹配特定资源
);

4.2 过滤器执行顺序

通过setOrder方法控制执行顺序,值越小优先级越高:

@Bean
public FilterRegistrationBean<FilterA> filterA() {
    FilterRegistrationBean<FilterA> reg = new FilterRegistrationBean<>();
    reg.setOrder(1); // 最先执行
    // ...
}

@Bean
public FilterRegistrationBean<FilterB> filterB() {
    FilterRegistrationBean<FilterB> reg = new FilterRegistrationBean<>();
    reg.setOrder(2); // 其次执行
    // ...
}

4.3 初始化参数配置

可以通过两种方式配置初始化参数:

  1. 注解方式:
@WebFilter(
    urlPatterns = "/*",
    initParams = {
        @WebInitParam(name = "param1", value = "value1"),
        @WebInitParam(name = "param2", value = "value2")
    }
)
  1. FilterRegistrationBean方式:
registration.addInitParameter("param1", "value1");
registration.addInitParameter("param2", "value2");

在Filter中通过FilterConfig获取:

String value = filterConfig.getInitParameter("param1");

五、实战案例

5.1 请求日志记录过滤器

public class RequestLoggingFilter implements Filter {
    private static final Logger log = LoggerFactory.getLogger(RequestLoggingFilter.class);

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, 
                         FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        
        // 记录请求信息
        String requestURI = httpRequest.getRequestURI();
        String method = httpRequest.getMethod();
        String queryString = httpRequest.getQueryString();
        String clientIP = httpRequest.getRemoteAddr();
        
        log.info("Request: {} {}?{}, IP: {}", method, requestURI, queryString, clientIP);
        
        long startTime = System.currentTimeMillis();
        chain.doFilter(request, response);
        long duration = System.currentTimeMillis() - startTime;
        
        log.info("Response: {} completed in {} ms", requestURI, duration);
    }
    
    // init和destroy方法省略
}

5.2 权限验证过滤器

public class AuthFilter implements Filter {
    private List<String> excludeUrls = Arrays.asList("/login", "/public/");
    
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, 
                         FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;
        
        String path = httpRequest.getRequestURI().substring(
            httpRequest.getContextPath().length());
        
        // 排除不需要验证的URL
        if (isExcluded(path)) {
            chain.doFilter(request, response);
            return;
        }
        
        // 检查认证信息
        String token = httpRequest.getHeader("Authorization");
        if (!validateToken(token)) {
            httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Invalid token");
            return;
        }
        
        chain.doFilter(request, response);
    }
    
    private boolean isExcluded(String path) {
        return excludeUrls.stream().anyMatch(path::startsWith);
    }
    
    private boolean validateToken(String token) {
        // 实现token验证逻辑
        return true;
    }
}

5.3 XSS防护过滤器

public class XssFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, 
                         FilterChain chain) throws IOException, ServletException {
        chain.doFilter(new XssRequestWrapper((HttpServletRequest) request), response);
    }
}

public class XssRequestWrapper extends HttpServletRequestWrapper {
    public XssRequestWrapper(HttpServletRequest request) {
        super(request);
    }
    
    @Override
    public String getParameter(String name) {
        return cleanXss(super.getParameter(name));
    }
    
    @Override
    public String[] getParameterValues(String name) {
        String[] values = super.getParameterValues(name);
        if (values == null) return null;
        return Arrays.stream(values).map(this::cleanXss).toArray(String[]::new);
    }
    
    private String cleanXss(String value) {
        if (value == null) return null;
        // 实现XSS清理逻辑
        return value.replaceAll("<", "&lt;").replaceAll(">", "&gt;");
    }
}

5.4 跨域处理过滤器

public class CorsFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, 
                         FilterChain chain) throws IOException, ServletException {
        HttpServletResponse httpResponse = (HttpServletResponse) response;
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        
        // 设置CORS头
        httpResponse.setHeader("Access-Control-Allow-Origin", "*");
        httpResponse.setHeader("Access-Control-Allow-Methods", 
            "GET, POST, PUT, DELETE, OPTIONS");
        httpResponse.setHeader("Access-Control-Max-Age", "3600");
        httpResponse.setHeader("Access-Control-Allow-Headers", 
            "Content-Type, Authorization, X-Requested-With");
        
        // 对OPTIONS请求直接返回
        if ("OPTIONS".equalsIgnoreCase(httpRequest.getMethod())) {
            httpResponse.setStatus(HttpServletResponse.SC_OK);
            return;
        }
        
        chain.doFilter(request, response);
    }
}

六、高级应用

6.1 过滤器链工作原理

Spring Boot中的过滤器链执行流程:

  1. 客户端发送请求到Servlet容器
  2. 容器创建过滤器链,按顺序执行过滤器
  3. 每个过滤器的doFilter方法被调用
  4. 最后一个过滤器调用chain.doFilter()进入Servlet
  5. Servlet处理请求并生成响应
  6. 响应沿过滤器链逆序返回
  7. 每个过滤器可以对响应进行后处理
  8. 最终响应返回客户端

6.2 异步请求处理

对于异步请求,需要特殊处理:

public class AsyncFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, 
                         FilterChain chain) throws IOException, ServletException {
        if (request.isAsyncSupported()) {
            request.setAttribute("ASYNC_SUPPORTED", true);
        }
        
        // 包装响应以支持异步
        AsyncResponseWrapper wrappedResponse = new AsyncResponseWrapper(
            (HttpServletResponse) response);
        
        try {
            chain.doFilter(request, wrappedResponse);
        } finally {
            if (!request.isAsyncStarted()) {
                wrappedResponse.finish();
            }
        }
    }
}

6.3 异常处理机制

过滤器中的异常处理策略:

public class ExceptionHandlingFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, 
                         FilterChain chain) throws IOException, ServletException {
        try {
            chain.doFilter(request, response);
        } catch (Exception e) {
            handleException((HttpServletRequest) request, 
                          (HttpServletResponse) response, e);
        }
    }
    
    private void handleException(HttpServletRequest request, 
                                HttpServletResponse response, 
                                Exception ex) throws IOException {
        // 根据异常类型返回不同的错误响应
        if (ex instanceof AuthenticationException) {
            response.sendError(HttpServletResponse.SC_UNAUTHORIZED, ex.getMessage());
        } else {
            response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, 
                             "Server error");
        }
    }
}

七、常见问题与解决方案

7.1 过滤器不生效问题

可能原因及解决方案

  1. 未正确注册

    • 确保使用@Component@WebFilter+@ServletComponentScan
    • 或通过FilterRegistrationBean显式注册
  2. URL模式不匹配

    • 检查urlPatterns是否包含目标路径
    • 使用/*测试是否匹配所有请求
  3. 顺序问题

    • 其他过滤器可能中断了过滤器链
    • 检查是否所有过滤器都调用了chain.doFilter()

7.2 执行顺序问题

控制执行顺序的方法

  1. 使用@Order注解:

    @Component
    @Order(1)
    public class FilterA implements Filter { ... }
    
  2. 使用FilterRegistrationBeansetOrder方法:

    registration.setOrder(Ordered.HIGHEST_PRECEDENCE);
    
  3. 实现Ordered接口:

    public class FilterB implements Filter, Ordered {
       @Override
       public int getOrder() { return 2; }
    }
    

7.3 性能优化建议

  1. 减少过滤器数量:合并功能相似的过滤器
  2. 避免复杂逻辑:将业务逻辑移到Service层
  3. 使用条件过滤
    
    if (!needsFiltering(request)) {
       chain.doFilter(request, response);
       return;
    }
    
  4. 异步处理:对于耗时操作考虑异步处理
  5. 资源缓存:在init中初始化资源,避免重复创建

八、总结与最佳实践

8.1 过滤器使用总结

  1. 适用场景

    • 处理与业务无关的横切关注点
    • 需要修改请求或响应的场景
    • 需要拦截所有请求的场景
  2. 实现方式对比

方式 优点 缺点
实现Filter接口 简单直接 配置不够灵活
@WebFilter注解 配置简洁 顺序控制有限
FilterRegistrationBean 高度可配置,功能强大 代码量稍多

8.2 最佳实践建议

  1. 单一职责原则:每个过滤器只处理一个特定功能
  2. 合理控制范围:精确配置url
推荐阅读:
  1. springboot 拦截器与servlet的过滤器
  2. springboot中过滤器和拦截器如何实现

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

springboot web

上一篇:css中order属性怎么用

下一篇:Vue2.x中如何实现双向绑定

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》