在一般发送请求的过程中,我们会在请求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 {
@Override
public void apply(RequestTemplate template) {
//从RequestContextHolder中获取HttpServletRequest
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
//获取RequestContextHolder中的信息
Map headers = getHeaders(request);
//放入feign的RequestTemplate中
for (Map.Entry entry : headers.entrySet()) {
template.header(entry.getKey(), entry.getValue());
}
}
/**
* 获取原请求头
*/
private Map getHeaders(HttpServletRequest request) {
Map map = new LinkedHashMap<>();
Enumeration enumeration = request.getHeaderNames();
if (enumeration != null) {
while (enumeration.hasMoreElements()) {
String key = enumeration.nextElement();
String value = request.getHeader(key);
map.put(key, value);
}
}
return map;
}
}