知識庫 / Spring / Spring MVC RSS 訂閱

Spring Web 應用中排除 URL 的過濾器

Spring MVC
HongKong
4
01:09 PM · Dec 06 ,2025

1. 概述

大多數 Web 應用程序都有執行諸如請求日誌記錄、驗證或身份驗證等操作的需求。更重要的是,這些 任務通常在 HTTP 端點的一組中共享

好消息是,Spring Web 框架提供了一個 過濾機制,正是為了解決這個問題。

在本教程中,我們將學習如何為一組 URL 指定是否包含或排除 過濾器風格的任務的執行。

2. 過濾特定 URL

假設我們的 Web 應用程序需要記錄有關其請求的信息,例如它們的路徑和內容類型。一種方法是創建日誌過濾功能。

2.1. 日誌過濾器

首先,讓我們在 <em >LogFilter</em> 類中創建我們的日誌過濾器,該類繼承了 <em >OncePerRequestFilter</em> 類,並實現了 <em >doFilterInternal</em> 方法:

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
  FilterChain filterChain) throws ServletException, IOException {
    String path = request.getRequestURI();
    String contentType = request.getContentType();
    logger.info("Request URL path : {}, Request content type: {}", path, contentType);
    filterChain.doFilter(request, response);
}

2.1. 規則過濾器

假設我們需要確保日誌任務僅在特定 URL 模式下執行,即 /health</em/> 和 /faq/*.</em/>。為此,我們將使用 FilterRegistrationBean</em/> 註冊我們的日誌過濾器,使其僅匹配所需 URL 模式。

@Bean
public FilterRegistrationBean<LogFilter> logFilter() {
    FilterRegistrationBean<LogFilter> registrationBean = new FilterRegistrationBean<>();
    registrationBean.setFilter(new LogFilter());
    registrationBean.addUrlPatterns("/health","/faq/*");
    return registrationBean;
}

2.2 排除過濾器

如果我們要排除URL在執行日誌任務時被執行,可以通過以下兩種方式輕鬆實現:

  1. 對於新的URL,請確保它不匹配過濾器使用的URL模式。
  2. 對於之前已啓用日誌記錄的舊URL,可以修改URL模式以排除該URL。

3. 篩選所有可能的 URL

我們輕鬆地滿足了在 LogFilter 中包含 URL 的先前用例,並且只需極小的努力。然而,如果 Filter 使用通配符 (*) 來匹配所有可能的 URL 模式,情況就會變得 複雜

在這種情況下,我們需要自己編寫包含和排除邏輯。

3.1. 自定義過濾器

客户端可以通過請求頭向服務器發送有用的信息。 假設我們的 Web 應用程序目前僅在美國運行,這意味着我們不想處理來自其他國家/地區的請求。

假設我們的 Web 應用程序通過 X-Country-Code 請求頭指示區域。 因此,每個請求都包含此信息,這為使用過濾器提供了明確的理由。

讓我們實現一個 過濾器,該過濾器檢查請求頭,並拒絕不符合我們條件的請求:

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
      FilterChain filterChain) throws ServletException, IOException {

    String countryCode = request.getHeader("X-Country-Code");
    if (!"US".equals(countryCode)) {
        response.sendError(HttpStatus.BAD_REQUEST.value(), "Invalid Locale");
        return;
    }

    filterChain.doFilter(request, response);
}

3.2. 過濾器註冊

首先,我們使用星號 (*)通配符來註冊我們的過濾器,以匹配所有可能的 URL 模式:

@Bean
public FilterRegistrationBean<HeaderValidatorFilter> headerValidatorFilter() {
    FilterRegistrationBean<HeaderValidatorFilter> registrationBean = new FilterRegistrationBean<>();
    registrationBean.setFilter(new HeaderValidatorFilter());
    registrationBean.addUrlPatterns("*");
    return registrationBean;
}

稍後,我們可以排除不必要的 URL 模式,從而避免對驗證區域請求頭信息的任務造成不必要的負擔。

4. URL 排除

在本節中,我們將學習如何為我們的客户 過濾器 排除 URL。

4.1. 樸素策略

假設我們仍然有一個位於 /health 的 Web 路由,用於對應用程序進行乒乓健康檢查。

此前,所有請求都會觸發我們的過濾器。正如我們可以猜測的,這在健康檢查方面會帶來額外的開銷。

因此,為了簡化 /health 請求,我們將它們排除在主過濾器的作用範圍內:

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
  FilterChain filterChain) throws ServletException, IOException {
    String path = request.getRequestURI();
    if ("/health".equals(path)) {
    	filterChain.doFilter(request, response);
    	return;
    }

    String countryCode = request.getHeader("X-Country-Code");
    // ... same as before
}

需要注意的是,在 doFilter 方法中添加這種自定義邏輯會使 /health 端點和我們的過濾器之間產生耦合。因此,這並不是最佳實踐,因為如果我們在不修改 doFilter 方法內部的代碼的情況下更改健康檢查端點,我們可能會破壞過濾邏輯。

4.2. 使用 shouldNotFilter 方法

採用前述方法,URL 排除與任務執行邏輯之間存在緊耦合,導致過濾器中可能意外引入錯誤,即使只是為了修改其中一個部分。

相反,我們可以通過重寫 <a href="https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/filter/OncePerRequestFilter.html#shouldNotFilter-javax.servlet.http.HttpServletRequest-">shouldNotFilter` 方法來隔離這兩種邏輯:

@Override
protected boolean shouldNotFilter(HttpServletRequest request)
  throws ServletException {
    String path = request.getRequestURI();
    return "/health".equals(path);
}

因此,doInternalFilter() 方法遵循 單一職責原則:

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
  FilterChain filterChain) throws ServletException, IOException {
    String countryCode = request.getHeader("X-Country-Code");
    // ... same as before
}

5. 結論

在本教程中,我們探討了如何在 Spring Boot Web 應用程序的 Servlet 過濾器中排除 URL 模式(模式)的方法,用於兩個用例:日誌記錄和請求頭驗證。

此外,我們瞭解到,對於使用通配符匹配所有可能 URL 模式的過濾器,排除特定的 URL 集合可能會變得複雜。

user avatar
0 位用戶收藏了這個故事!
收藏

發佈 評論

Some HTML is okay.