spring cloud gateway Response修改後,返回值中及個別字符亂碼。
相信很多人接觸了spring cloud gateway,但是少數人會真正把它直接用在項目上,我們的新項目快上線了,整個開發過程中遇到了很多問題,簡單說一下感受,現階段spring cloud gateway相關資料太少,很多東西查不到,很多時候需要自己去看源碼自己去仿照源碼重新去寫,而且大坑往往更是查不到。
spring cloud gateway Response 修改並不被官方推薦,但是我們有一個需求,就是在網關內對某些特殊的字符進行替換,而且完全替換,相信這種需求很多人都遇到過,但是有N種實現方式,而我想到的最簡單的方式就是在網關內對response進行修改替換了,這也是爲大坑埋下了伏筆。
上圖看現象:
一包返回值中僅出現一箇中文字符亂碼。
但是多個接口中出現了同樣的現象!!!
又不是每個接口都發生問題。
給人的感受,這不像是編碼問題,感覺好像是返回值因爲數據量過長,在處理時進行拆分處理的過程中遇到了問題。
但是後來,通過對比原始數據的字節數組發現了問題。
可以看出,原始返回值僅經過轉換未做任何處理時,已經出現了問題,這是字節數組,最後幾位發生了變化。
這個問題感覺好像還是字節數組和字符串相互轉換時發生了問題。
上代碼:(這是已經解決問題了的代碼)
ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(originalResponse) {
@Override
public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
if (HttpStatus.OK.equals(getStatusCode()) && body instanceof Flux) {
Flux<? extends DataBuffer> fluxBody = Flux.from(body);
return super.writeWith(fluxBody.buffer().map(dataBuffers -> {
StringBuffer stringBuffer = new StringBuffer();
dataBuffers.forEach(dataBuffer -> {
byte[] content = new byte[dataBuffer.readableByteCount()];
dataBuffer.read(content);
DataBufferUtils.release(dataBuffer);
String tempStr = new String(content, Charset.forName("ISO_8859_1"));
stringBuffer.append(tempStr);
});
String str = new String(stringBuffer);
String fileKey = "\":\"" + Const.DATA_BASE_FILE_URL_HEAD + Const.M00;
if (str.contains(fileKey)) {
//修改
String value = "\":\"" + Const.SYSTEMS_FILE_URL_HEAD + Const.DATA_BASE_FILE_URL_HEAD + Const.M00;
str = str.replaceAll(fileKey, value);
}
byte[] content = str.getBytes(Charset.forName("ISO_8859_1"));
return bufferFactory().wrap(content);
}));
}
// if body is not a flux. never got there.
return super.writeWith(body);
}
};
百度一大堆都是寫的UTF-8,其實這是有問題的。
由於 UTF-8 是多字節編碼,需要用多個字節來表示一個字符的編碼,所以也就出現了在轉換之後 byte[] 數組長度、內容不一致的情況。而 ISO-8859-1 編碼是單字節編碼,所以使用該編碼就不會出現問題。
因此這裏一定要用ISO-8859-1編碼,百度一大堆卻沒一個對的,相信大多數都是demo,並沒有發現問題。
參考:
https://blog.csdn.net/qq_27760433/article/details/78327328
一定要注意字節數組的處理!!!