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

使用Feign動(dòng)態(tài)設(shè)置header和原理分析

 更新時(shí)間:2022年03月04日 16:07:24   作者:20世紀(jì)少年  
這篇文章主要介紹了使用Feign動(dòng)態(tài)設(shè)置header和原理分析,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

Feign動(dòng)態(tài)設(shè)置header和原理

項(xiàng)目中用到了Feign做遠(yuǎn)程調(diào)用, 有部分場(chǎng)景需要?jiǎng)討B(tài)配置header

開始的做法是通過(guò) @RequestHeader 設(shè)置參數(shù)來(lái)實(shí)現(xiàn)動(dòng)態(tài)的header配置

例如

@GetMapping(value = "/test", consumes = {MediaType.APPLICATION_JSON_UTF8_VALUE}) ? ?
String access(@RequestHeader("Auth") String auth, @RequestBody Expression expression);

這種方式雖然可以達(dá)到header的動(dòng)態(tài)配置, 但是當(dāng)參數(shù)過(guò)多時(shí)會(huì)降低接口可用性, 所以想通過(guò)傳遞bean的方式來(lái)設(shè)置header

先說(shuō)解決辦法

public class HeaderInterceptor implements RequestInterceptor {
? ? @Override
? ? public void apply(RequestTemplate requestTemplate) {
? ? ? ? byte[] bytes = requestTemplate.requestBody().asBytes();
? ? ? ? Identity identity = JSONObject.parseObject(bytes, Identity.class);
? ? ? ? requestTemplate.header("Auth", identity.getSecret());
? ? }
}?
/**
?* configuration指定Interceptor
**/
@FeignClient(name = "test", url = "127.0.0.1:8300", configuration = HeaderInterceptor.class)
public interface GolangTestHandle2 {
? ? @GetMapping(value = "/handler", consumes = {MediaType.APPLICATION_JSON_UTF8_VALUE})
? ? String handle(Identity identity);
}

自定義Interceptor實(shí)現(xiàn)RequestInterceptor接口, 回調(diào)方法apply提供了RequestTemplate對(duì)象, 對(duì)象內(nèi)部封裝了request的所有信息, 最后通過(guò)configuration指定接口, 之后就隨便你怎么玩了(例如通過(guò)body獲取接口參數(shù)并動(dòng)態(tài)設(shè)置header)

值得注意的一點(diǎn)是HeaderInterceptor如果注入到Springboot容器的話會(huì)全局生效, 就是說(shuō)及時(shí)沒有指定configuration也會(huì)對(duì)全局feign接口生效, 為什么呢? 這里簡(jiǎn)單說(shuō)明一下

首先Feign為每個(gè)feign class創(chuàng)建springcontext上下文

spring通過(guò)調(diào)用getObject獲取feign工廠實(shí)例

? ? @Override
? ? public Object getObject() throws Exception {
? ? ? ? return getTarget();
? ? }

    內(nèi)部調(diào)用FeignClientFatoryBean.getTarget()方法

<T> T getTarget() {
? ? ? ? //獲取feign上下文
? ? ? ? FeignContext context = this.applicationContext.getBean(FeignContext.class);
? ? ? ? //構(gòu)建feign Builder
? ? ? ? Feign.Builder builder = feign(context);
? ? ? ? ...
? ? }

根據(jù)feign(FeignContext context)構(gòu)建Builder

protected Feign.Builder feign(FeignContext context) {
? ? ? ? FeignLoggerFactory loggerFactory = get(context, FeignLoggerFactory.class);
? ? ? ? Logger logger = loggerFactory.create(this.type);
? ? ? ? // @formatter:off
? ? ? ? Feign.Builder builder = get(context, Feign.Builder.class)
? ? ? ? ? ? ? ? // required values
? ? ? ? ? ? ? ? .logger(logger)
? ? ? ? ? ? ? ? //默認(rèn)springEncoder
? ? ? ? ? ? ? ? .encoder(get(context, Encoder.class))
? ? ? ? ? ? ? ? //默認(rèn)OptionalDecoder
? ? ? ? ? ? ? ? .decoder(get(context, Decoder.class))
? ? ? ? ? ? ? ? //默認(rèn)SpringMvcContrat
? ? ? ? ? ? ? ? .contract(get(context, Contract.class));
? ? ? ? // @formatter:on
? ? ? ? //配置該feign的context
? ? ? ? configureFeign(context, builder);
? ? ? ? return builder;
? ? }

    在構(gòu)建過(guò)程中通過(guò)FeignClientFactoryBean.configureUsingConfiguration為feign class注冊(cè)基本的配置項(xiàng), 其中也包括了Interceptor的注冊(cè)

? ? protected void configureUsingConfiguration(FeignContext context,
? ? ? ? ? ? Feign.Builder builder) {
? ? ? ? Logger.Level level = getOptional(context, Logger.Level.class);
? ? ? ? if (level != null) {
? ? ? ? ? ? builder.logLevel(level);
? ? ? ? }
? ? ? ? Retryer retryer = getOptional(context, Retryer.class);
? ? ? ? if (retryer != null) {
? ? ? ? ? ? builder.retryer(retryer);
? ? ? ? }
? ? ? ? ErrorDecoder errorDecoder = getOptional(context, ErrorDecoder.class);
? ? ? ? if (errorDecoder != null) {
? ? ? ? ? ? builder.errorDecoder(errorDecoder);
? ? ? ? }
? ? ? ? Request.Options options = getOptional(context, Request.Options.class);
? ? ? ? if (options != null) {
? ? ? ? ? ? builder.options(options);
? ? ? ? }
? ? ? ? //從feign context獲取interceptors
? ? ? ? Map<String, RequestInterceptor> requestInterceptors = context
? ? ? ? ? ? ? ? .getInstances(this.contextId, RequestInterceptor.class);
? ? ? ? if (requestInterceptors != null) {
? ? ? ? ? ? builder.requestInterceptors(requestInterceptors.values());
? ? ? ? }
? ? ? ? if (this.decode404) {
? ? ? ? ? ? builder.decode404();
? ? ? ? }
? ? }

contextId為具體的feign class id, RequestInterceptor為具體的接口, 即是說(shuō)通過(guò)context.getInstances獲取所有RequestInterceptor實(shí)例并注冊(cè)到builder中.

? ? public <T> Map<String, T> getInstances(String name, Class<T> type) {
? ? ? ? AnnotationConfigApplicationContext context = getContext(name);
? ? ? ? //使用beanNamesForTypeIncludingAncestors
? ? ? ? if (BeanFactoryUtils.beanNamesForTypeIncludingAncestors(context,
? ? ? ? ? ? ? ? type).length > 0) {
? ? ? ? ? ? return BeanFactoryUtils.beansOfTypeIncludingAncestors(context, type);
? ? ? ? }
? ? ? ? return null;
? ? }

獲取工廠中的實(shí)例使用的是beanNamesForTypeIncludingAncestors方法, 該方法不僅會(huì)從feign的factory中查找, 也會(huì)通過(guò)父級(jí)別spring工廠查找相應(yīng)實(shí)例(類似于springmvc的工廠)

也是因?yàn)樵摲椒? 即使你沒有在FeignClient中配置configuration, 但是你的Interceptor通過(guò)@Component等方法注入容器的話也會(huì)全局生效的, 所以如果指向讓你的Interceptor部分生效不讓它注入到Spring容器就好

設(shè)置Feign的header信息(兩種形式)

在使用微服務(wù)SpringCloud全家桶組件Fegin的時(shí)候,我們?cè)谶M(jìn)行遠(yuǎn)程服務(wù)之間調(diào)用的同時(shí),為了防止客戶端劫持信息,我們需要將一些敏感信息添加到我們的Fegin頭部(Header)當(dāng)中,今天朋友問起,總結(jié)一下:那么工作中常見的方式有兩種

1.在方法參數(shù)前面添加@RequestHeader注解

@PostMapping(value = "/getPersonDetail")?
public ServerResponse getPersonDetail(@RequestBody Map map,@RequestHeader(name = "id") String id);

使用@RequestHeader(name = "id")可以傳遞動(dòng)態(tài)header屬性

2.實(shí)現(xiàn)RequestInterceptor接口

設(shè)置Header(所有的Fegin請(qǐng)求)

import org.springframework.context.annotation.Configuration;?
import org.springframework.web.context.request.RequestContextHolder;?
import org.springframework.web.context.request.ServletRequestAttributes;?
import feign.RequestInterceptor;?
import feign.RequestTemplate;?
@Configuration?
public class FeignConfiguration implements RequestInterceptor { ? ?
? ? ? ? @Override ? ?
? ? ? ? public void apply(RequestTemplate template) { ? ? ?
? ? ? ? ? ? ? ? ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); ? ? ??
? ? ? ? ? ? ? ? HttpServletRequest request = attributes.getRequest(); ? ? ? ?
? ? ? ? ? ? ? ? Enumeration<String> headerNames = request.getHeaderNames(); ? ? ? ?
? ? ? ? ? ? ? ? if (headerNames != null) { ? ? ? ? ? ?
? ? ? ? ? ? ? ? ? ? ? ? while (headerNames.hasMoreElements()) { ? ? ? ? ? ??
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? String name = headerNames.nextElement(); ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? String values = request.getHeader(name); ? ? ? ? ? ??
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? template.header(name, values); ? ? ? ? ? ?
? ? ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ?
? ? ? ? ? ? ? ? } ? ?
? ? ? ? }?
}?
?
@Component
@FeignClient(value = "abc",fallback = abcServiceHystric.class ,configuration = FeignConfiguration.class) public interface AbcService { }

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

相關(guān)文章

  • MyBatis中傳入?yún)?shù)parameterType類型詳解

    MyBatis中傳入?yún)?shù)parameterType類型詳解

    這篇文章主要給大家介紹了關(guān)于MyBatis中傳入?yún)?shù)parameterType類型的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2018-04-04
  • Spring?AOP核心功能示例代碼詳解

    Spring?AOP核心功能示例代碼詳解

    AOP面向切面編程,它是一種思想,它是對(duì)某一類事情的集中處理,而AOP是一種思想,而Spring?AOP是一個(gè)框架,提供了一種對(duì)AOP思想的實(shí)現(xiàn),它們的關(guān)系和loC與DI類似,這篇文章主要介紹了Spring?AOP統(tǒng)一功能處理示例代碼,需要的朋友可以參考下
    2023-02-02
  • spring @Scheduled注解的使用誤區(qū)及解決

    spring @Scheduled注解的使用誤區(qū)及解決

    這篇文章主要介紹了spring @Scheduled注解的使用誤區(qū)及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • springboot普通類中如何獲取session問題

    springboot普通類中如何獲取session問題

    這篇文章主要介紹了springboot普通類中如何獲取session問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-01-01
  • Java實(shí)現(xiàn)文件夾中內(nèi)容定時(shí)刪除

    Java實(shí)現(xiàn)文件夾中內(nèi)容定時(shí)刪除

    這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)文件夾中內(nèi)容定時(shí)刪除,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • Spring?循環(huán)依賴之AOP實(shí)現(xiàn)詳情

    Spring?循環(huán)依賴之AOP實(shí)現(xiàn)詳情

    這篇文章主要介紹了Spring?循環(huán)依賴之AOP實(shí)現(xiàn)詳情,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的盆友可以參考一下
    2022-07-07
  • 基于SpringBoot后端導(dǎo)出Excel文件的操作方法

    基于SpringBoot后端導(dǎo)出Excel文件的操作方法

    這篇文章給大家介紹了基于SpringBoot后端導(dǎo)出Excel文件的操作方法,文中通過(guò)代碼示例給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下
    2024-02-02
  • Java靜態(tài)泛型使用方法實(shí)例解析

    Java靜態(tài)泛型使用方法實(shí)例解析

    這篇文章主要介紹了Java靜態(tài)泛型使用方法實(shí)例解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-06-06
  • JavaWeb?Servlet實(shí)現(xiàn)文件上傳與下載功能實(shí)例

    JavaWeb?Servlet實(shí)現(xiàn)文件上傳與下載功能實(shí)例

    因自己負(fù)責(zé)的項(xiàng)目中需要實(shí)現(xiàn)文件上傳,所以下面下面這篇文章主要給大家介紹了關(guān)于JavaWeb?Servlet實(shí)現(xiàn)文件上傳與下載功能的相關(guān)資料,需要的朋友可以參考下
    2022-04-04
  • Java修改eclipse中web項(xiàng)目的server部署路徑問題

    Java修改eclipse中web項(xiàng)目的server部署路徑問題

    這篇文章主要介紹了Java修改eclipse中web項(xiàng)目的server部署路徑,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-11-11

最新評(píng)論

贵州省| 陆丰市| 康乐县| 海晏县| 临汾市| 连城县| 韶关市| 措勤县| 喀喇| 陈巴尔虎旗| 广宗县| 冕宁县| 昆明市| 盐津县| 明星| 堆龙德庆县| 阳江市| 武冈市| 肥东县| 巴林左旗| 出国| 丰镇市| 阿合奇县| 泽州县| 闻喜县| 鸡西市| 蒙阴县| 鲁山县| 临海市| 洪湖市| 武穴市| 淮北市| 依安县| 东辽县| 天祝| 四平市| 阿合奇县| 康乐县| 桑植县| 崇礼县| 潜江市|