gateway 实现接口日志保存

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

posted @ 2021-05-20 10:38  staystand  阅读(1409)  评论(0编辑  收藏  举报