1.CachePostBodyFilter将request body 取出来重存
import io.netty.buffer.UnpooledByteBufAllocator;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.NettyDataBufferFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.server.HandlerStrategies;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@Component
public class CachePostBodyFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest serverHttpRequest = exchange.getRequest();
String method = serverHttpRequest.getMethodValue();
if ("POST".equalsIgnoreCase(method)) {
ServerRequest serverRequest = ServerRequest.create(exchange, HandlerStrategies.withDefaults().messageReaders());
Mono<String> bodyToMono = serverRequest.bodyToMono(String.class);
return bodyToMono.flatMap(body -> {
exchange.getAttributes().put("cachedRequestBody", body);
ServerHttpRequest newRequest = new ServerHttpRequestDecorator(serverHttpRequest) {
@Override
public HttpHeaders getHeaders() {
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.putAll(super.getHeaders());
httpHeaders.set(HttpHeaders.TRANSFER_ENCODING, "chunked");
return httpHeaders;
}
@Override
public Flux<DataBuffer> getBody() {
NettyDataBufferFactory nettyDataBufferFactory = new NettyDataBufferFactory(new UnpooledByteBufAllocator(false));
DataBuffer bodyDataBuffer = nettyDataBufferFactory.wrap(body.getBytes());
return Flux.just(bodyDataBuffer);
}
};
return chain.filter(exchange.mutate().request(newRequest).build());
});
}
return chain.filter(exchange);
}
@Override
public int getOrder() {
return -21;
}
}
2.LogFilter 收集请求参数和返回参数
import com.alibaba.fastjson.JSONObject;
import com.msl.mafa.entity.RequestLog;
import com.msl.mafa.service.IRequestLogService;
import com.msl.mafa.utils.DateTimeUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.reactivestreams.Publisher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.http.server.reactive.ServerHttpResponseDecorator;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.nio.charset.Charset;
import java.util.Date;
@Slf4j
@Component
public class LogFilter implements GlobalFilter, Ordered {
@Autowired
private IRequestLogService iRequestLogService;
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
try {
Date startTime = DateTimeUtil.getFormattedDate(new Date(),DateTimeUtil.yyyyMMddHHmmss);
StringBuilder logBuilder = new StringBuilder();
StringBuilder requestBody=new StringBuilder();
ServerHttpRequest serverHttpRequest = exchange.getRequest();
String method = serverHttpRequest.getMethodValue().toUpperCase();
logBuilder.append(method).append(",").append(serverHttpRequest.getURI());
if ("POST".equals(method)) {
requestBody.append(exchange.getAttributeOrDefault("cachedRequestBody", ""));
if (StringUtils.isNotBlank(requestBody)) {
logBuilder.append(",body=").append(requestBody);
}
}else if("GET".equals(method)){
MultiValueMap<String, String> queryParams = serverHttpRequest.getQueryParams();
logBuilder.append(",body=").append(JSONObject.toJSONString(queryParams));
requestBody.append(JSONObject.toJSONString(queryParams));
}
ServerHttpResponse serverHttpResponse = exchange.getResponse();
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.map(dataBuffer -> {
byte[] content = new byte[dataBuffer.readableByteCount()];
dataBuffer.read(content);
DataBufferUtils.release(dataBuffer);
try {
String resp = new String(content, Charset.forName("UTF-8"));
Date endTime = DateTimeUtil.getFormattedDate(new Date(),DateTimeUtil.yyyyMMddHHmmss);
//保存日志到数据库
buildLog(exchange, requestBody.toString(),resp,startTime,endTime);
logBuilder.append(",resp=").append(resp);
}catch (Exception e){
log.info("save log err!");
log.info(e.getMessage(),e);
}
log.info(logBuilder.toString());
byte[] uppedContent = new String(content, Charset.forName("UTF-8")).getBytes();
return bufferFactory.wrap(uppedContent);
}));
}
return super.writeWith(body);
}
};
return chain.filter(exchange.mutate().response(decoratedResponse).build());
}catch (Exception e){
log.info("logfilter exception!");
log.info(e.getMessage(),e);
}
return chain.filter(exchange);
}
@Override
public int getOrder() {
return -20;
}
参考:https://blog.csdn.net/autfish/article/details/90637957?utm_medium=distribute.pc_relevant_t0.none-task-blog-2~default~BlogCommendFromMachineLearnPai2~default-1.control&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2~default~BlogCommendFromMachineLearnPai2~default-1.control