溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

SpringBoot web中過濾器Filter的使用方法

發布時間:2021-09-28 09:14:42 來源:億速云 閱讀:206 作者:柒染 欄目:大數據
# 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獲?。?/p>

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
向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女