spring cloud gateway Response 修改bug

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

 

一定要注意字節數組的處理!!!

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章