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

SpringBoot實(shí)現(xiàn)攔截Http請(qǐng)求并設(shè)置請(qǐng)求頭

 更新時(shí)間:2026年01月29日 09:50:20   作者:你這個(gè)代碼我看不懂  
這篇文章主要為大家詳細(xì)介紹了如何使用SpringBoot實(shí)現(xiàn)攔截Http請(qǐng)求并設(shè)置請(qǐng)求頭,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

ClientHttpRequestInterceptor攔截器

在Spring Boot中,你可以通過攔截RestTemplate請(qǐng)求并在發(fā)送前設(shè)置請(qǐng)求頭,通常有以下兩種方式實(shí)現(xiàn):

1. 使用ClientHttpRequestInterceptor

通過自定義攔截器ClientHttpRequestInterceptor,在intercept方法中修改請(qǐng)求頭,然后將攔截器添加到RestTemplate實(shí)例中。

步驟:

  • 創(chuàng)建攔截器類實(shí)現(xiàn)ClientHttpRequestInterceptor接口
  • intercept方法中添加或修改請(qǐng)求頭
  • 將攔截器注冊(cè)到RestTemplate

示例代碼:

import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.web.client.RestTemplate;

import java.io.IOException;
import java.util.Collections;

public class HeaderInterceptor implements ClientHttpRequestInterceptor {
    
    @Override
    public ClientHttpResponse intercept(HttpRequest request, byte[] body, 
                                      ClientHttpRequestExecution execution) throws IOException {
        // 添加請(qǐng)求頭
        request.getHeaders().add("Authorization", "Bearer your-token");
        request.getHeaders().add("Custom-Header", "custom-value");
        
        return execution.execute(request, body);
    }
}

// 配置RestTemplate
@Bean
public RestTemplate restTemplate() {
    RestTemplate restTemplate = new RestTemplate();
    restTemplate.setInterceptors(Collections.singletonList(new HeaderInterceptor()));
    return restTemplate;
}

2. 使用RestTemplateBuilder(推薦)

通過RestTemplateBuilder可以更方便地添加攔截器,支持鏈?zhǔn)秸{(diào)用。

示例代碼:

import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class RestTemplateConfig {
    
    @Bean
    public RestTemplate restTemplate(RestTemplateBuilder builder) {
        return builder
                .additionalInterceptors(new HeaderInterceptor())
                .build();
    }
}

3. 動(dòng)態(tài)設(shè)置請(qǐng)求頭(針對(duì)特定請(qǐng)求)

如果某些請(qǐng)求頭需要?jiǎng)討B(tài)設(shè)置(如從上下文獲取token),可以在攔截器中加入邏輯:

public class DynamicHeaderInterceptor implements ClientHttpRequestInterceptor {
    
    @Override
    public ClientHttpResponse intercept(HttpRequest request, byte[] body, 
                                      ClientHttpRequestExecution execution) throws IOException {
        // 從安全上下文或其他來源動(dòng)態(tài)獲取值
        String token = SecurityContextHolder.getContext().getAuthentication().getCredentials().toString();
        request.getHeaders().add("Authorization", "Bearer " + token);
        
        return execution.execute(request, body);
    }
}

注意事項(xiàng)

  • 攔截器會(huì)應(yīng)用于所有通過該RestTemplate發(fā)起的請(qǐng)求
  • 如果需要為不同請(qǐng)求設(shè)置不同請(qǐng)求頭,可在攔截器中根據(jù)request.getURI()判斷路徑
  • 考慮使用ThreadLocal存儲(chǔ)線程安全的上下文信息(如請(qǐng)求ID)

如果需要更細(xì)粒度的控制,可以考慮使用RestTemplateexchange()方法直接傳入HttpEntity(包含頭部信息),但這種方式需要在每次調(diào)用時(shí)顯式設(shè)置。

統(tǒng)一攔截所有HTTP請(qǐng)求

要統(tǒng)一攔截所有HTTP請(qǐng)求(包括RestTemplate、WebClient、Feign等),可以通過以下幾種方式實(shí)現(xiàn):

1. 使用Spring的ClientHttpRequestInterceptor(僅適用于RestTemplate)

適用于所有通過RestTemplate發(fā)起的請(qǐng)求,但對(duì)其他客戶端無效。

2. 使用Servlet Filter(最通用)

Filter可以攔截所有進(jìn)入容器的HTTP請(qǐng)求,包括:

  • RestTemplate發(fā)起的請(qǐng)求
  • WebClient發(fā)起的請(qǐng)求
  • Feign客戶端發(fā)起的請(qǐng)求
  • 任何其他HTTP客戶端發(fā)起的請(qǐng)求

示例代碼:

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

@Component
@Order(1) // 執(zhí)行順序
public class GlobalHttpFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, 
                        FilterChain chain) throws IOException, ServletException {
        
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        
        // 添加全局請(qǐng)求頭
        if (httpRequest.getHeader("Authorization") == null) {
            // 這里可以設(shè)置默認(rèn)認(rèn)證頭或其他通用頭
        }
        
        // 記錄請(qǐng)求日志
        System.out.println("Request URL: " + httpRequest.getRequestURL());
        System.out.println("Method: " + httpRequest.getMethod());
        
        chain.doFilter(request, response); // 繼續(xù)執(zhí)行過濾器鏈
    }
}

3. 使用AOP面向切面編程

通過AOP攔截所有HTTP客戶端調(diào)用方法:

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class HttpRequestAspect {

    @Around("execution(* org.springframework.web.client.RestTemplate.*(..)) || " +
            "execution(* org.springframework.web.reactive.function.client.WebClient.*(..))")
    public Object aroundHttpRequest(ProceedingJoinPoint joinPoint) throws Throwable {
        
        // 在方法執(zhí)行前添加請(qǐng)求頭
        Object[] args = joinPoint.getArgs();
        for (int i = 0; i < args.length; i++) {
            if (args[i] instanceof HttpEntity) {
                HttpEntity<?> entity = (HttpEntity<?>) args[i];
                HttpHeaders headers = new HttpHeaders();
                headers.putAll(entity.getHeaders());
                headers.add("Global-Header", "common-value");
                
                // 替換為新的HttpEntity
                args[i] = new HttpEntity<>(entity.getBody(), headers);
            }
        }
        
        return joinPoint.proceed(args);
    }
}

4. 使用OkHttp的Interceptor(如果使用OkHttp作為底層客戶端)

import okhttp3.Interceptor;
import okhttp3.Response;
import java.io.IOException;

public class GlobalOkHttpInterceptor implements Interceptor {
    @Override
    public Response intercept(Chain chain) throws IOException {
        return chain.proceed(chain.request().newBuilder()
                .addHeader("Authorization", "Bearer token")
                .addHeader("X-Request-ID", UUID.randomUUID().toString())
                .build());
    }
}

5. 推薦方案:組合使用

攔截方式適用范圍優(yōu)點(diǎn)缺點(diǎn)
Servlet Filter所有HTTP請(qǐng)求最通用,覆蓋全面無法區(qū)分內(nèi)部/外部請(qǐng)求
AOP方法級(jí)別攔截精確控制,可區(qū)分業(yè)務(wù)配置相對(duì)復(fù)雜
ClientHttpRequestInterceptor僅RestTemplate簡單易用局限性大
OkHttp Interceptor使用OkHttp的客戶端性能好需要統(tǒng)一HTTP客戶端

最佳實(shí)踐建議:

  • 使用Servlet Filter處理全局通用的請(qǐng)求頭(如追蹤ID、基礎(chǔ)認(rèn)證)
  • 使用AOP處理業(yè)務(wù)特定的攔截邏輯
  • 根據(jù)項(xiàng)目使用的HTTP客戶端選擇相應(yīng)的攔截機(jī)制

根據(jù)你的需求,Servlet Filter通常是最合適的統(tǒng)一攔截方案。

手動(dòng)攔截并設(shè)置(反射):

public void setRequestHeader(String key, String value) {
        if (StringUtils.isEmpty(key) || StringUtils.isEmpty(value)) {
            return;
        }
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (null == attributes) {
            return;
        }
        HttpServletRequest request = attributes.getRequest();
        Class<? extends HttpServletRequest> requestClass = request.getClass();
        try {
            // 反射獲取request屬性
            Field headerField = requestClass.getDeclaredField("headerMap");
            headerField.setAccessible(true);
            Map<String, String> headerMap = (Map<String, String>) headerField.get(request);
            headerMap.put(key, value);
        } catch (Exception e) {
            log.error("set header error: ", e);
        }
    }

ClientHttpRequestInterceptor 會(huì)在 每次 通過配置了該攔截器的 RestTemplate 實(shí)例發(fā)起 HTTP 調(diào)用之前執(zhí)行。

工作原理

當(dāng)你調(diào)用 RestTemplate 的任何方法(如 getForObject, postForEntity, exchange 等)時(shí),Spring 會(huì)按以下順序處理:

  • 你調(diào)用 restTemplate.getForObject(...)
  • Spring 開始構(gòu)建實(shí)際的 HTTP 請(qǐng)求
  • 在執(zhí)行網(wǎng)絡(luò)調(diào)用之前,Spring 會(huì)遍歷所有已注冊(cè)的 ClientHttpRequestInterceptor
  • 按順序調(diào)用每個(gè)攔截器的 intercept 方法
  • 在你的 intercept 方法中,你可以檢查和修改請(qǐng)求(HttpRequest)和請(qǐng)求體(byte[] body
  • 所有攔截器執(zhí)行完畢后,最終調(diào)用 execution.execute(request, body) 來真正地發(fā)送網(wǎng)絡(luò)請(qǐng)求

關(guān)鍵特性

  • 每次調(diào)用都執(zhí)行:無論這個(gè) RestTemplate 實(shí)例被調(diào)用多少次,攔截器都會(huì)在每次請(qǐng)求前工作。
  • 適用于所有方法:它不區(qū)分 get, post, put, delete 等方法,對(duì)所有通過該 RestTemplate 發(fā)起的請(qǐng)求一視同仁。
  • 可設(shè)置多個(gè)攔截器:你可以為一個(gè) RestTemplate 添加多個(gè)攔截器,它們會(huì)按照添加的順序依次執(zhí)行。

示例場(chǎng)景驗(yàn)證

假設(shè)你有以下配置和代碼:

// 1. 定義一個(gè)打印日志的攔截器
public class LoggingInterceptor implements ClientHttpRequestInterceptor {
    @Override
    public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
        System.out.println("【攔截器執(zhí)行】準(zhǔn)備發(fā)送請(qǐng)求至: " + request.getURI());
        // ... 可以在這里添加請(qǐng)求頭
        return execution.execute(request, body);
    }
}

// 2. 將攔截器添加到 RestTemplate
@Bean
public RestTemplate restTemplate() {
    RestTemplate restTemplate = new RestTemplate();
    restTemplate.setInterceptors(Collections.singletonList(new LoggingInterceptor()));
    return restTemplate;
}

// 3. 在服務(wù)中多次使用 RestTemplate
@Service
public class MyService {

    @Autowired
    private RestTemplate restTemplate;

    public void fetchData() {
        // 第一次調(diào)用
        String result1 = restTemplate.getForObject("https://api.example.com/data/1", String.class);
        
        // 第二次調(diào)用
        String result2 = restTemplate.getForObject("https://api.example.com/data/2", String.class);
    }
}

當(dāng)你調(diào)用 myService.fetchData() 時(shí),控制臺(tái)會(huì)輸出:

【攔截器執(zhí)行】準(zhǔn)備發(fā)送請(qǐng)求至: https://api.example.com/data/1
【攔截器執(zhí)行】準(zhǔn)備發(fā)送請(qǐng)求至: https://api.example.com/data/2

這清楚地證明了攔截器為每次請(qǐng)求都執(zhí)行了一次。

總結(jié)

你可以放心地依賴 ClientHttpRequestInterceptor 來執(zhí)行諸如添加認(rèn)證令牌、設(shè)置公共請(qǐng)求頭、記錄請(qǐng)求日志、重試邏輯等需要在每個(gè)請(qǐng)求發(fā)出前完成的統(tǒng)一操作。它的設(shè)計(jì)初衷就是為此類場(chǎng)景服務(wù)的。

Attribute和Header

  • Attribute(屬性)服務(wù)端內(nèi)部的“便簽”,用于在一次請(qǐng)求的生命周期內(nèi),在服務(wù)器內(nèi)部的各個(gè)組件(如Controller、Service、Interceptor、Filter、View等)之間傳遞數(shù)據(jù)。客戶端(如瀏覽器)完全不知道它的存在。
  • Header(頭信息)客戶端和服務(wù)器之間正式通信協(xié)議(HTTP)的一部分,用于傳遞元數(shù)據(jù)(如內(nèi)容類型、認(rèn)證信息、緩存控制等)。它對(duì)客戶端是可見的,并且通常會(huì)影響請(qǐng)求/響應(yīng)的處理方式。

下面是一個(gè)詳細(xì)的對(duì)比表格,幫助你更清晰地理解:

特性Attribute(屬性)Header(頭信息)
作用域服務(wù)器端的一次請(qǐng)求生命周期內(nèi)(Request Scope)**HTTP協(xié)議本身,在客戶端和服務(wù)器之間傳輸
可見性僅服務(wù)器內(nèi)部可見(如Filter, Interceptor, Controller, Service, JSP/Thymeleaf等)客戶端和服務(wù)器都可見,可通過瀏覽器開發(fā)者工具或抓包工具查看
用途在服務(wù)器處理請(qǐng)求的過程中,在不同組件間傳遞數(shù)據(jù)。例如:
- Filter校驗(yàn)用戶后,將用戶信息存入attribute供Controller使用
- Interceptor計(jì)算耗時(shí)后,將耗時(shí)結(jié)果存入attribute
傳遞HTTP協(xié)議的元數(shù)據(jù)。例如:
- Content-Type: 聲明請(qǐng)求體/響應(yīng)體的格式(如application/json)
- Authorization: 傳遞認(rèn)證憑證(如Bearer token)
- User-Agent: 聲明客戶端類型
- Custom-Header: 自定義業(yè)務(wù)頭(如X-Request-ID用于全鏈路追蹤)
生命周期從請(qǐng)求進(jìn)入服務(wù)器開始,到服務(wù)器返回響應(yīng)結(jié)束。請(qǐng)求結(jié)束即銷毀。請(qǐng)求頭(Request Header) 隨請(qǐng)求從客戶端發(fā)往服務(wù)器。
響應(yīng)頭(Response Header) 隨響應(yīng)從服務(wù)器發(fā)往客戶端。
數(shù)據(jù)類型可以是任何Java對(duì)象(Object)只能是字符串(String)或字符串?dāng)?shù)組(String[])
操作方式 (Java)request.setAttribute("key", value);
Object value = request.getAttribute("key");
獲取請(qǐng)求頭:
String value = request.getHeader("Header-Name");
設(shè)置響應(yīng)頭:
response.setHeader("Header-Name", "value");
response.addHeader("Header-Name", "value");

類比幫助理解

你可以把它們想象成寄送一個(gè)實(shí)體包裹:

  • Header 就像是包裹外面的快遞單。上面寫明了收件人地址、寄件人信息、包裹類型(易碎品)、是否需要代收款等。快遞員和收發(fā)貨雙方都能看到這個(gè)單子,并根據(jù)上面的信息來處理包裹。
  • Attribute 就像是包裹里面的一張內(nèi)部紙條,是發(fā)貨人寫給倉庫分揀員的,比如“這是VIP客戶的加急訂單,優(yōu)先處理”。只有打開包裹的內(nèi)部人員(服務(wù)器)才能看到這張紙條,收貨人(客戶端)根本不知道它的存在。

代碼示例

1. 操作 Header (在Servlet Filter或Controller中)

// 從客戶端發(fā)來的請(qǐng)求中獲取頭信息
String authHeader = httpRequest.getHeader("Authorization");
String userAgent = httpRequest.getHeader("User-Agent");

// 向客戶端發(fā)送響應(yīng)時(shí)設(shè)置頭信息
httpResponse.setHeader("Content-Type", "application/json");
httpResponse.addHeader("X-Custom-Header", "MyValue");

2. 操作 Attribute (在Filter, Interceptor, Controller中)

// 在Filter中設(shè)置屬性
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
    HttpServletRequest httpRequest = (HttpServletRequest) request;
    // 認(rèn)證成功后,將用戶信息存入attribute
    User user = authenticateUser(httpRequest);
    httpRequest.setAttribute("currentUser", user); // 存入任何對(duì)象
    chain.doFilter(request, response);
}

// 在Controller中獲取和使用屬性
@GetMapping("/api/profile")
public ResponseEntity getUserProfile(HttpServletRequest request) {
    // 從attribute中取出之前存入的對(duì)象
    User currentUser = (User) request.getAttribute("currentUser");
    // ... 使用user對(duì)象處理業(yè)務(wù)
    return ResponseEntity.ok(currentUser.getProfile());
}

總結(jié)

記住這個(gè)最簡單的原則:

  • 需要讓客戶端知曉或受其影響的信息,用 Header(如認(rèn)證、緩存、內(nèi)容協(xié)商)。
  • 只在服務(wù)器內(nèi)部處理過程中需要臨時(shí)攜帶的數(shù)據(jù),用 Attribute(如用戶身份、計(jì)算中間結(jié)果、頁面渲染數(shù)據(jù))。

到此這篇關(guān)于SpringBoot實(shí)現(xiàn)攔截Http請(qǐng)求并設(shè)置請(qǐng)求頭的文章就介紹到這了,更多相關(guān)SpringBoot攔截Http請(qǐng)求內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 詳解Spring Cloud負(fù)載均衡重要組件Ribbon中重要類的用法

    詳解Spring Cloud負(fù)載均衡重要組件Ribbon中重要類的用法

    本篇文章主要介紹了詳解Spring Cloud負(fù)載均衡重要組件Ribbon中重要類的用法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-03-03
  • 詳解Java?ThreadPoolExecutor的拒絕策略

    詳解Java?ThreadPoolExecutor的拒絕策略

    這篇文章主要介紹了Java?ThreadPoolExecutor的拒絕策略,本文對(duì)于線程的池的幾種策略進(jìn)行詳細(xì)的講解,在實(shí)際的生產(chǎn)中需要集合相關(guān)的場(chǎng)景來選擇合適的拒絕策略,需要的朋友可以參考下
    2022-08-08
  • MybatisPlus使用@TableId主鍵id自增長無效的解決

    MybatisPlus使用@TableId主鍵id自增長無效的解決

    本文主要介紹了MybatisPlus使用@TableId主鍵id自增長無效的解決,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • Java中的for循環(huán)高級(jí)用法

    Java中的for循環(huán)高級(jí)用法

    本文系統(tǒng)解析Java中傳統(tǒng)、增強(qiáng)型for循環(huán)、Stream API及并行流的實(shí)現(xiàn)原理與性能差異,并通過大量代碼示例展示實(shí)際開發(fā)中的最佳實(shí)踐,感興趣的朋友一起看看吧
    2025-06-06
  • springboot使JUL實(shí)現(xiàn)日志管理功能

    springboot使JUL實(shí)現(xiàn)日志管理功能

    這篇文章主要介紹了springboot使JUL實(shí)現(xiàn)日志管理功能,本文分步驟給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-09-09
  • IDEA中設(shè)置背景顏色的步驟

    IDEA中設(shè)置背景顏色的步驟

    在IntelliJ IDEA中,用戶可以通過訪問【Settings】或【Preferences】菜單,進(jìn)入【Editor】>【ColorScheme】選項(xiàng)來選擇和調(diào)整編輯區(qū)域的顏色方案,此外,通過【Appearance & Behavior】>【Appearance】選項(xiàng)
    2024-09-09
  • Mybatis基于注解形式的sql語句生成實(shí)例代碼

    Mybatis基于注解形式的sql語句生成實(shí)例代碼

    這篇文章主要介紹了 Mybatis基于注解形式的sql語句生成實(shí)例代碼,需要的朋友可以參考下
    2017-09-09
  • Mybatis錯(cuò)誤引起的程序啟動(dòng)卡死問題及解決

    Mybatis錯(cuò)誤引起的程序啟動(dòng)卡死問題及解決

    這篇文章主要介紹了Mybatis錯(cuò)誤引起的程序啟動(dòng)卡死問題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-02-02
  • 使用注解開發(fā)SpringMVC詳細(xì)配置教程

    使用注解開發(fā)SpringMVC詳細(xì)配置教程

    這篇文章主要介紹了使用注解開發(fā)SpringMVC詳細(xì)配置教程,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-09-09
  • 基于Java ActiveMQ的實(shí)例講解

    基于Java ActiveMQ的實(shí)例講解

    下面小編就為大家?guī)硪黄贘ava ActiveMQ的實(shí)例講解。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-09-09

最新評(píng)論

叶城县| 凤阳县| 九龙城区| 宿州市| 高要市| 澄迈县| 宿松县| 巴楚县| 上林县| 上犹县| 和龙市| 新巴尔虎左旗| 南开区| 河源市| 海丰县| 莱西市| 巴彦县| 佛山市| 游戏| 永年县| 怀化市| 昆山市| 柘荣县| 政和县| 七台河市| 息烽县| 多伦县| 池州市| 西华县| 泰顺县| 武乡县| 福泉市| 奉化市| 田阳县| 中方县| 新安县| 辽中县| 廊坊市| 盐山县| 阿克陶县| 鄱阳县|