ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

feign服务中调用,传递token

2022-03-09 19:32:57  阅读:170  来源: 互联网

标签:feign 调用 RequestContextHolder token 线程 import public


默认spring-boot 微服务中 用feign来做服务间调用,是不会携带token传递的。为了能让服务间调用的时候带上token,需要进行配置,增强resTemplate  

1、先实现请求拦截器

/**
 * feign配置token
 */
@Configuration
public class FeignRequestInterceptor implements RequestInterceptor {

    @Override
    public void apply(RequestTemplate requestTemplate) {
        // 这里可以添加feign请求的全局参数
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (attributes == null || attributes.getRequest() == null) {
            return;
        }
        HttpServletRequest request = attributes.getRequest();
        requestTemplate.header("token", request.getHeader("token"));
        requestTemplate.header("feignClient", "ifaas-hotel-robot-platform");

    }
}
 

2.在@FeignClient接口里添加configuration = {FeignConfig.class}

@FeignClient(name="被调用的服务名", configuration={FeignRequestInterceptor .class})

 

由于feign的熔断器hystrix的隔离策略的原因,feign调用线程和主线程隔离了,请求上下文不共用,导致feign拦截器中 RequestContextHolder.getRequestAttributes()为空   原因: 此属性指示HystrixCommand.run()执行哪种隔离策略,是以下两种选择之一:
  • THREAD —它在单独的线程上执行,并发请求受线程池中线程数的限制
  • SEMAPHORE —它在调用线程上执行,并发请求受信号量限制
 

3、解决feign中RequestContextHolder.getRequestAttributes()为null方案有两种:

3.1、修改隔离策略:默认是 采用THREAD ,修改成SEMAPHORE 即可,但是不推荐这种做法,因为并发请求收到限制。

 

3.2、自定义feign的并发策略 继承HystrixConcurrencyStrategy,然后重写wrapCallable方法。如下:

import com.netflix.hystrix.strategy.HystrixPlugins;
import com.netflix.hystrix.strategy.concurrency.HystrixConcurrencyStrategy;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;


import java.util.concurrent.Callable;

/**
 * Created by YangGuanRong
 * date: 2022/3/8
 */
@Slf4j
@Primary
@Component
public class CustomFeignHystrixConcurrencyStrategy extends HystrixConcurrencyStrategy {

    public CustomFeignHystrixConcurrencyStrategy() {
        try {

            HystrixPlugins.getInstance().registerConcurrencyStrategy(this);

        } catch (Exception e) {
            log.error("Failed to register Sleuth Hystrix Concurrency Strategy", e);
        }
    }


    @Override
    public <T> Callable<T> wrapCallable(Callable<T> callable) {
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        return new WrappedCallable<>(callable, requestAttributes);
    }


    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;
        }

        /**
         * feign opens the fuse (hystrix): feign.hystrix.enabled=ture, and uses the default signal isolation level,
         * The HttpServletRequest object is independent of each other in the parent thread and the child thread and is not shared.
         * So the HttpServletRequest data of the parent thread used in the child thread is null,
         * naturally it is impossible to obtain the token information of the request header In a multithreaded environment, call before the request, set the context before the call
         *
         * feign启用了hystrix,并且feign.hystrix.enabled=ture。采用了线程隔离策略。
         * HttpServletRequest 请求在对象在父线程和子线程中相互独立,且不共享
         * 所以父线程的 HttpServletRequest 在子线程中为空,
         * 所以通常 在多线程环境中,在请求调用之前设置上下文
         * @return T
         * @throws Exception Exception
         */
        @Override
        public T call() throws Exception {
            try {
                // Set true to share the parent thread's HttpServletRequest object setting
                RequestContextHolder.setRequestAttributes(requestAttributes, true);
                return target.call();
            } finally {
                RequestContextHolder.resetRequestAttributes();
            }
        }
    }
}

 

 

 

 

 

标签:feign,调用,RequestContextHolder,token,线程,import,public
来源: https://www.cnblogs.com/ygreatred/p/15986657.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有