在使用SpringCloud進行Feign跨服調用時header請求頭中的信息會丟失,是由於Feign是不會帶上當前請求的Cookie信息和頭信息的,這個時候就須要重寫請求攔截。網絡
一、須要重寫RequestInterceptor接口中的apply方法(前提是Feign的隔離策略爲SEMAPHORE)併發
@Component public class FeignInterceptor implements RequestInterceptor{ @Override public void apply(RequestTemplate template) { ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); if (attributes != null) { HttpServletRequest request = attributes.getRequest(); //將token信息放入header中 template.header("access_token",request.getHeader("access_token")); } } }
注意當Feign的隔離策略爲THREAD時,因爲當使用該隔離策略時,是沒辦法拿到 ThreadLocal 中的值的,可是RequestContextHolder 源碼中,使用了兩個ThreadLocal,所以當使用該隔離策略時是沒有辦法經過RequestContextHolder獲取到request對象的,這時若是你還堅持使用THREAD這個隔離策略就須要自定義策略(重寫THREAD隔離策略),代碼以下:app
/** * 自定義併發策略 * 將現有的併發策略做爲新併發策略的成員變量 * 在新併發策略中,返回現有併發策略的線程池、Queue * * hystrix.command.default.execution.isolation.strategy=THREAD Hystrix的默認隔離策略(官方推薦,當使用該隔離策略時,是沒辦法拿到 ThreadLocal 中的值的,可是 * RequestContextHolder 源碼中,使用了兩個ThreadLocal) * hystrix.command.default.execution.isolation.strategy=SEMAPHORE (將隔離策略改成SEMAPHORE 也能夠解決這個問題,可是官方並不推薦這個策略,由於這個策略對網絡資源消耗比較大) * * 主要是解決當 Hystrix的默認隔離策略是THREAD時,不能經過RequestContextHolder獲取到request對象的問題 * * Create By yxl on 2018/5/22 */ @Component 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(); } } } }