经由网关层的接口返回的json数据中偶尔出现中文乱码的问题
一、问题如下
页面出现乱码问题,且是偶发性的,不定时出现一次。
二、问题定位
- 排查编码格式: 前端、后台、数据库都为UTF-8,基本排除由于编码格式问题引起的乱码。
- 定位乱码位置: 前端页面显示乱码,应用服务日志正常,网关服务日志乱码。在网上查阅了一些资料,终于定位了问题就在gateway网关对response的处理上。
三、问题处理:
// 原代码
serverHttpResponse.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
DataBufferFactory bufferFactory = serverHttpResponse.bufferFactory();
ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(serverHttpResponse) {
@Override
public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
if (body instanceof Flux) {
Flux<? extends DataBuffer> fluxBody = (Flux<? extends DataBuffer>) body;
return super.writeWith(fluxBody.buffer().map(dataBuffers -> {
List<String> list = Lists.newArrayList();
dataBuffers.forEach(dataBuffer -> {
byte[] content = new byte[dataBuffer.readableByteCount()];
dataBuffer.read(content);
DataBufferUtils.release(dataBuffer);
list.add(new String(content, Charset.forName("UTF-8")));
});
String resp = joiner.join(list);
byte[] uppedContent = new String(resp.getBytes(), Charset.forName("UTF-8")).getBytes();
return bufferFactory.wrap(uppedContent);
}));
}
return super.writeWith(body);
}
};
处理方法一: 结果报错
serverHttpResponse.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
DataBufferFactory bufferFactory = serverHttpResponse.bufferFactory();
ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(serverHttpResponse) {
@Override
public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
if (body instanceof Flux) {
Flux<? extends DataBuffer> fluxBody = (Flux<? extends DataBuffer>) body;
return super.writeWith(fluxBody.buffer().map(dataBuffers -> {
List<String> list = Lists.newArrayList();
dataBuffers.forEach(dataBuffer -> {
DataBufferFactory dataBufferFactory = new DefaultDataBufferFactory();
DataBuffer join = dataBufferFactory.join(dataBuffers);
byte[] content = new byte[join.readableByteCount()];
join.read(content);
DataBufferUtils.release(join);
list.add(new String(content, Charset.forName("UTF-8")));
});
String resp = joiner.join(list);
byte[] uppedContent = new String(resp.getBytes(), Charset.forName("UTF-8")).getBytes();
return bufferFactory.wrap(uppedContent);
}));
}
return super.writeWith(body);
}
};
io.netty.util.IllegalReferenceCountException: refCnt: 0
at io.netty.buffer.AbstractByteBuf.ensureAccessible(AbstractByteBuf.java:1489)
Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Error has been observed at the following site(s):
|_ checkpoint ⇢ org.springframework.cloud.gateway.filter.WeightCalculatorWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.cloud.sleuth.instrument.web.TraceWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.boot.actuate.metrics.web.reactive.server.MetricsWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ HTTP POST "/*****/****/*****/*****?timestamp=****&nonce=****&signature=******" [ExceptionHandlingWebHandler]
Stack trace:
at io.netty.buffer.AbstractByteBuf.ensureAccessible(AbstractByteBuf.java:1489)
at io.netty.buffer.AbstractByteBuf.checkIndex(AbstractByteBuf.java:1418)
at io.netty.buffer.PooledByteBuf.duplicateInternalNioBuffer(PooledByteBuf.java:194)
at io.netty.buffer.PooledByteBuf.nioBuffer(PooledByteBuf.java:211)
at io.netty.buffer.PooledSlicedByteBuf.nioBuffer(PooledSlicedByteBuf.java:89)
at io.netty.buffer.AbstractByteBuf.nioBuffer(AbstractByteBuf.java:1232)
at org.springframework.core.io.buffer.NettyDataBuffer.asByteBuffer(NettyDataBuffer.java:273)
at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
at java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:482)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:472)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:546)
at java.util.stream.AbstractPipeline.evaluateToArrayNode(AbstractPipeline.java:260)
at java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:505)
at org.springframework.core.io.buffer.DefaultDataBuffer.write(DefaultDataBuffer.java:308)
at org.springframework.core.io.buffer.DefaultDataBufferFactory.lambda$join$0(DefaultDataBufferFactory.java:113)
at java.util.ArrayList.forEach(ArrayList.java:1257)
at org.springframework.core.io.buffer.DefaultDataBufferFactory.join(DefaultDataBufferFactory.java:113)
at org.springframework.core.io.buffer.DefaultDataBufferFactory.join(DefaultDataBufferFactory.java:32)
at com.taikang.grouppolicy.gateway.filter.AuthFilter$1.lambda$null$0(AuthFilter.java:168)
at java.util.ArrayList.forEach(ArrayList.java:1257)
at com.taikang.grouppolicy.gateway.filter.AuthFilter$1.lambda$writeWith$1(AuthFilter.java:166)
at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:100)
at org.springframework.cloud.sleuth.instrument.reactor.ScopePassingSpanSubscriber.onNext(ScopePassingSpanSubscriber.java:90)
at reactor.core.publisher.FluxBuffer$BufferExactSubscriber.onComplete(FluxBuffer.java:179)
处理方法二: 目前正常
serverHttpResponse.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
DataBufferFactory bufferFactory = serverHttpResponse.bufferFactory();
ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(serverHttpResponse) {
@Override
public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
if (body instanceof Flux) {
Flux<? extends DataBuffer> fluxBody = (Flux<? extends DataBuffer>) body;
return super.writeWith(fluxBody.buffer().map(dataBuffers -> {
DataBufferFactory dataBufferFactory = new DefaultDataBufferFactory();
DataBuffer join = dataBufferFactory.join(dataBuffers);
byte[] content = new byte[join.readableByteCount()];
join.read(content);
DataBufferUtils.release(join);
String resp=new String(content, Charset.forName("UTF-8"));
byte[] uppedContent = new String(resp.getBytes(), Charset.forName("UTF-8")).getBytes(StandardCharsets.UTF_8);
return bufferFactory.wrap(uppedContent);
}));
}
return super.writeWith(body);
}
};