SpringCloud組件OpenFeign之攔截器解讀
SpringCloud組件OpenFeign之攔截器
OpenFeign組件中有這么一個接口——RequestInterceptor 。
我們來看一下源碼中關于這個接口的介紹。
package feign; ? /** ?* 可以配置零個或多個請求攔截器,可以用于例如給所有請求添加請求頭信息.但是不能保證攔截器的應用順? ?* 序。一旦攔截器被應用,就會調(diào)用Target類中的apply(RequestTemplate)方法去創(chuàng)建不可變的http請? ?* 求,該請求通過Client類中的execute(Request, feign.Request.Options)發(fā)送。 ?* ?* 攔截器是在設置rest模板參數(shù)后才被應用的,因此不能再攔截器中添加參數(shù),比如不能再 ? ? ?* apply(RequestTemplate)方法中給/path/{foo}/bar中的foo設置參數(shù)。 ?* 這個類類似于RequestInterceptor.intercept()方法,可以實現(xiàn)讀取、刪除或以其他方式改變請求模板? ?* 的任何部分。 ?*/ public interface RequestInterceptor { ? ? /** ? ?* 可以被每個請求調(diào)用。使用RequestTemplate提供的這個方法可以添加數(shù)據(jù)。 ? ?*/ ? void apply(RequestTemplate template); }
通過對該類及方法的注釋可以了解到RequestInterceptor接口的apply方法可以對請求進行攔截,可以在該方法中添加請求頭信息。
實踐一下。
一、創(chuàng)建一個攔截器在請求頭中添加traceId信息
場景如下,使用攔截器在請求頭中添加traceId屬性,服務端可以獲取到該traceId,用于日志追蹤。
方式一:創(chuàng)建自定義攔截器+@Configuration
package com.example.rtbootconsumer.config.interceptor; ? import com.example.rtbootconsumer.common.utils.TraceIdUtil; import feign.Request; import feign.RequestInterceptor; import feign.RequestTemplate; import org.apache.commons.lang3.StringUtils; import org.springframework.context.annotation.Configuration; ? /** ?* @Description Feign接口請求攔截器 ?**/ @Configuration public class FeignRequestInterceptor implements RequestInterceptor { ? ? ? /** ? ? ?* @description: 將traceId設置到請求頭 ? ? ?*/ ? ? @Override ? ? public void apply(RequestTemplate template) { ? ? ? ? String traceId = TraceIdUtil.getTraceId(); ? ? ? ? if (StringUtils.isNotEmpty(traceId)) { ? ? ? ? ? ? template.header("traceId", traceId); ? ? ? ? } ? ? } }
方式二:創(chuàng)建自定義攔截器+配置@FeignClient注解的configuration屬性
package com.example.rtbootconsumer.config.interceptor; ? import com.example.rtbootconsumer.common.utils.TraceIdUtil; import feign.Request; import feign.RequestInterceptor; import feign.RequestTemplate; import org.apache.commons.lang3.StringUtils; import org.springframework.context.annotation.Configuration; ? /** ?* @Description Feign接口請求攔截器 ?**/ public class FeignRequestInterceptor implements RequestInterceptor { ? ? ? /** ? ? ?* @description: 將traceId設置到請求頭 ? ? ?*/ ? ? @Override ? ? public void apply(RequestTemplate template) { ? ? ? ? String traceId = TraceIdUtil.getTraceId(); ? ? ? ? if (StringUtils.isNotEmpty(traceId)) { ? ? ? ? ? ? template.header("traceId", traceId); ? ? ? ? } ? ? } }
package com.example.rtbootconsumer.feignservice; ? import com.example.rtbootconsumer.pojo.User; import com.example.rtbootconsumer.vo.ResultBody; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.*; ? import java.util.List; ? ? @FeignClient(name = "service-provider", path = "/testComm", url = "${addr.url}",configuration = FeignRequestInterceptor.class) public interface UserFeignService { ? ? ? @PostMapping(value = "/getUser") ? ? public ResultBody<User> getUser(@RequestBody User user); }
二、創(chuàng)建兩個攔截器
也可以同時創(chuàng)建多個攔截器實現(xiàn)攔截器鏈的功能。
此時再創(chuàng)建一個攔截器FeignRequestInterceptor2,用于在請求頭中設置屬性名為test,值為lalala信息。
方式一:同上
package com.example.rtbootconsumer.config.interceptor; ? import com.example.rtbootconsumer.common.utils.TraceIdUtil; import feign.Request; import feign.RequestInterceptor; import feign.RequestTemplate; import org.apache.commons.lang3.StringUtils; import org.springframework.context.annotation.Configuration; ? /** ?* @Description Feign接口請求攔截器 ?**/ @Configuration public class FeignRequestInterceptor2 implements RequestInterceptor { ? ? ? /** ? ? ?* @description: 將test設置到請求頭 ? ? ?*/ ? ? @Override ? ? public void apply(RequestTemplate template) { ? ? ? ? String traceId = TraceIdUtil.getTraceId(); ? ? ? ? if (StringUtils.isNotEmpty(traceId)) { ? ? ? ? ? ? template.header("test", "lalala"); ? ? ? ? } ? ? } }
方式二:同上,注意這里設置的@FeignClient注解的configuration屬性值是兩個攔截器的class數(shù)組。
package com.example.rtbootconsumer.feignservice; ? import com.example.rtbootconsumer.pojo.User; import com.example.rtbootconsumer.vo.ResultBody; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.*; ? import java.util.List; ? ? @FeignClient(name = "service-provider", path = "/testComm", url = "${addr.url}",configuration = {FeignRequestInterceptor.class,FeignRequestInterceptor2.class}) public interface UserFeignService { ? ? ? @PostMapping(value = "/getUser") ? ? public ResultBody<User> getUser(@RequestBody User user); ? ? ? @PostMapping(value = "/testList") ? ? public ResultBody<List<User>> testList(@RequestBody List<User> list); }
三、注意
在創(chuàng)建并配置攔截器時有兩點需要特別注意。
1.在使用方式一去創(chuàng)建攔截器時
會攔截所有請求。用方式二時若@FeignClient注解的configuration屬性未設置攔截器,那么并不會攔截該接口下所有方法的請求。攔截器只會攔截所有configuration屬性值設置了攔截器的接口下所有方法的請求。因此使用方式二更靈活。
2.攔截器執(zhí)行順序
若使用方式一去創(chuàng)建多個攔截器時,正如前面注釋所講,不能保證攔截器的執(zhí)行順序。
但是使用方式二則可以控制攔截器的執(zhí)行順序,攔截器的執(zhí)行順序和@FeignClient注解中configuration屬性中攔截器的配置順序有關。
若配置為 {FeignRequestInterceptor.class,FeignRequestInterceptor2.class}),則會先執(zhí)行FeignRequestInterceptor中的攔截,再執(zhí)行FeignRequestInterceptor2中的攔截。
若配置為 {FeignRequestInterceptor2.class,FeignRequestInterceptor.class}),則會先執(zhí)行FeignRequestInterceptor2中的攔截,再執(zhí)行FeignRequestInterceptor中的攔截。有興趣的可以試一下。
總結
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
Mybatis傳遞多個參數(shù)的三種實現(xiàn)方法
這篇文章主要介紹了Mybatis傳遞多個參數(shù)的三種實現(xiàn)方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-04-04SpringBoot整合WebService的實現(xiàn)示例
本文主要介紹了SpringBoot整合WebService,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-11-11劍指Offer之Java算法習題精講數(shù)組與字符和等差數(shù)列
跟著思路走,之后從簡單題入手,反復去看,做過之后可能會忘記,之后再做一次,記不住就反復做,反復尋求思路和規(guī)律,慢慢積累就會發(fā)現(xiàn)質(zhì)的變化2022-03-03Spring中@PropertySource和@Value注解詳解
這篇文章主要介紹了Spring中@PropertySource和@Value注解詳解,@PropertySource注解可以方便和靈活的向Spring的環(huán)境容器(org.springframework.core.env.Environment Environment)中注入一些屬性,這些屬性可以在Bean中使用,需要的朋友可以參考下2023-11-11java使用RandomAccessFile類基于指針讀寫文件實例代碼
這篇文章主要介紹了java使用RandomAccessFile類基于指針讀寫文件實例代碼,具有一定參考價值,需要的朋友可以了解下。2017-10-10