丟失請求頭
feign遠程調(diào)用如果不對之進行增強价匠,則會丟失請求頭。
Feign遠程調(diào)用前麦牺,會通過遍歷容器中的Feign包下的攔截器RequestInterceptor判斷是否為當前的RequestTemplate進行增強。
遠程調(diào)用核心代碼
遍歷private final List<RequestInterceptor> requestInterceptors;
如果Spring容器中沒有裝配的RequestInterceptor的bean實例,則默認使用一個不增強的RequestTemplate运授,其header中沒有需要的請求頭。
解決方案
裝配一個RequestInterceptor 的bean實例乔煞,對RequestTemplate進行增強吁朦。
@Configuration
public class GuliFeignConfig {
@Bean
public RequestInterceptor requestInterceptor() {
return new RequestInterceptor() {
@Override
public void apply(RequestTemplate template) {
//1. 使用RequestContextHolder拿到老請求的請求數(shù)據(jù)
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if (requestAttributes != null) {
HttpServletRequest request = requestAttributes.getRequest();
if (request != null) {
//2. 將老請求得到cookie信息放到feign請求上
String cookie = request.getHeader("Cookie");
template.header("Cookie", cookie);
}
}
}
};
}
}
異步線程丟失上下文
異步調(diào)用的時候,第十一行會報空指針
@Configuration
public class GuliFeignConfig {
@Bean
public RequestInterceptor requestInterceptor() {
return new RequestInterceptor() {
@Override
public void apply(RequestTemplate template) {
//1. 使用RequestContextHolder拿到老請求的請求數(shù)據(jù)
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if (requestAttributes != null) {
HttpServletRequest request = requestAttributes.getRequest();
if (request != null) {
//2. 將老請求得到cookie信息放到feign請求上
String cookie = request.getHeader("Cookie");
template.header("Cookie", cookie);
}
}
}
};
}
}
因為異步調(diào)用會創(chuàng)建新線程渡贾,無法獲取主線程的數(shù)據(jù)逗宜。
解決辦法
利用RequestContextHolder通過ThreadLocal共享數(shù)據(jù)的特性,先在主線程中獲取主線程的RequestAttributes,后在子線程中RequestContextHolder.setRequestAttributes(requestAttributes);
@Override
public ResponseResult<OrderConfirm> confirmOrder() {
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
CompletableFuture<Object> objectFuture = CompletableFuture.supplyAsync(() -> {
RequestContextHolder.setRequestAttributes(requestAttributes);
//xxxx
return Object;
}, executor);
}
}