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
一定要注意字节数组的处理!!!