一、需求分析
现有接口存在对用户信息进行拦截鉴权需求,在使用Feign包调用下游接口时,需要将当前请求头一直传递下去。
二、实现方案
在参考了网上的各种资料之后,通过自定义hystrix并发策略和Feign调用拦截器实现此需求
1、拦截器定义
拦截全部的Feign调用请求,从当前requestContext请求头中获取出需要的身份信息,再手动添加到requestTemplate中。
这里的问题是,当请求走到此拦截器中时,如果没有配置hystrix并发策略为信号量模式的话,就会根据hystrix默认的并发策略,进入一个新的线程池。所以在这里是获取不到我们想要的requestContext的。需要通过第二步进行处理。
@Configuration public class FeignInterceptor implements RequestInterceptor { @Override public void apply(RequestTemplate requestTemplate) { ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder .getRequestAttributes(); // 服务内部跳转时,可能不存在Request上下文 if (Objects.isNull(attributes)){ requestTemplate.header(AuthorizationUtil.Authorization, AuthorizationUtil.Authorization); return; } HttpServletRequest request = attributes.getRequest(); boolean hasParam=(request.getParameter(AuthorizationUtil.Authorization)!=null&& !"".equals(request.getParameter(AuthorizationUtil.Authorization))); if("GET".equals(request.getMethod())&& hasParam){ requestTemplate.header(AuthorizationUtil.Authorization, request.getParameter(AuthorizationUtil.Authorization)); return; } Enumeration<String> headerNames = request.getHeaderNames(); boolean bool = false; if (headerNames != null) { while (headerNames.hasMoreElements()) { String name = headerNames.nextElement(); String values = request.getHeader(name); // 只取需要的header if ("Authorization".equals(name) || "authorization".equals(name)){ requestTemplate.header(name, values); bool = true; } else if (AuthorizationUtil.Authorization.equals(name)) { requestTemplate.header(name, values); bool = true; } } if (!bool) { //判断url中是否有数据 requestTemplate.header(AuthorizationUtil.Authorization, AuthorizationUtil.Authorization); } } else { requestTemplate.header(AuthorizationUtil.Authorization, AuthorizationUtil.Authorization); } } }
2、自定义hystrix并发策略
重点在于继承HystrixConcurrencyStrategy之后,重写wrapCallable方法,内部把当前上下文中的信息填充到新线程的上下文中
@Configuration public class RequestHeaderHystrixConcurrencyStrategy extends HystrixConcurrencyStrategy { private static final Log log = LogFactory.getLog(RequestHeaderHystrixConcurrencyStrategy.class); private HystrixConcurrencyStrategy delegate; public RequestHeaderHystrixConcurrencyStrategy() { try { this.delegate = HystrixPlugins.getInstance().getConcurrencyStrategy(); if (this.delegate instanceof RequestHeaderHystrixConcurrencyStrategy) { // 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 ThreadPoolExecutor getThreadPool(HystrixThreadPoolKey threadPoolKey, HystrixThreadPoolProperties threadPoolProperties) { return this.delegate.getThreadPool(threadPoolKey, threadPoolProperties); } @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(); } } } }
标签:Feign,调用,return,请求,getInstance,AuthorizationUtil,public,Authorization,HystrixPlu From: https://www.cnblogs.com/sunshine-ground-poems/p/17147867.html