Tomcat 8.5已经为此响应调用了response.getWriter()方法。

5

我正在生产环境中使用Tomcat 8.5.23与Servlets(如果相关,还使用了Spring自动装配功能)。

response.getWriter()在生产环境下返回null

在自定义过滤器中调用chain.doFilter(req, res);也会出现这种情况。

public class MyFilter implements Filter {
  public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) res;
        response.setHeader("Access-Control-Allow-Origin", "*");
        chain.doFilter(req, res);
  }
  public void init(FilterConfig filterConfig) {}
  public void destroy() {}
}

异常:

Request processing failed; nested exception is java.lang.IllegalStateException: getWriter() has already been called for this response] with root cause
java.lang.IllegalStateException: getWriter() has already been called for this response
        at org.apache.catalina.connector.Response.getOutputStream(Response.java:591)
        at org.apache.catalina.connector.ResponseFacade.getOutputStream(ResponseFacade.java:194)
        at org.springframework.http.server.ServletServerHttpResponse.getBody(ServletServerHttpResponse.java:89)
        at org.springframework.http.converter.StringHttpMessageConverter.writeInternal(StringHttpMessageConverter.java:106)
        at org.springframework.http.converter.StringHttpMessageConverter.writeInternal(StringHttpMessageConverter.java:41)
        at org.springframework.http.converter.AbstractHttpMessageConverter.write(AbstractHttpMessageConverter.java:227)
        at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:247)
        at org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor.handleReturnValue(HttpEntityMethodProcessor.java:203)
        at org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:81)
        at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:113)
        at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
        at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
        at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
        at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967)
        at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901)
        at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
        at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:635)
        at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
        at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)

我尝试添加HttpServletResponseWrapper,但它没有起作用。


HttpServletResponse 在 tomcat 中的实现不能返回 null。有两种情况:1. 调用了 getOutputStream() -> 它会抛出 IllegalStateException,2. 内部 writer 为 null:它将创建一个新的 CoyoteWriter。很可能一些过滤器正在包装响应对象并且没有正确处理某些情况。只需使用调试器逐步通过过滤器链即可。绝对不是 tomcat 的问题。 - Svetlin Zarev
@SvetlinZarev 这个问题只会偶尔出现,目前无法复现。 - user7294900
1个回答

1
您的过滤器代码看起来没问题,问题出在其他地方。有评论提到getWriter()不能返回null。请查看发生这种情况的代码。很可能是代码尝试将写入器分配给变量,但捕获并忽略了该异常。在忽略异常的点之后,某人尝试使用该变量,但它包含null,因为赋值没有发生。
这些“已调用”错误可能发生的一个常见情况是在错误处理中。Servlet开始发送响应,因此调用了getWriter()。然后它遇到错误,错误处理尝试编写错误响应,因此再次调用getWriter()。您无法重现该问题,因为该错误情况随机发生。

但据我所知,问题不在过滤器上。 - Roland Weber
但是过滤器在Servlet之前执行。 - user7294900
你的过滤器执行没有问题,然后调用了servlet。但是servlet遇到了问题。你的过滤器甚至没有调用getWriter(),那么在你的过滤器中如何出现getWriter()返回null的问题呢? - Roland Weber

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接