diff --git a/src/main/java/com/sczx/gateway/filter/LoggingGlobalFilter.java b/src/main/java/com/sczx/gateway/filter/LoggingGlobalFilter.java index 6130b79..988fd10 100644 --- a/src/main/java/com/sczx/gateway/filter/LoggingGlobalFilter.java +++ b/src/main/java/com/sczx/gateway/filter/LoggingGlobalFilter.java @@ -20,6 +20,7 @@ import org.springframework.web.server.ServerWebExchangeDecorator; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; +import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import java.util.UUID; @@ -64,7 +65,8 @@ public class LoggingGlobalFilter implements GlobalFilter, Ordered { private static class CustomExchange extends ServerWebExchangeDecorator implements CustomExchangeInterface { private final StringBuilder requestBody = new StringBuilder(); - private String responseBody; + private final StringBuilder responseBodyBuilder = new StringBuilder(); + public CustomExchange(ServerWebExchange delegate) { @@ -88,25 +90,31 @@ public class LoggingGlobalFilter implements GlobalFilter, Ordered { }; } + @Override public ServerHttpResponse getResponse() { - return new ServerHttpResponseDecorator(super.getResponse()) { - private final StringBuilder responseBodyBuilder = new StringBuilder(); + ServerHttpResponse originalResponse = super.getResponse(); + DataBufferFactory bufferFactory = originalResponse.bufferFactory(); + return new ServerHttpResponseDecorator(originalResponse) { @Override public Mono writeWith(Publisher body) { if (body instanceof Flux) { - return super.writeWith(Flux.from(body) - .doOnNext(buffer -> { - DataBufferUtils.join(Flux.just(buffer)) - .map(dataBuffer -> { - byte[] content = new byte[dataBuffer.readableByteCount()]; - dataBuffer.read(content); - responseBody = new String(content, StandardCharsets.UTF_8); - return dataBuffer; - }) - .subscribe(); - })); + Flux flux = (Flux) body; + return super.writeWith(flux.doOnNext(dataBuffer -> { + // 复制数据以避免修改原始缓冲区 + DataBuffer duplicate = dataBuffer.factory().allocateBuffer(dataBuffer.readableByteCount()); + duplicate.write(dataBuffer); + + // 读取数据内容用于日志记录 + byte[] bytes = new byte[duplicate.readableByteCount()]; + duplicate.read(bytes); + String bodyContent = new String(bytes, StandardCharsets.UTF_8); + responseBodyBuilder.append(bodyContent); + + // 释放复制的缓冲区 + DataBufferUtils.release(duplicate); + })); } return super.writeWith(body); } @@ -120,7 +128,7 @@ public class LoggingGlobalFilter implements GlobalFilter, Ordered { @Override public String getResponseBody() { - return responseBody; + return responseBodyBuilder.toString(); } } diff --git a/src/main/java/com/sczx/gateway/filter/ResponseLogGlobalFilter.java b/src/main/java/com/sczx/gateway/filter/ResponseLogGlobalFilter.java index 4065c69..44e2f27 100644 --- a/src/main/java/com/sczx/gateway/filter/ResponseLogGlobalFilter.java +++ b/src/main/java/com/sczx/gateway/filter/ResponseLogGlobalFilter.java @@ -23,6 +23,7 @@ import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; @@ -30,38 +31,46 @@ import java.util.List; //@Configuration public class ResponseLogGlobalFilter implements GlobalFilter, Ordered { + @Override public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) { try { ServerHttpResponse originalResponse = exchange.getResponse(); DataBufferFactory bufferFactory = originalResponse.bufferFactory(); HttpStatus statusCode = originalResponse.getStatusCode(); + + // 排除特定路径,避免处理Swagger等静态资源 + String path = exchange.getRequest().getURI().getPath(); + if (path.contains("/v2/api-docs") || + path.contains("/swagger") || + path.contains("/webjars")) { + return chain.filter(exchange); + } + if (statusCode != HttpStatus.OK) { return chain.filter(exchange);//降级处理返回数据 } + ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(originalResponse) { @Override public Mono writeWith(Publisher body) { if (body instanceof Flux) { Flux fluxBody = Flux.from(body); - return super.writeWith(fluxBody.buffer().map(dataBuffers -> { + return super.writeWith(fluxBody.map(dataBuffer -> { + // 复制数据以避免修改原始缓冲区 + byte[] content = new byte[dataBuffer.readableByteCount()]; + dataBuffer.read(content); + DataBufferUtils.release(dataBuffer); - // 合并多个流集合,解决返回体分段传输 - DataBufferFactory dataBufferFactory = new DefaultDataBufferFactory(); - DataBuffer buff = dataBufferFactory.join(dataBuffers); - byte[] content = new byte[buff.readableByteCount()]; - buff.read(content); - DataBufferUtils.release(buff);//释放掉内存 - - //排除Excel导出,不是application/json不打印。若请求是上传图片则在最上面判断。 + // 排除Excel导出,不是application/json不打印。若请求是上传图片则在最上面判断。 MediaType contentType = originalResponse.getHeaders().getContentType(); - if (!MediaType.APPLICATION_JSON.isCompatibleWith(contentType)) { + if (contentType == null || !MediaType.APPLICATION_JSON.isCompatibleWith(contentType)) { return bufferFactory.wrap(content); } // 构建返回日志 - String joinData = new String(content); + String joinData = new String(content, StandardCharsets.UTF_8); String result = modifyBody(joinData); List rspArgs = new ArrayList<>(); rspArgs.add(originalResponse.getStatusCode().value()); @@ -69,8 +78,8 @@ public class ResponseLogGlobalFilter implements GlobalFilter, Ordered { rspArgs.add(result); log.info("<-- {} {}\n{}", rspArgs.toArray()); - getDelegate().getHeaders().setContentLength(result.getBytes().length); - return bufferFactory.wrap(result.getBytes()); + // 返回处理后的内容 + return bufferFactory.wrap(result.getBytes(StandardCharsets.UTF_8)); })); } else { log.error("<-- {} 响应code异常", getStatusCode()); @@ -88,14 +97,23 @@ public class ResponseLogGlobalFilter implements GlobalFilter, Ordered { @Override public int getOrder() { - return Ordered.HIGHEST_PRECEDENCE; + // 设置较低优先级,确保在其他过滤器之后执行 + return Ordered.LOWEST_PRECEDENCE - 1; } //返回统一的JSON日期数据 2024-02-23 11:00, null转空字符串 private String modifyBody(String jsonStr){ - JSONObject json = JSON.parseObject(jsonStr, Feature.AllowISO8601DateFormat); - JSONObject.DEFFAULT_DATE_FORMAT = "yyyy-MM-dd HH:mm"; - return JSONObject.toJSONString(json, (ValueFilter) (object, name, value) -> value == null ? "" : value, SerializerFeature.WriteDateUseDateFormat); + if (jsonStr == null || jsonStr.isEmpty()) { + return jsonStr; + } + try { + JSONObject json = JSON.parseObject(jsonStr, Feature.AllowISO8601DateFormat); + JSONObject.DEFFAULT_DATE_FORMAT = "yyyy-MM-dd HH:mm"; + return JSONObject.toJSONString(json, (ValueFilter) (object, name, value) -> value == null ? "" : value, SerializerFeature.WriteDateUseDateFormat); + } catch (Exception e) { + // 如果不是有效的JSON,直接返回原始字符串 + return jsonStr; + } } }