解決微服務(wù)feign調(diào)用添加token的問題
微服務(wù)feign調(diào)用添加token
1.一般情況是這么配置的
具體的怎么調(diào)用就不說了 如下配置,就可以在請(qǐng)求頭中添加需要的請(qǐng)求頭信息。
package localdate;
import feign.RequestInterceptor;
import feign.RequestTemplate;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Map;
/**
* feign調(diào)用服務(wù)時(shí),會(huì)丟失請(qǐng)求頭信息。需要在這里把認(rèn)證信息收到添加上去
* @author TRON
* @since 2019-11-23
*
*
*/
@Configuration
@Slf4j
public class FeignTokenInterceptor implements RequestInterceptor {
@Override
public void apply(RequestTemplate requestTemplate) {
log.info("======上下文中獲取原請(qǐng)求信息======");
String token = "without token";
HttpServletRequest request = ((ServletRequestAttributes)
RequestContextHolder.getRequestAttributes()).getRequest();
Enumeration<String> headerNames = request.getHeaderNames();
while (headerNames.hasMoreElements()) {
String headerName = headerNames.nextElement();
String HeadValue = request.getHeader(headerName);
log.info("===原請(qǐng)求頭信息=== headName: {}, headValue: {}", headerName, HeadValue);
if (headerName.equals("X-Authorization-access_token")||headerName.equals("x-authorization-access_token")) {
token = HeadValue;
}
}
log.info("=======Feign添加頭部信息start======");
// requestTemplate.header("X-Authorization-access_token", token);
requestTemplate.header("X-Authorization-access_token", "tron123456");
log.info("=======Feign添加頭部信息end======");
}
}
2 .但是,當(dāng)熔斷開啟后,原先的這么配置就不起作用了
package localdate;
import com.netflix.hystrix.HystrixThreadPoolKey;
import com.netflix.hystrix.strategy.HystrixPlugins;
import com.netflix.hystrix.strategy.concurrency.HystrixConcurrencyStrategy;
import com.netflix.hystrix.strategy.concurrency.HystrixRequestVariable;
import com.netflix.hystrix.strategy.concurrency.HystrixRequestVariableLifecycle;
import com.netflix.hystrix.strategy.eventnotifier.HystrixEventNotifier;
import com.netflix.hystrix.strategy.executionhook.HystrixCommandExecutionHook;
import com.netflix.hystrix.strategy.metrics.HystrixMetricsPublisher;
import com.netflix.hystrix.strategy.properties.HystrixPropertiesStrategy;
import com.netflix.hystrix.strategy.properties.HystrixProperty;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* 自定義并發(fā)策略
* 將現(xiàn)有的并發(fā)策略作為新并發(fā)策略的成員變量
* 在新并發(fā)策略中,返回現(xiàn)有并發(fā)策略的線程池、Queue
*
* hystrix.command.default.execution.isolation.strategy=THREAD
* Hystrix的默認(rèn)隔離策略(官方推薦,當(dāng)使用該隔離策略時(shí),是沒辦法拿到 ThreadLocal 中的值的,但是RequestContextHolder 源碼中,使用了兩個(gè)ThreadLocal)
* hystrix.command.default.execution.isolation.strategy=SEMAPHORE (將隔離策略改為SEMAPHORE 也可以解決這個(gè)問題,但是官方并不推薦這個(gè)策略,因?yàn)檫@個(gè)策略對(duì)網(wǎng)絡(luò)資源消耗比較大)
*
* 主要是解決當(dāng) Hystrix的默認(rèn)隔離策略是THREAD時(shí),不能通過RequestContextHolder獲取到request對(duì)象的問題
*
*/
//@Configuration
public class FeignConfig extends HystrixConcurrencyStrategy {
private static final Logger log = LoggerFactory.getLogger(FeignConfig.class);
private HystrixConcurrencyStrategy delegate;
public FeignConfig() {
try {
this.delegate = HystrixPlugins.getInstance().getConcurrencyStrategy();
if (this.delegate instanceof FeignConfig) {
// Welcome to singleton hell...
return;
}
HystrixCommandExecutionHook commandExecutionHook =
HystrixPlugins.getInstance().getCommandExecutionHook();
HystrixEventNotifier eventNotifier = HystrixPlugins.getInstance().getEventNotifier();
HystrixMetricsPublisher metricsPublisher = HystrixPlugins.getInstance().getMetricsPublisher();
HystrixPropertiesStrategy propertiesStrategy =
HystrixPlugins.getInstance().getPropertiesStrategy();
this.logCurrentStateOfHystrixPlugins(eventNotifier, metricsPublisher, propertiesStrategy);
HystrixPlugins.reset();
HystrixPlugins.getInstance().registerConcurrencyStrategy(this);
HystrixPlugins.getInstance().registerCommandExecutionHook(commandExecutionHook);
HystrixPlugins.getInstance().registerEventNotifier(eventNotifier);
HystrixPlugins.getInstance().registerMetricsPublisher(metricsPublisher);
HystrixPlugins.getInstance().registerPropertiesStrategy(propertiesStrategy);
} catch (Exception e) {
log.error("Failed to register Sleuth Hystrix Concurrency Strategy", e);
}
}
private void logCurrentStateOfHystrixPlugins(HystrixEventNotifier eventNotifier,
HystrixMetricsPublisher metricsPublisher, HystrixPropertiesStrategy propertiesStrategy) {
if (log.isDebugEnabled()) {
log.debug("Current Hystrix plugins configuration is [" + "concurrencyStrategy ["
+ this.delegate + "]," + "eventNotifier [" + eventNotifier + "]," + "metricPublisher ["
+ metricsPublisher + "]," + "propertiesStrategy [" + propertiesStrategy + "]," + "]");
log.debug("Registering Sleuth Hystrix Concurrency Strategy.");
}
}
@Override
public <T> Callable<T> wrapCallable(Callable<T> callable) {
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
return new WrappedCallable<>(callable, requestAttributes);
}
@Override
public ThreadPoolExecutor getThreadPool(HystrixThreadPoolKey threadPoolKey,
HystrixProperty<Integer> corePoolSize, HystrixProperty<Integer> maximumPoolSize,
HystrixProperty<Integer> keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
return this.delegate.getThreadPool(threadPoolKey, corePoolSize, maximumPoolSize, keepAliveTime,
unit, workQueue);
}
@Override
public BlockingQueue<Runnable> getBlockingQueue(int maxQueueSize) {
return this.delegate.getBlockingQueue(maxQueueSize);
}
@Override
public <T> HystrixRequestVariable<T> getRequestVariable(HystrixRequestVariableLifecycle<T> rv) {
return this.delegate.getRequestVariable(rv);
}
static class WrappedCallable<T> implements Callable<T> {
private final Callable<T> target;
private final RequestAttributes requestAttributes;
public WrappedCallable(Callable<T> target, RequestAttributes requestAttributes) {
this.target = target;
this.requestAttributes = requestAttributes;
}
@Override
public T call() throws Exception {
try {
RequestContextHolder.setRequestAttributes(requestAttributes);
return target.call();
} finally {
RequestContextHolder.resetRequestAttributes();
}
}
}
}
3 .feign和熔斷的配置
feign:
client:
config:
default:
connectTimeout: 5000 #連接超時(shí)3秒,連接失敗時(shí)直接調(diào)用降級(jí)方法
readTimeout: 100000 #連接成功,處理數(shù)據(jù)的時(shí)間限制10秒 100000 讀取時(shí)間過短會(huì)拋異常java.net.SocketTimeoutException: Read timed out
loggerLevel: full #日志輸出等級(jí)
hystrix:
enabled: true
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 5000 #服務(wù)連接成功,但是時(shí)間過長,降級(jí)方法調(diào)用時(shí)間 60000 5000
feign微服務(wù)的相互調(diào)用
我只是記錄服務(wù)提供方、消費(fèi)方的代碼編寫,配置什么的大家在網(wǎng)上搜,一大堆。
首先是服務(wù)提供方:
啟動(dòng)類上加上注解@EnableFeignClients,然后正常的寫controller、service等業(yè)務(wù)邏輯

其次是服務(wù)的調(diào)用方:
1.首先啟動(dòng)類上加上注解@EnableFeignClients

2.編寫服務(wù)調(diào)用接口

3.編寫接口熔斷處理方法

4.本人遇到的問題是需要用到調(diào)用方的請(qǐng)求頭里面的信息,但是在提供方取不到,這時(shí)可以通過在調(diào)用方增加配置來解決

import feign.RequestInterceptor;
import feign.RequestTemplate;
import java.util.Enumeration;
import javax.servlet.http.HttpServletRequest;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
/**
* @author ydf
* @date 2021/5/13
* @description:
**/
public class FeignBasicAuthRequestInterceptor implements RequestInterceptor {
@Override
public void apply(RequestTemplate requestTemplate) {
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);
requestTemplate.header(name, values);
}
}
}
}

import com.jingling.netsign.applet.interceptor.FeignBasicAuthRequestInterceptor;
import feign.RequestInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author ydf
* @date 2021/5/13
* @description:
**/
@Configuration
public class FeignSupportConfig {
/**
* feign請(qǐng)求攔截器
*
* @return
*/
@Bean
public RequestInterceptor requestInterceptor(){
return new FeignBasicAuthRequestInterceptor();
}
}
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Java實(shí)現(xiàn)文件檢索系統(tǒng)的示例代碼
這篇文章主要為大家詳細(xì)介紹了如何劉Java語言實(shí)現(xiàn)簡易的文件檢索系統(tǒng),文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Java開發(fā)有一定的幫助,需要的可以參考一下2022-07-07
java面試題——詳解HashMap和Hashtable 的區(qū)別
本篇文章主要介紹了java中HashMap和Hashtable的區(qū)別,具有一定的參考價(jià)值,有需要的可以了解一下。2016-11-11
使用Java把文本內(nèi)容轉(zhuǎn)換成網(wǎng)頁的實(shí)現(xiàn)方法分享
這篇文章主要介紹了使用Java把文本內(nèi)容轉(zhuǎn)換成網(wǎng)頁的實(shí)現(xiàn)方法分享,利用到了Java中的文件io包,需要的朋友可以參考下2015-11-11
spring異步service中處理線程數(shù)限制詳解
這篇文章主要給大家介紹了關(guān)于spring異步service中處理線程數(shù)限制的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用spring具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09
Java實(shí)現(xiàn)查找當(dāng)前字符串最大回文串代碼分享
本文給大家介紹的是如何使用Java實(shí)現(xiàn)查找當(dāng)前字符串最大回文串代碼,非常的簡單實(shí)用,有需要的小伙伴可以參考下2016-07-07

