最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

OncePerRequestFilter和GenericFilterBean的區(qū)別及說明

 更新時間:2025年11月06日 15:23:33   作者:@zcc@  
文章對比了Spring中的GenericFilterBean和OncePerRequestFilter過濾器,指出OncePerRequestFilter提供了更嚴格的單次執(zhí)行保證,適用于認證、鑒權等場景

OncePerRequestFilter和GenericFilterBean過濾器的區(qū)別

1. 繼承關系與核心功能

GenericFilterBean

  • 是 Spring 對 javax.servlet.Filter 接口的實現(xiàn),提供基礎功能(如初始化、銷毀方法的默認實現(xiàn))。
  • 需要開發(fā)者手動控制過濾邏輯的執(zhí)行次數(shù),無法自動確保每個請求只執(zhí)行一次
  • 適用于需要靈活控制執(zhí)行次數(shù)的場景(如多次記錄日志或動態(tài)處理請求)。

OncePerRequestFilter

  • 繼承自 GenericFilterBean核心功能是確保每個 HTTP 請求的過濾邏輯僅執(zhí)行一次。
  • 內部通過檢查請求屬性(如 javax.servlet._FILTERED)或 ThreadLocal 來跟蹤請求是否已處理過。
  • 適用于需要嚴格保證單次執(zhí)行的場景(如認證、鑒權、流量控制等)。

2. 執(zhí)行邏輯的區(qū)別

特性GenericFilterBeanOncePerRequestFilter
執(zhí)行次數(shù)控制需手動確保邏輯不重復執(zhí)行(如請求轉發(fā)時可能多次觸發(fā))。自動確保每個請求僅執(zhí)行一次,即使請求被轉發(fā)或異步處理。
適用場景需要多次執(zhí)行的邏輯(如日志記錄、動態(tài)參數(shù)處理)。需要單次執(zhí)行的邏輯(如認證、安全校驗)。
需重寫的方法doFilterdoFilterInternal
依賴Servlet API直接使用Servlet原生方法。內部封裝了Servlet邏輯,簡化重復執(zhí)行的檢查。

3. 使用場景對比

選擇 GenericFilterBean 的場景

  • 需要對請求進行多次攔截(如每個轉發(fā)點都需要記錄日志)。
  • 需要細粒度控制過濾邏輯的執(zhí)行時機(如根據(jù)請求路徑動態(tài)處理)。
  • 示例:請求頭的動態(tài)修改、跨域預檢(OPTIONS 請求)的多次處理。

選擇 OncePerRequestFilter 的場景

  • 需要確保邏輯僅執(zhí)行一次(如身份驗證、設置請求上下文)。
  • 避免資源重復消耗(如數(shù)據(jù)庫連接、令牌生成)。
  • 示例:JWT 認證、Trace ID 的一次設置。

如何使用?

1. GenericFilterBean 的使用

步驟

  1. 繼承 GenericFilterBean。
  2. 重寫 doFilter 方法,實現(xiàn)自定義邏輯。
  3. 在 Spring 配置中注冊過濾器(如 WebMvcConfigurer@Bean)。

示例代碼:記錄每次請求的 URL 和耗時(可能多次觸發(fā)):

import org.springframework.web.filter.GenericFilterBean;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebFilter("/*") // 配置過濾路徑
public class LoggingFilter extends GenericFilterBean {
    @Override
    public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        //請求響應前
        long startTime = System.currentTimeMillis();
        System.out.println("Request Start: " + request.getRequestURI());
        
        chain.doFilter(request, response); // 繼續(xù)處理
        //請求響應后
        long endTime = System.currentTimeMillis();
        System.out.println("Request End: " + request.getRequestURI() + ", Time: " + (endTime - startTime) + "ms");
    }
}

2. OncePerRequestFilter 的使用

步驟

  1. 繼承 OncePerRequestFilter。
  2. 重寫 doFilterInternal 方法,實現(xiàn)單次執(zhí)行的邏輯。
  3. 在 Spring 配置中注冊過濾器。

示例代碼:設置請求頭(僅執(zhí)行一次):

import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class HeaderFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
            throws ServletException, IOException {
        //請求響應前
        long startTime = System.currentTimeMillis();
        System.out.println("Request Start: " + request.getRequestURI());
       
        // 設置請求頭,僅執(zhí)行一次
        response.setHeader("X-Custom-Header", "Spring-Once");
        
        // 必須調用 chain.doFilter(),否則請求無法繼續(xù)
        chain.doFilter(request, response);
        //請求響應后
        long endTime = System.currentTimeMillis();
        System.out.println("Request End: " + request.getRequestURI() + ", Time: " + (endTime - startTime) + "ms");

    }
}

關鍵區(qū)別總結

場景GenericFilterBeanOncePerRequestFilter
執(zhí)行次數(shù)可能多次(需手動控制)嚴格一次(自動控制)
適用邏輯日志記錄、動態(tài)參數(shù)處理認證、鑒權、Trace ID 設置
核心方法doFilterdoFilterInternal
是否依賴請求屬性無自動跟蹤通過請求屬性或 ThreadLocal 跟蹤

舉例說明

示例 1:日志記錄(GenericFilterBean)

假設需要在每次請求的每個階段(如轉發(fā)前、轉發(fā)后)記錄日志,此時使用 GenericFilterBean

@Component
@Order(2) // 可以定執(zhí)行順序,數(shù)字越小優(yōu)先級越高
public class MultiLogFilter extends GenericFilterBean {
    @Override
    public void doFilter(HttpServletRequest req, HttpServletResponse res, FilterChain chain) {
        System.out.println("Log: " + req.getRequestURI() + " - Stage 1");
        chain.doFilter(req, res); // 繼續(xù)處理,可能觸發(fā)多次
        System.out.println("Log: " + req.getRequestURI() + " - Stage 2");
    }
}

結果:如果請求被轉發(fā)多次,日志會重復記錄。

示例 2:認證過濾器(OncePerRequestFilter)

確保身份驗證邏輯僅執(zhí)行一次:

@Component
@Order(2) // 可以定執(zhí)行順序,數(shù)字越小優(yōu)先級越高
public class AuthFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain chain) {
        // 檢查 Token,僅執(zhí)行一次
        String token = req.getHeader("Authorization");
        if (token == null) {
            res.sendError(401, "Unauthorized");
            return;
        }
        chain.doFilter(req, res);
    }
}

結果:即使請求被轉發(fā),認證邏輯僅執(zhí)行一次。

總結

  • 選 GenericFilterBean:當需要靈活控制執(zhí)行次數(shù)或允許重復操作時。
  • 選 OncePerRequestFilter:當需要嚴格保證邏輯僅執(zhí)行一次時。
  • 關鍵方法doFilter(Generic) vs doFilterInternal(OncePer)。
  • 典型場景:日志(Generic) vs 認證(OncePer)。

以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關文章

  • Jmeter參數(shù)化獲取序列數(shù)據(jù)實現(xiàn)過程

    Jmeter參數(shù)化獲取序列數(shù)據(jù)實現(xiàn)過程

    這篇文章主要介紹了Jmeter參數(shù)化獲取序列數(shù)據(jù)實現(xiàn)過程,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-07-07
  • Springboot中的@ConditionalOnBean注解使用指南與最佳實踐(工作原理)

    Springboot中的@ConditionalOnBean注解使用指南與最佳實踐(工作原理)

    在使用Spring Boot進行開發(fā)時,大家應該都聽說過條件注解Conditional Annotations,下面給大家聊聊Springboot中的@ConditionalOnBean注解使用指南與最佳實踐,感興趣的朋友一起看看吧
    2025-05-05
  • Zookeeper原理及在Dubbo中的使用示例詳解

    Zookeeper原理及在Dubbo中的使用示例詳解

    這篇文章主要為大家介紹了Zookeeper原理及在Dubbo中的使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-03-03
  • 帶你入門Java的方法

    帶你入門Java的方法

    這篇文章主要介紹了java基礎之方法詳解,文中有非常詳細的代碼示例,對正在學習java基礎的小伙伴們有非常好的幫助,需要的朋友可以參考下
    2021-07-07
  • Spring boot @RequestBody數(shù)據(jù)傳遞過程詳解

    Spring boot @RequestBody數(shù)據(jù)傳遞過程詳解

    這篇文章主要介紹了Spring boot @RequestBody數(shù)據(jù)傳遞過程詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-12-12
  • 基于MybatisPlus插件TenantLineInnerInterceptor實現(xiàn)多租戶功能

    基于MybatisPlus插件TenantLineInnerInterceptor實現(xiàn)多租戶功能

    這篇文章主要介紹了基于MybatisPlus插件TenantLineInnerInterceptor實現(xiàn)多租戶功能,需要的朋友可以參考下
    2021-11-11
  • java.net.MalformedURLException異常的解決方法

    java.net.MalformedURLException異常的解決方法

    下面小編就為大家?guī)硪黄猨ava.net.MalformedURLException異常的解決方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-05-05
  • Java根據(jù)code獲取枚舉優(yōu)化方式

    Java根據(jù)code獲取枚舉優(yōu)化方式

    文章介紹了如何優(yōu)化枚舉類根據(jù)code獲取枚舉類型的過程,通過創(chuàng)建基接口BaseEnum和枚舉工具類MyEnumUtil,實現(xiàn)了通用的獲取方法,同時,還討論了根據(jù)description獲取枚舉的優(yōu)化方法,并建議使用第二種方法
    2026-03-03
  • 詳解Java數(shù)組的四種拷貝方式

    詳解Java數(shù)組的四種拷貝方式

    Java數(shù)組一共有四種拷貝方式: for循環(huán)、copyof/copyOfRange、arraycopy和clone。本文將為大家詳細介紹一下這四種方式,感興趣的可以了解一下
    2022-02-02
  • Java實現(xiàn)post請求詳細代碼(帶有參數(shù))

    Java實現(xiàn)post請求詳細代碼(帶有參數(shù))

    這篇文章主要給大家介紹了關于Java實現(xiàn)帶有參數(shù)post請求的相關資料,文中通過代碼示例介紹的非常詳細,對大家學習或者使用Java具有一定的參考學習價值,需要的朋友可以參考下
    2023-08-08

最新評論

阳春市| 新郑市| 双峰县| 名山县| 清新县| 平罗县| 万盛区| 侯马市| 东海县| 海南省| 雷州市| 定西市| 富源县| 西藏| 高雄市| 卢湾区| 应城市| 双桥区| 桐柏县| 威海市| 郯城县| 德清县| 武隆县| 昌都县| 丽江市| 西贡区| 甘德县| 祁连县| 镇远县| 五河县| 辽阳县| 泗水县| 阜城县| 太康县| 井研县| 石家庄市| 梁山县| 堆龙德庆县| 鄂托克旗| 新龙县| 徐州市|