Spring MVC与Spring Boot Filter日志打印问题及解决

0 下载量 82 浏览量 更新于2024-08-31 收藏 69KB PDF 举报
"在Spring MVC或Spring Boot应用中,使用Filter来打印请求参数时可能会遇到问题,特别是当请求类型为Content-Type: application/json时。通常,我们使用AOP来记录请求和响应信息,但在不使用AOP的情况下,直接在Filter中处理可能会导致异常。本文将探讨如何在Filter中正确地打印请求和响应参数,以及如何避免常见的错误。" 在Spring MVC和Spring Boot框架中,过滤器(Filter)是处理HTTP请求和响应的关键组件。它们在请求被控制器处理之前和之后执行,可用于日志记录、安全检查等。Spring提供了`OncePerRequestFilter`抽象类,简化了过滤器的实现,确保每个请求只被过滤一次。当然,你也可以直接实现`javax.servlet.Filter`接口来自定义过滤器。 然而,当你尝试在Filter中打印Content-Type为application/json的POST请求参数时,可能会遇到"Stream closed"的异常。这是因为当Filter链继续执行并到达Controller时,请求的输入流可能已经被读取或关闭,因此在Filter中再次尝试访问时会引发异常。 错误写法一展示了这个问题的一个例子: ```java @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { filterChain.doFilter(request, response); printRequestLog(request); printResonseLog(response); } ``` 在这个例子中,`filterChain.doFilter(request, response)`调用会导致请求的输入流被处理,因此在调用`printRequestLog(request)`时,流可能已经关闭,导致IOException。 要解决这个问题,你需要在Filter中先复制请求和响应对象,然后在处理完原始流后再使用复制的对象。这里是一个正确的示例: ```java @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { HttpServletRequest clonedRequest = new ClonedHttpServletRequest(request); HttpServletResponse clonedResponse = new ClonedHttpServletResponse(response); filterChain.doFilter(clonedRequest, clonedResponse); printRequestLog(clonedRequest); printResonseLog(clonedResponse); } // 自定义ClonedHttpServletRequest和ClonedHttpServletResponse以复制原始对象 class ClonedHttpServletRequest extends HttpServletRequestWrapper { // 实现复制逻辑 } class ClonedHttpServletResponse extends HttpServletResponseWrapper { // 实现复制逻辑 } ``` 通过创建`ClonedHttpServletRequest`和`ClonedHttpServletResponse`,你可以确保在`filterChain.doFilter()`之后仍然可以安全地访问请求和响应参数,而不会触发异常。 此外,对于请求参数的解析,考虑到json类型的请求体,你可能需要使用`HttpServletRequest`的`getInputStream()`方法获取输入流,并使用`Jackson`或`Gson`等库来反序列化JSON数据。这样,即使在Filter中,也能正确读取并打印出JSON请求参数。 正确处理过滤器中的请求和响应参数是Spring MVC或Spring Boot应用中一个需要注意的细节。确保在继续Filter链之前复制这些对象,以及适当地处理输入流,可以避免潜在的异常并确保日志记录的准确性和可靠性。