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

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

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

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

1. 繼承關(guān)系與核心功能

GenericFilterBean

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

OncePerRequestFilter

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

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

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

3. 使用場景對比

選擇 GenericFilterBean 的場景

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

選擇 OncePerRequestFilter 的場景

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

如何使用?

1. GenericFilterBean 的使用

步驟

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

示例代碼:記錄每次請求的 URL 和耗時(shí)(可能多次觸發(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 {
        //請求響應(yīng)前
        long startTime = System.currentTimeMillis();
        System.out.println("Request Start: " + request.getRequestURI());
        
        chain.doFilter(request, response); // 繼續(xù)處理
        //請求響應(yīng)后
        long endTime = System.currentTimeMillis();
        System.out.println("Request End: " + request.getRequestURI() + ", Time: " + (endTime - startTime) + "ms");
    }
}

2. OncePerRequestFilter 的使用

步驟

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

示例代碼:設(shè)置請求頭(僅執(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 {
        //請求響應(yīng)前
        long startTime = System.currentTimeMillis();
        System.out.println("Request Start: " + request.getRequestURI());
       
        // 設(shè)置請求頭,僅執(zhí)行一次
        response.setHeader("X-Custom-Header", "Spring-Once");
        
        // 必須調(diào)用 chain.doFilter(),否則請求無法繼續(xù)
        chain.doFilter(request, response);
        //請求響應(yīng)后
        long endTime = System.currentTimeMillis();
        System.out.println("Request End: " + request.getRequestURI() + ", Time: " + (endTime - startTime) + "ms");

    }
}

關(guān)鍵區(qū)別總結(jié)

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

舉例說明

示例 1:日志記錄(GenericFilterBean)

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

@Component
@Order(2) // 可以定執(zhí)行順序,數(shù)字越小優(yōu)先級(jí)越高
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");
    }
}

結(jié)果:如果請求被轉(zhuǎn)發(fā)多次,日志會(huì)重復(fù)記錄。

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

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

@Component
@Order(2) // 可以定執(zhí)行順序,數(shù)字越小優(yōu)先級(jí)越高
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);
    }
}

結(jié)果:即使請求被轉(zhuǎn)發(fā),認(rèn)證邏輯僅執(zhí)行一次。

總結(jié)

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

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

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

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

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

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

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

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

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

    帶你入門Java的方法

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

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

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

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

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

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

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

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

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

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

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

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

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

最新評(píng)論

南溪县| 铜山县| 江安县| 女性| 恭城| 女性| 太和县| 棋牌| 冕宁县| 牙克石市| 青铜峡市| 邛崃市| 玛多县| 济宁市| 南康市| 开封市| 天柱县| 耒阳市| 鹰潭市| 合山市| 唐河县| 万宁市| 淳安县| 土默特左旗| 滕州市| 东阿县| 北辰区| 永登县| 郧西县| 正定县| 商城县| 天祝| 托克逊县| 阳西县| 青龙| 乌什县| 吉隆县| 闽侯县| 寻甸| 项城市| 若尔盖县|