iis服务器助手广告广告
返回顶部
首页 > 资讯 > 数据库 >如何实现SpringCloud Gateway请求响应日志
  • 198
分享到

如何实现SpringCloud Gateway请求响应日志

2024-04-02 19:04:59 198人浏览 薄情痞子
摘要

这篇文章主要讲解了“如何实现SpringCloud Gateway请求响应日志”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“如何实现springCloud

这篇文章主要讲解了“如何实现SpringCloud Gateway请求响应日志”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“如何实现springCloud Gateway请求响应日志”吧!

如何实现SpringCloud Gateway请求响应日志

获取输入输出参数

首先我们先定义一个日志体

@Data public class GatewayLog {          private String targetServer;          private String requestPath;          private String requestMethod;          private String schema;          private String requestBody;          private String responseData;          private String ip;       private Date requestTime;       private Date responseTime;          private long executeTime; }

【关键】在网关定义日志过滤器,获取输入输出参数

 @Slf4j @Component public class AccessLogFilter implements GlobalFilter, Ordered {     @Autowired     private AccessLogService accessLogService;      private final List<HttpMessageReader<?>> messageReaders = HandlerStrategies.withDefaults().messageReaders();      @Override     public int getOrder() {         return -100;     }      @Override     @SuppressWarnings("unchecked")     public Mono<Void> filter(ServerWEBExchange exchange, GatewayFilterChain chain) {          ServerHttpRequest request = exchange.getRequest();          // 请求路径         String requestPath = request.getPath().pathWithinApplication().value();          Route route = getGatewayRoute(exchange);           String ipAddress = WebUtils.getServerHttpRequestIpAddress(request);          GatewayLog gatewayLog = new GatewayLog();         gatewayLog.setSchema(request.getURI().getScheme());         gatewayLog.setRequestMethod(request.getMethodValue());         gatewayLog.setRequestPath(requestPath);         gatewayLog.setTargetServer(route.getId());         gatewayLog.setRequestTime(new Date());         gatewayLog.setIp(ipAddress);          MediaType mediaType = request.getHeaders().getContentType();          if(MediaType.APPLICATION_FORM_URLENCODED.isCompatibleWith(mediaType) || MediaType.APPLICATION_JSON.isCompatibleWith(mediaType)){             return writeBodyLog(exchange, chain, gatewayLog);         }else{             return writeBasicLog(exchange, chain, gatewayLog);         }     }      private Mono<Void> writeBasicLog(ServerWebExchange exchange, GatewayFilterChain chain, GatewayLog accessLog) {         StringBuilder builder = new StringBuilder();         MultiValueMap<String, String> queryParams = exchange.getRequest().getQueryParams();         for (Map.Entry<String, List<String>> entry : queryParams.entrySet()) {             builder.append(entry.geTKEy()).append("=").append(StringUtils.join(entry.getValue(), ","));         }         accessLog.setRequestBody(builder.toString());          //获取响应体         ServerHttpResponseDecorator decoratedResponse = recordResponseLog(exchange, accessLog);          return chain.filter(exchange.mutate().response(decoratedResponse).build())                 .then(Mono.fromRunnable(() -> {                     // 打印日志                     writeAccessLog(accessLog);                 }));     }            @SuppressWarnings("unchecked")     private Mono writeBodyLog(ServerWebExchange exchange, GatewayFilterChain chain, GatewayLog gatewayLog) {         ServerRequest serverRequest = ServerRequest.create(exchange,messageReaders);          Mono<String> modifiedBody = serverRequest.bodyToMono(String.class)                 .flatMap(body ->{                     gatewayLog.setRequestBody(body);                     return Mono.just(body);                 });          // 通过 BodyInserter 插入 body(支持修改body), 避免 request body 只能获取一次         BodyInserter bodyInserter = BodyInserters.fromPublisher(modifiedBody, String.class);         HttpHeaders headers = new HttpHeaders();         headers.putAll(exchange.getRequest().getHeaders());         // the new content type will be computed by bodyInserter         // and then set in the request decorator         headers.remove(HttpHeaders.CONTENT_LENGTH);          CachedBodyOutputMessage outputMessage = new CachedBodyOutputMessage(exchange, headers);          return bodyInserter.insert(outputMessage,new BodyInserterContext())                 .then(Mono.defer(() -> {                     // 重新封装请求                     ServerHttpRequest decoratedRequest = requestDecorate(exchange, headers, outputMessage);                      // 记录响应日志                     ServerHttpResponseDecorator decoratedResponse = recordResponseLog(exchange, gatewayLog);                      // 记录普通的                     return chain.filter(exchange.mutate().request(decoratedRequest).response(decoratedResponse).build())                             .then(Mono.fromRunnable(() -> {                                 // 打印日志                                 writeAccessLog(gatewayLog);                             }));                 }));     }           private void writeAccessLog(GatewayLog gatewayLog) {         log.info(gatewayLog.toString());       }        private Route getGatewayRoute(ServerWebExchange exchange) {         return exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR);     }            private ServerHttpRequestDecorator requestDecorate(ServerWebExchange exchange, HttpHeaders headers,                                                        CachedBodyOutputMessage outputMessage) {         return new ServerHttpRequestDecorator(exchange.getRequest()) {             @Override             public HttpHeaders getHeaders() {                 long contentLength = headers.getContentLength();                 HttpHeaders httpHeaders = new HttpHeaders();                 httpHeaders.putAll(super.getHeaders());                 if (contentLength > 0) {                     httpHeaders.setContentLength(contentLength);                 } else {                     // TODO: this causes a 'HTTP/1.1 411 Length Required' // on                     // httpbin.org                     httpHeaders.set(HttpHeaders.TRANSFER_ENcoding, "chunked");                 }                 return httpHeaders;             }              @Override             public Flux<DataBuffer> getBody() {                 return outputMessage.getBody();             }         };     }            private ServerHttpResponseDecorator recordResponseLog(ServerWebExchange exchange, GatewayLog gatewayLog) {         ServerHttpResponse response = exchange.getResponse();         DataBufferFactory bufferFactory = response.bufferFactory();          return new ServerHttpResponseDecorator(response) {             @Override             public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {                 if (body instanceof Flux) {                     Date responseTime = new Date();                     gatewayLog.setResponseTime(responseTime);                     // 计算执行时间                     long executeTime = (responseTime.getTime() - gatewayLog.getRequestTime().getTime());                      gatewayLog.setExecuteTime(executeTime);                      // 获取响应类型,如果是 json 就打印                     String originalResponseContentType = exchange.getAttribute(ServerWebExchangeUtils.ORIGINAL_RESPONSE_CONTENT_TYPE_ATTR);                       if (ObjectUtil.equal(this.getStatusCode(), httpstatus.OK)                             && StringUtil.isNotBlank(originalResponseContentType)                             && originalResponseContentType.contains("application/json")) {                          Flux<? extends DataBuffer> fluxBody = Flux.from(body);                         return super.writeWith(fluxBody.buffer().map(dataBuffers -> {                              // 合并多个流集合,解决返回体分段传输                             DataBufferFactory dataBufferFactory = new DefaultDataBufferFactory();                             DataBuffer join = dataBufferFactory.join(dataBuffers);                             byte[] content = new byte[join.readableByteCount()];                             join.read(content);                              // 释放掉内存                             DataBufferUtils.release(join);                             String responseResult = new String(content, StandardCharsets.UTF_8);                                gatewayLog.setResponseData(responseResult);                              return bufferFactory.wrap(content);                         }));                     }                 }                 // if body is not a flux. never Got there.                 return super.writeWith(body);             }         };     } }

代码较长建议直接拷贝到编辑器,只要注意下面一个关键点:

getOrder()方法返回的值必须要<-1,「否则标准的NettyWriteResponseFilter将在您的过滤器被调用的机会之前发送响应,即不会执行获取后端响应参数的方法」

通过上面的两步我们已经可以获取到请求的输入输出参数了,在  writeAccessLog()中将其输出到了日志文件,大家可以在Postman发送请求观察日志。

存储日志

如果需要将日志持久化方便后期检索的话可以考虑将日志存储在mongoDB中,实现过程很简单。(安装MongoDB可以参考这篇文章:实战|MongoDB的安装配置)

  • 引入MongoDB

<dependency>     <groupId>org.springframework.boot</groupId>     <artifactId>spring-boot-starter-data-mongodb-Reactive</artifactId> </dependency>

由于gateway是基于webflux,所以我们需要选择reactive版本。

  • 在GatewayLog上添加对应的注解

@Data @Document public class GatewayLog {     @Id     private String id;  ... }
  • 建立AccessLogRepository

@Repository public interface AccessLogRepository extends ReactiveMongoRepository<GatewayLog,String> {    }
  • 建立Service

public interface AccessLogService {           Mono<GatewayLog> saveAccessLog(GatewayLog gatewayLog);  }
  • 建立实现类

@Service public class AccessLogServiceImpl implements AccessLogService {     @Autowired     private AccessLogRepository accessLogRepository;      @Override     public Mono<GatewayLog> saveAccessLog(GatewayLog gatewayLog) {         return accessLogRepository.insert(gatewayLog);     } }
  • Nacos配置中心添加MongoDB对应配置

spring:   data:     mongodb:       host: xxx.xx.x.xx       port: 27017       database: accesslog       username: accesslog       passWord: xxxxxx

执行请求,打开MongoDB客户端,查看日志结果

如何实现SpringCloud Gateway请求响应日志

感谢各位的阅读,以上就是“如何实现SprinGCloud Gateway请求响应日志”的内容了,经过本文的学习后,相信大家对如何实现SpringCloud Gateway请求响应日志这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程网,小编将为大家推送更多相关知识点的文章,欢迎关注!

您可能感兴趣的文档:

--结束END--

本文标题: 如何实现SpringCloud Gateway请求响应日志

本文链接: https://www.lsjlt.com/news/61592.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 如何实现SpringCloud Gateway请求响应日志
    这篇文章主要讲解了“如何实现SpringCloud Gateway请求响应日志”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“如何实现SpringCloud ...
    99+
    2022-10-18
  • SpringCloud Gateway之请求应答日志打印方式
    目录Gateway请求应答日志打印第一步第二步Gateway全局请求日志打印把请求体的数据存入exchange编写全局日志拦截器代码在代码中配置全局拦截器Gateway请求应答日志打...
    99+
    2022-11-13
  • Spring Cloud gateway 网关如何拦截Post请求日志
    gateway版本是 2.0.1 1.pom结构 (部分内部项目依赖已经隐藏) <dependency> <groupId>org.springf...
    99+
    2022-11-12
  • 如何使用PHP实现同步HTTP请求并记录请求日志?
    PHP是一种流行的编程语言,它被广泛应用于Web开发领域。在Web开发中,我们通常需要使用HTTP请求与其他服务进行通信。本文将介绍如何使用PHP实现同步HTTP请求并记录请求日志,希望对你有所帮助。 一、PHP实现同步HTTP请求 在PH...
    99+
    2023-09-03
    同步 http 日志
  • Netty4之如何实现HTTP请求、响应
    目录前言1.Netty中HTTP请求和响应类2.Netty中客户端、服务端的编解码器3.Server端编写Handler类处理客户请求4.测试总结前言 我们所编写的项目多以BS为主,...
    99+
    2023-05-14
    Netty4 HTTP请求 Netty4 HTTP响应
  • 实时日志如何影响ASP响应?
    ASP是一种基于服务器端脚本语言的Web开发技术,它使用VBScript或JScript脚本语言来创建动态网页。ASP应用程序处理大量的请求和响应,因此优化ASP响应的速度非常重要。本文将探讨实时日志如何影响ASP响应。 日志记录是Web...
    99+
    2023-07-21
    响应 实时 日志
  • ASP如何响应实时日志?
    随着互联网的快速发展和技术的不断进步,日志文件对于网站运营和维护变得越来越重要。ASP是一种非常流行的动态网站开发技术,而实时日志是一种非常有用的工具,可以帮助网站管理员更好地了解网站的运行情况,及时发现问题并进行处理。本文将介绍如何使用...
    99+
    2023-07-21
    响应 实时 日志
  • PHP如何实现HTTP同步请求并记录日志?
    在Web开发中,常常需要与其他Web服务进行通信,例如调用RESTful API获取数据或者向第三方服务发送数据。在这些场景下,我们需要使用HTTP同步请求来与其他Web服务进行通信。同时,为了方便排查问题和追踪请求,我们需要记录请求和响...
    99+
    2023-09-03
    同步 http 日志
  • Python如何实时获取任务请求对应的Nginx日志
    这篇文章主要介绍“Python如何实时获取任务请求对应的Nginx日志”,在日常操作中,相信很多人在Python如何实时获取任务请求对应的Nginx日志问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Pytho...
    99+
    2023-06-20
  • SpringMVC框架中如何使用Filter实现请求日志打印
    这篇文章主要为大家展示了“SpringMVC框架中如何使用Filter实现请求日志打印”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“SpringMVC框架中如何使用Filter实现请求日志打印”...
    99+
    2023-06-25
  • Python 函数如何实现实时响应并发请求?
    Python 是一门强大的编程语言,它支持并发编程。在现代 Web 应用程序中,实现并发请求处理是至关重要的。在本文中,我们将探讨如何使用 Python 函数来实现实时响应并发请求。 Python 函数是一种可重复使用的代码块,可以接收参...
    99+
    2023-08-29
    函数 实时 并发
  • 如何使用Java缓存HTTP请求日志?详解实现步骤
    当今互联网时代,HTTP请求日志已经成为了系统监控和性能优化的重要指标之一。为了更好地跟踪和分析系统运行状态,我们需要对HTTP请求日志进行缓存处理。本文将详细介绍如何使用Java缓存HTTP请求日志,包括实现步骤和演示代码。 一、缓存HT...
    99+
    2023-07-24
    http 日志 缓存
  • Python中如何实现Flask请求数据获取响应
    这篇文章给大家分享的是有关Python中如何实现Flask请求数据获取响应的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。一,请求数据及其获取      ...
    99+
    2023-06-25
  • springboot如何实现异步响应请求(前端请求超时的问题解决)
    目录问题解决方案1.服务端异步处理2.设置响应时间需要避免踩到的坑1.关于dubbo中的设置2.关于tomcat的设置3.关于Nginx的设置总结问题 实际场景中会遇到请求业务处理流...
    99+
    2023-01-30
    springboot 异步响应请求 springboot异步请求处理 springboot异步接口响应
  • HTTP请求时,如何使用PHP实现同步性并记录日志?
    在Web开发中,我们经常需要使用HTTP请求来获取或提交数据。而在PHP中,我们可以使用cURL库来发送HTTP请求。但是,如果我们需要在一个脚本中发送多个HTTP请求,并且需要等待所有请求都完成后才能进行下一步操作,就需要使用同步性。同...
    99+
    2023-09-03
    同步 http 日志
  • Laravel响应与ASP异步编程:如何实现快速响应用户请求?
    随着互联网技术的不断发展,用户对于网站的响应速度要求越来越高。为了满足用户的需求,我们需要通过优化服务器响应速度来提高用户体验。本文将介绍Laravel响应和ASP异步编程的实现方法,以实现快速响应用户请求。 一、Laravel响应 La...
    99+
    2023-08-17
    异步编程 laravel 响应
  • axios请求响应数据加解密封装如何实现
    本篇内容主要讲解“axios请求响应数据加解密封装如何实现”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“axios请求响应数据加解密封装如何实现”吧!安装依赖在前端开发中,我们经常需要向后端发送...
    99+
    2023-07-05
  • 实时日志如何提高ASP响应速度?
    ASP(Active Server Pages)是一种动态网页开发技术,它使用VBScript或JScript来编写脚本,通过IIS(Internet Information Services)来处理HTTP请求,并生成动态网页。在ASP...
    99+
    2023-07-21
    响应 实时 日志
  • 实时日志如何优化ASP响应能力?
    随着互联网和移动互联网的发展,越来越多的网站和应用程序需要实时监控和分析日志。ASP是一种常见的Web开发技术,但在处理大量实时日志时,ASP的响应能力会受到影响。本文将介绍如何通过优化ASP的代码和配置,来提高ASP处理实时日志的响应能...
    99+
    2023-07-21
    响应 实时 日志
  • springBoot之如何获取接口请求数据和返回数据实现日志
    目录一、获取接口请求的数据HttpServletRequestFilterRequestWrapperafterCompletion二、获取接口返回的数据HttpServletRes...
    99+
    2023-05-14
    springBoot接口 springBoot接口请求数据 springBoot返回数据日志
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作