nis*_*ntv 6 spring-mvc spring-boot spring-async spring-filter
我在 Scala 中有一个带有多个端点的 Spring Boot API。所有端点都是async并 return DeferredResult。在某些情况下,我想使用过滤器来记录响应正文。我创建了一个顺序为 1 的过滤器来缓存请求和响应,如下所示:
@Component
@Order(1)
class ContentCachingFilter extends OncePerRequestFilter {
override def doFilterInternal(request: HttpServletRequest, response: HttpServletResponse, filterChain: FilterChain): Unit = {
val requestToCache = new ContentCachingRequestWrapper(request)
val responseToCache = new ContentCachingResponseWrapper(response)
filterChain.doFilter(requestToCache, responseToCache)
responseToCache.copyBodyToResponse()
}
}
Run Code Online (Sandbox Code Playgroud)
我的日志过滤器类似于下面(删除了域特定逻辑):
@Component
@Order(2)
class RequestResponseLoggingFilter extends OncePerRequestFilter {
override def doFilterInternal(request: HttpServletRequest, response: HttpServletResponse, filterChain: FilterChain): Unit = {
logger.info(
s"Request -> URL : ${request.getMethod} ${request.getRequestURI} ${request.getParameterMap.asScala.stringRepresentation()}")
logger.debug(
s"Request Headers -> Content-type : ${request.getContentType} \\n Headers : ${new ServletServerHttpRequest(request).getHeaders}")
filterChain.doFilter(request, response)
logger.info(s"Response -> Status : ${response.getStatus}")
}
}
Run Code Online (Sandbox Code Playgroud)
我必须使用,ContentCachingResponseWrapper因为我想记录响应正文。但是,即使不尝试记录响应正文并且仅通过引入ContentCachingResponseWrapper,我也不会收到对任何端点的调用的任何响应。本地正在运行的实例在curl上返回如下输出:
HTTP/1.1 200
Content-Type: application/json
Content-Length: 197
.
.
.
<
* transfer closed with 197 bytes remaining to read
* stopped the pause stream!
* Closing connection 0
curl: (18) transfer closed with 197 bytes remaining to read
Run Code Online (Sandbox Code Playgroud)
如果我删除ContentCachingFilter,上面的日志过滤器工作正常,但如果我尝试记录响应正文,响应流将被消耗并且不再生成响应。因此我需要使用ContentCachingFilter.
我确实发现,如果端点是同步的,那么所有这些都有效。有人可以帮我找出问题所在以及如何使其与异步端点一起工作吗?
小智 9
responseToCache.copyBodyToResponse()
Run Code Online (Sandbox Code Playgroud)
改成 :
if (requestToCache.isAsyncStarted()) {
requestToCache.getAsyncContext().addListener(new AsyncListener() {
public void onComplete(AsyncEvent asyncEvent) throws IOException {
responseToCache.copyBodyToResponse()
}
public void onTimeout(AsyncEvent asyncEvent) throws IOException {
}
public void onError(AsyncEvent asyncEvent) throws IOException {
}
public void onStartAsync(AsyncEvent asyncEvent) throws IOException {
}
})
} else {
responseToCache.copyBodyToResponse()
}
Run Code Online (Sandbox Code Playgroud)
小智 0
val requestToCache = new ContentCachingRequestWrapper(request);
val responseToCache = new ContentCachingResponseWrapper(response);
Run Code Online (Sandbox Code Playgroud)
这两行改为:
if(!(request instanceof ContentCachingRequestWrapper)) {
requestToCache = new ContentCachingRequestWrapper(request);
}
if(!(request instanceof ContentCachingResponseWrapper)){
responseToCache = new ContentCachingResponseWrapper(request);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3165 次 |
| 最近记录: |