解决方式:将请求头存入本地线程中
网上看了类似的Feign传输请求头的案例,同步发送的只需要加拦截器即可
/**
* feign 配置文件
* 将请求头中的参数,全部作为 feign 请求头参数传递
* @author: linjinp
* @create: 2020-06-28 09:54
**/
@Configuration
public class FeignConfiguration implements RequestInterceptor {
@Override
public void apply(RequestTemplate requestTemplate) {
HttpServletRequest request = SpringContextUtils.getHttpServletRequest();
Enumeration<String> headerNames = request.getHeaderNames();
if (headerNames != null) {
while (headerNames.hasMoreElements()) {
String name = headerNames.nextElement();
String values = request.getHeader(name);
requestTemplate.header(name, values);
}
}
}
}
转载于 Spring Cloud Feign 请求时附带请求头_乐之终曲的博客-CSDN博客_feign带请求头
异步调用采用了一些方式,类似于
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
传到子线程中,再重新赋值RequestContextHolder.setRequestAttributes(requestAttributes);
但是我用这种方法无法成功,但也给出了一些方案,通过获取请求头的方式来加载本地请求头。
首先是注册拦截器
import feign.RequestInterceptor;
import feign.RequestTemplate;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import java.util.Map;
@Configuration
@Slf4j
public class FeignHeaderInterceptor implements RequestInterceptor {
@Override
public void apply(RequestTemplate template) {
try {
//获取本地加载过的请求头
Map<String, String> headerMap = RequestHeaderHandler.getHeaderMap();
if (headerMap != null) {
for (String key : headerMap.keySet()) {
String values = headerMap.get(key);
template.header(key, values);
}
}
}catch (Exception e){
log.error("获取请求头失败->{}","FeignHeaderInterceptor");
log.error(e.getMessage());
}
}
}
第二步 构造两个工具类
import lombok.extern.slf4j.Slf4j;
import java.util.Map;
@Slf4j
public class RequestHeaderHandler {
public static final ThreadLocal<Map<String, String>> THREAD_LOCAL = new ThreadLocal<>();
public static void setHeaderMap(Map<String, String> headerMap) {
THREAD_LOCAL.set(headerMap);
}
public static Map<String, String> getHeaderMap() {
return THREAD_LOCAL.get();
}
public static void remove() {
THREAD_LOCAL.remove();
}
}
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
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.Map;
@Slf4j
public class RequestContextUtil {
/**
* 获取请求头数据
*
* @return key->请求头名称 value->请求头值
* @author
*/
public static Map<String, String> getHeaderMap() {
Map<String, String> headerMap = Maps.newLinkedHashMap();
try {
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if (requestAttributes == null) {
return headerMap;
}
HttpServletRequest request = requestAttributes.getRequest();
Enumeration<String> enumeration = request.getHeaderNames();
while (enumeration.hasMoreElements()) {
String key = enumeration.nextElement();
String value = request.getHeader(key);
headerMap.put(key, value);
}
} catch (Exception e) {
log.error("《RequestContextUtil》 获取请求头参数失败:", e);
}
return headerMap;
}
}
实战例子
手打案例 供参考
/**
*案例
**/
@Override
public void test() {
Map<String, String> headerMap = RequestContextUtil.getHeaderMap();
pool.execute(()->{
//共享之前分享的数据
RequestHeaderHandler.setHeaderMap(headerMap);
//todo 业务代码
});
}
参考连接:Error(17) 解决多线程异步Feign调用请求头丢失问题_郑清的博客-CSDN博客_多线程feign调用