app开发定制SpringCloud Gateway 打印请求响应日志

不是基于springmvc的,而是基于webflux去做的
SpringCloudGateway中Postapp开发定制请求参数只能读取一次
这是因为Gatewayapp开发定制默认使用的是SpringWebflux,app开发定制解决这个问题需要容重新构造一个request来替换原先的request

全局过滤器把原有的request请求中的body内容读出来,并且使用ServerHttpRequestDecorator这个请求装饰器对request进行包装,重写getBody方法,并把包装后的请求放到过滤器链中传递下去。
//这样后面的过滤器中再使用exchange.getRequest().getBody()来获取body时,实际上就是调用的重载后的getBody方法,获取的最先已经缓存了的body数据。这样就能够实现body的多次读取了。
//过滤器的Ordered.HIGHEST_PRECEDENCE,即最高优先级的过滤器。优先级设置高的原因是某些系统内置的过滤器可能也会去读body。

Request log

@Configurationpublic class RequestLogGlobalFilter implements GlobalFilter, Ordered {    @Override    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {        ServerHttpRequest request = exchange.getRequest();        URI uri = request.getURI();        //String path = request.getPath().value();        String path = request.getPath().pathWithinApplication().value();//打印请求路径        String requestUrl = this.getOriginalRequestUrl(exchange);//打印请求url        String method = request.getMethodValue();        //cors        HttpHeaders headers = request.getHeaders();        //        if(CorsUtils.isCorsRequest(request)){//            log.info("---> isCorsRequest Access");//            headers.add("Access-Control-Allow-Origin", "*");//            headers.add("Access-Control-Allow-Methods", "*");//            headers.add("Access-Control-Max-Age", "18000L");//            headers.add("Access-Control-Allow-Headers", "*");//            headers.add("Access-Control-Expose-Headers", "*");//            headers.add("Access-Control-Allow-Credentials", "true");//        }        log.info("---> method: {} URI: {} header: {}", method, requestUrl, headers);        if ("POST".equals(method)) {            return DataBufferUtils.join(exchange.getRequest().getBody())                    .flatMap(dataBuffer -> {                        byte[] bytes = new byte[dataBuffer.readableByteCount()];                        dataBuffer.read(bytes);                        String bodyString = new String(bytes, StandardCharsets.UTF_8);                        log.info("---> {}", bodyString);                        exchange.getAttributes().put("POST_BODY", bodyString);                        DataBufferUtils.release(dataBuffer);                        Flux<DataBuffer> cachedFlux = Flux.defer(() -> {                            DataBuffer buffer = exchange.getResponse().bufferFactory().wrap(bytes);                            return Mono.just(buffer);                        });                        ServerHttpRequest mutatedRequest = new ServerHttpRequestDecorator(request) {                            @Override                            public Flux<DataBuffer> getBody() {                                return cachedFlux;                            }                        };                        //log.info("****************************************************************************\");                        return chain.filter(exchange.mutate().request(mutatedRequest).build());                    });        } else if ("GET".equals(method)) {            MultiValueMap<String, String> queryParams = request.getQueryParams();            log.info("请求参数:" + queryParams);            //log.info("****************************************************************************\");            return chain.filter(exchange);        }        return chain.filter(exchange);    }    private String getOriginalRequestUrl(ServerWebExchange exchange) {        ServerHttpRequest req = exchange.getRequest();        LinkedHashSet<URI> uris = exchange.getRequiredAttribute(ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR);        URI requestUri = uris.stream().findFirst().orElse(req.getURI());        MultiValueMap<String, String> queryParams = req.getQueryParams();        //打印 /api/rest/feign/order/detail        // return UriComponentsBuilder.fromPath(requestUri.getRawPath()).queryParams(queryParams).build().toUriString();        return requestUri.toString(); // http://localhost:8091/api/rest/feign/order/detail    }    @Override    public int getOrder() {        return Ordered.LOWEST_PRECEDENCE;    }//    @Bean //https://www.pudn.com/news/6250847e74bc5c01056623c1.html//    public CorsWebFilter corsWebFilter() {//        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource (new PathPatternParser());//        CorsConfiguration corsConfig = new CorsConfiguration ();//        // 允许所有请求方法//        corsConfig.addAllowedMethod ("*");//        // 允许所有域,当请求头//        corsConfig.addAllowedOrigin ("*");//        // 允许全部请求头//        corsConfig.addAllowedHeader ("*");//        // 允许携带 Cookie 等用户凭证//        corsConfig.setAllowCredentials (true);//        // 允许全部请求路径//        source.registerCorsConfiguration ("/**", corsConfig);//        return new CorsWebFilter (source);//    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91

Response log

@Configurationpublic class ResponseLogGlobalFilter implements GlobalFilter, Ordered {    @Override    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {        try {            ServerHttpResponse originalResponse = exchange.getResponse();            DataBufferFactory bufferFactory = originalResponse.bufferFactory();            HttpStatus statusCode = originalResponse.getStatusCode();            if(statusCode == HttpStatus.OK){                ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(originalResponse) {                    @Override                    public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {                        //log.info("body instanceof Flux: {}", (body instanceof Flux));                        if (body instanceof Flux) {                            Flux<? extends DataBuffer> fluxBody = Flux.from(body);                            //                            return super.writeWith(fluxBody.map(dataBuffer -> {                                byte[] content = new byte[dataBuffer.readableByteCount()];                                dataBuffer.read(content);                                DataBufferUtils.release(dataBuffer);//释放掉内存                                // 构建日志                                StringBuilder sb2 = new StringBuilder(200);                                sb2.append("<--- {} {} \");                                List<Object> rspArgs = new ArrayList<>();                                rspArgs.add(originalResponse.getStatusCode());                                //rspArgs.add(requestUrl);                                String data = new String(content, StandardCharsets.UTF_8);//data                                sb2.append(data);                                log.info(sb2.toString(), rspArgs.toArray());//log.info("<-- {} {}\", originalResponse.getStatusCode(), data);                                return bufferFactory.wrap(content);                            }));                        } else {                            log.error("<--- {} 响应code异常", getStatusCode());                        }                        return super.writeWith(body);                    }                };                return chain.filter(exchange.mutate().response(decoratedResponse).build());            }            return chain.filter(exchange);//降级处理返回数据        }catch (Exception e){            log.error("gateway log exception.\" + e);            return chain.filter(exchange);        }    }    @Override    public int getOrder() {        return Ordered.HIGHEST_PRECEDENCE;    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55

SpringCloud Gateway 请求响应日志打印

参考资料
SpringCloud Gateway 打印请求和响应信息
https://blog.csdn.net/liben0429/article/details/126106528

Gateway网关日志
https://blog.csdn.net/small_to_large/article/details/125326498

https://www.jb51.net/article/240256.htm
https://blog.csdn.net/chaojunma/article/details/122595612

http://t.zoukankan.com/lifengdi-p-12524092.html

https://www.51ufo.cn/%E5%88%86%E5%B8%83%E5%BC%8F/2021/12/23/SpringCloud-Gateway%E7%BD%91%E5%85%B3%E6%94%B6%E9%9B%86%E8%AF%B7%E6%B1%82%E6%97%A5%E5%BF%97.html

乱码问题处理
https://blog.csdn.net/qq_38380025/article/details/100032490

https://www.icode9.com/content-4-1302983.html

网站建设定制开发 软件系统开发定制 定制软件开发 软件开发定制 定制app开发 app开发定制 app开发定制公司 电商商城定制开发 定制小程序开发 定制开发小程序 客户管理系统开发定制 定制网站 定制开发 crm开发定制 开发公司 小程序开发定制 定制软件 收款定制开发 企业网站定制开发 定制化开发 android系统定制开发 定制小程序开发费用 定制设计 专注app软件定制开发 软件开发定制定制 知名网站建设定制 软件定制开发供应商 应用系统定制开发 软件系统定制开发 企业管理系统定制开发 系统定制开发