在一般发送请求的过程中,我们会在请求Header中添加参数信息,如token认证、全局事物id、链路追踪的logid等。
但是使用openfeign后,默认不支持传递header头信息。
因此,需要借助额外的配置,让请求的Header中的参数令牌在微服务链路调用中传递下去,保证各个微服务能够获取令牌中的用户信息。
注意:openFeign在开启熔断降级后内部调用开启了子线程,因此传统的方案直接在RequestInterceptor中设置是不可行的。
RequestContextHolder内部通过InheritableThreadLocal实现子线程共享信息。
在FeignCircuitBreakerInvocationHandler这个类中也是有如下一行代码:
RequestContextHolder.setRequestAttributes(requestAttributes);
以下通过实现RequestInterceptor拦截器,读取请求中的参数信息,放入feign的RequestTemplate中,实现透传功能。
import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;import javax.servlet.http.HttpServletRequest;
import java.util.Enumeration;
import java.util.LinkedHashMap;
import java.util.Map;@Component
public class OpenFeignConfig implements RequestInterceptor {@Overridepublic void apply(RequestTemplate template) { //从RequestContextHolder中获取HttpServletRequestHttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();//获取RequestContextHolder中的信息Map<String, String> headers = getHeaders(request);//放入feign的RequestTemplate中for (Map.Entry<String, String> entry : headers.entrySet()) {template.header(entry.getKey(), entry.getValue());}}/*** 获取原请求头*/private Map<String, String> getHeaders(HttpServletRequest request) {Map<String, String> map = new LinkedHashMap<>();Enumeration<String> enumeration = request.getHeaderNames();if (enumeration != null) {while (enumeration.hasMoreElements()) {String key = enumeration.nextElement();String value = request.getHeader(key);map.put(key, value);}}return map;}
}