在項目中使用根據(jù)請求頭處理異常信息國際化的問題,但是在feign調(diào)用的時候無法傳遞請求頭添怔,這個問題看了好久最后才知道feign開啟hystrix默認(rèn)會新建一個線程,而我的請求頭數(shù)據(jù)是通過攔截器放到ThreadLocal里的在新線程就無法獲取了
先看一下原來是怎么實現(xiàn)的
首先是header封裝類
@Data
public class CommonRequestHeader {
/**
* version 版本號
*/
private String version;
/**
* 平臺類型
*/
private String platform;
}
把請求頭封裝到ThreadLocal中
@Data
public class CommonRequestHeaderHolder {
public static final ThreadLocal<CommonRequestHeader> context = new ThreadLocal<>();
public static void clear() {
context.set(null);
}
public static void setContext(CommonRequestHeader header) {
context.set(header);
}
public static CommonRequestHeader getContext() {
return context.get();
}
}
每次請求的時候通過filter封裝把請求頭數(shù)據(jù)放入context中
但是在feign中開啟hystrix的話新線程的ThreadLocal是無法獲取主線程的數(shù)據(jù)的钞啸,這個時候就要用到InheritableThreadLocal襟齿,只需要改一行代碼
private static final ThreadLocal<CommonRequestData> context = new InheritableThreadLocal<>();
InheritableThreadLocal是ThreadLocal的子類,可以解決父線程和子線程的數(shù)據(jù)傳輸問題
當(dāng)在主線程開啟一個新線程時寞冯,會執(zhí)行Thread的init方法
init方法中有這么一段代碼
if (inheritThreadLocals && parent.inheritableThreadLocals != null)
this.inheritableThreadLocals =
ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
當(dāng)父線程中的inheritableThreadLocal被賦值時渴析,會將當(dāng)前線程的inheritableThreadLocal變量進行createInheritedMap(),看一下這個方法的具體實現(xiàn)晚伙,它會繼續(xù)調(diào)用ThreadLocalMap(parentMap),主要的目的是父線程的變量值賦值給子線程。
關(guān)于ThreadLocal可以看一下 ThreadLocal源碼簡單了解