微服务feign调用添加token
1.一般情况是这么配置的
具体的怎么调用就不说了 如下配置,就可以在请求头中添加需要的请求头信息。
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调用服务时,会丢失请求头信息。需要在这里把认证信息收到添加上去 * @author TRON * @since 2019-11-23 * * */ @Configuration @Slf4j public class FeignTokenInterceptor implements RequestInterceptor { @Override public void apply ( RequestTemplate requestTemplate ) { log . info ( "======上下文中获取原请求信息======" ); 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 ( "===原请求头信息=== 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 .但是,当熔断开启后,原先的这么配置就不起作用了
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 ; /** * 自定义并发策略 * 将现有的并发策略作为新并发策略的成员变量 * 在新并发策略中,返回现有并发策略的线程池、Queue * * hystrix测试数据mand.default.execution.isolation.strategy=THREAD * Hystrix的默认隔离策略(官方推荐,当使用该隔离策略时,是没办法拿到 ThreadLocal 中的值的,但是RequestContextHolder 源码中,使用了两个ThreadLocal) * hystrix测试数据mand.default.execution.isolation.strategy=SEMAPHORE (将隔离策略改为SEMAPHORE 也可以解决这个问题,但是官方并不推荐这个策略,因为这个策略对网络资源消耗比较大) * * 主要是解决当 Hystrix的默认隔离策略是THREAD时,不能通过RequestContextHolder获取到request对象的问题 * */ //@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 #连接超时3秒,连接失败时直接调用降级方法 readTimeout : 100000 #连接成功,处理数据的时间限制10秒 100000 读取时间过短会抛异常java.net.SocketTimeoutException: Read timed out loggerLevel : full #日志输出等级 hystrix : enabled : true hystrix : command : default : execution : isolation : thread : timeoutInMilliseconds : 5000 #服务连接成功,但是时间过长,降级方法调用时间 60000 5000feign微服务的相互调用
我只是记录服务提供方、消费方的代码编写,配置什么的大家在网上搜,一大堆。
首先是服务提供方:
启动类上加上注解@EnableFeignClients,然后正常的写controller、service等业务逻辑
其次是服务的调用方:
1.首先启动类上加上注解@EnableFeignClients
2.编写服务调用接口
3.编写接口熔断处理方法
4.本人遇到的问题是需要用到调用方的请求头里面的信息,但是在提供方取不到,这时可以通过在调用方增加配置来解决
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请求拦截器 * * @return */ @Bean public RequestInterceptor requestInterceptor (){ return new FeignBasicAuthRequestInterceptor (); } }
以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。
原文链接:https://blog.csdn.net/hzy3344520/article/details/105846487
查看更多关于解决微服务feign调用添加token的问题的详细内容...
声明:本文来自网络,不代表【好得很程序员自学网】立场,转载请注明出处:http://www.haodehen.cn/did214712