如何在Spring WebFlux中记录请求和响应正文
我想在带有Kotlin的Spring WebFlux上的REST API中集中记录请求和响应。到目前为止,我已经尝试过这种方法
@Beanfun apiRouter() = router {
(accept(MediaType.APPLICATION_JSON) and "/api").nest {
"/user".nest {
GET("/", userHandler::listUsers)
POST("/{userId}", userHandler::updateUser)
}
}
}.filter { request, next ->
logger.info { "Processing request $request with body ${request.bodyToMono<String>()}" }
next.handle(request).doOnSuccess { logger.info { "Handling with response $it" } }
}
此处请求方法和路径成功登录,但正文为Mono
,那么我应该如何记录呢?是否应该相反,我必须订阅请求正文Mono
并将其记录在回调中?另一个问题是ServerResponse
此处的接口无法访问响应主体。我怎么在这里买?
我尝试过的另一种方法是使用 WebFilter
@Beanfun loggingFilter(): WebFilter =
WebFilter { exchange, chain ->
val request = exchange.request
logger.info { "Processing request method=${request.method} path=${request.path.pathWithinApplication()} params=[${request.queryParams}] body=[${request.body}]" }
val result = chain.filter(exchange)
logger.info { "Handling with response ${exchange.response}" }
return@WebFilter result
}
同样的问题在这里:请求正文是Flux
,没有响应正文。
是否可以通过某些过滤器访问完整的请求和响应以进行日志记录?我不明白什么
回答:
这或多或少类似于Spring MVC中的情况。
在Spring MVC中,您可以使用AbstractRequestLoggingFilter
过滤器和
ContentCachingRequestWrapper
和/或ContentCachingResponseWrapper
。这里有很多折衷:
- 如果您想访问servlet请求属性,则需要实际读取和解析请求主体
- 记录请求主体意味着缓冲请求主体,这可能会使用大量内存
- 如果要访问响应正文,则需要包装响应并在编写响应正文时对其进行缓冲,以便以后检索
ContentCaching*Wrapper
WebFlux中不存在类,但是您可以创建类似的类。但请记住以下几点:
- 在内存中缓冲数据以某种方式违反了反应堆,因为我们正在尝试利用可用资源非常高效
- 您不应该篡改实际的数据流,并且不应该频繁/频繁地刷新数据,否则就有可能破坏流使用案例
- 在该级别,您只能访问
DataBuffer
实例,这些实例(大约)是内存有效的字节数组。这些属于缓冲池,并被回收以用于其他交换。如果未正确保留/释放这些内存,则会造成内存泄漏(并且缓冲数据以供日后使用肯定适合这种情况) - 同样在该级别,它只有字节,您无权访问任何编解码器来解析HTTP正文。如果最初不是人类可读的内容,我会忘记缓冲内容
您问题的其他答案:
- 是的,这
WebFilter
可能是最好的方法 - 不,您不应该订阅请求主体,否则您将使用处理程序将无法读取的数据;您可以
flatMap
根据要求将数据缓冲在doOn
运算符中 - 包装响应应该使您可以访问正在编写的响应正文;不过不要忘记内存泄漏
以上是 如何在Spring WebFlux中记录请求和响应正文 的全部内容, 来源链接: utcz.com/qa/434425.html