增加转发日志
This commit is contained in:
132
src/main/java/com/sczx/gateway/filter/LoggingGlobalFilter.java
Normal file
132
src/main/java/com/sczx/gateway/filter/LoggingGlobalFilter.java
Normal file
@ -0,0 +1,132 @@
|
||||
|
||||
package com.sczx.gateway.filter;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.reactivestreams.Publisher;
|
||||
import org.springframework.cloud.gateway.filter.GlobalFilter;
|
||||
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.core.io.buffer.DataBufferUtils;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
|
||||
import org.springframework.http.server.reactive.ServerHttpResponse;
|
||||
import org.springframework.http.server.reactive.ServerHttpResponseDecorator;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.ServerWebExchangeDecorator;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* 全局日志过滤器,用于打印请求路径、Header、Body 和响应状态码、Body。
|
||||
* 适用于 Spring Boot 2.3.x + Spring Cloud Hoxton.SR12 环境。
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class LoggingGlobalFilter implements GlobalFilter, Ordered {
|
||||
|
||||
@Override
|
||||
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
|
||||
// 包装请求体
|
||||
RequestBodyLogExchange requestLogExchange = new RequestBodyLogExchange(exchange);
|
||||
// 包装响应体
|
||||
ResponseBodyLogExchange responseLogExchange = new ResponseBodyLogExchange(exchange);
|
||||
|
||||
return chain.filter(requestLogExchange)
|
||||
.then(Mono.fromRunnable(() -> {
|
||||
String requestBody = requestLogExchange.getRequestBody();
|
||||
String responseBody = responseLogExchange.getResponseBody();
|
||||
|
||||
log.info("🌐 请求路径: {}", exchange.getRequest().getPath());
|
||||
log.info("📥 请求头: {}", exchange.getRequest().getHeaders());
|
||||
log.info("📥 请求体: {}", requestBody);
|
||||
log.info("🔚 响应状态: {}", exchange.getResponse().getStatusCode());
|
||||
log.info("📤 响应内容: {}", responseBody);
|
||||
}));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return Ordered.LOWEST_PRECEDENCE; // 最后执行
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求体拦截装饰器
|
||||
*/
|
||||
static class RequestBodyLogExchange extends ServerWebExchangeDecorator {
|
||||
|
||||
private final StringBuilder requestBody = new StringBuilder();
|
||||
|
||||
public RequestBodyLogExchange(ServerWebExchange delegate) {
|
||||
super(delegate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServerHttpRequest getRequest() {
|
||||
return new ServerHttpRequestDecorator(super.getRequest()) {
|
||||
@Override
|
||||
public Flux<DataBuffer> getBody() {
|
||||
return super.getBody().map(buffer -> {
|
||||
byte[] bytes = new byte[buffer.readableByteCount()];
|
||||
buffer.read(bytes);
|
||||
String chunk = new String(bytes, StandardCharsets.UTF_8);
|
||||
requestBody.append(chunk);
|
||||
DataBufferUtils.release(buffer); // 释放原始 buffer
|
||||
return buffer.factory().wrap(bytes); // 返回新的 buffer
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public String getRequestBody() {
|
||||
return requestBody.toString();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 响应体拦截装饰器(适配 Spring Boot 2.3.x)
|
||||
*/
|
||||
static class ResponseBodyLogExchange extends ServerWebExchangeDecorator {
|
||||
|
||||
private final StringBuilder responseBody = new StringBuilder();
|
||||
private final ServerWebExchange exchange; // 显式保存 exchange 引用
|
||||
|
||||
public ResponseBodyLogExchange(ServerWebExchange delegate) {
|
||||
super(delegate);
|
||||
this.exchange = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServerHttpResponse getResponse() {
|
||||
return new ServerHttpResponseDecorator(super.getResponse()) {
|
||||
@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.map(buffer -> {
|
||||
byte[] content = new byte[buffer.readableByteCount()];
|
||||
buffer.read(content);
|
||||
DataBufferUtils.release(buffer); // 释放原始 buffer
|
||||
|
||||
String responseStr = new String(content, StandardCharsets.UTF_8);
|
||||
responseBody.append(responseStr);
|
||||
|
||||
// ✅ 使用外部传入的 exchange 来设置 attribute
|
||||
exchange.getAttributes().put("responseBody", responseStr);
|
||||
|
||||
return buffer.factory().wrap(content); // 返回新 buffer
|
||||
}));
|
||||
}
|
||||
return super.writeWith(body);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public String getResponseBody() {
|
||||
return responseBody.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user