java.lang.IllegalStateException: getOutputStream() 已经为此响应调用

Posted

技术标签:

【中文标题】java.lang.IllegalStateException: getOutputStream() 已经为此响应调用【英文标题】:java.lang.IllegalStateException: getOutputStream() has already been called for this response 【发布时间】:2011-04-02 05:06:14 【问题描述】:

当我尝试从客户端的服务器请求加载图像时,出现以下异常:

241132533 [TP-Processor1] 错误 [/jspapps].[jsp] - servlet jsp 的 Servlet.service() 抛出异常 java.lang.IllegalStateException: getOutputStream() 已为此响应调用

谁能向我解释这个异常以及如何克服它?

【问题讨论】:

【参考方案1】:

我只是偶然发现了这个老问题,因为我遇到了同样的问题。最后很容易摆脱异常:只需调用out.clear()之前:

out.clear();
...
// later, in a different method
ServletOutputStream out = response.getOutputStream();
...

out.clear() 还帮助我摆脱了来自<%@page import=... 之类的所有空行。

【讨论】:

抱歉,我刚看了文档,在ServletOutputStream类中找不到clear方法? 实际上在 JSP 中存在的变量中;)它对我来说非常有效,谢谢。【参考方案2】:

谁能给我解释一下这个例外

您正在尝试使用 JSP 文件中的原始 Java 代码将二进制数据写入 response.getOutputStream(),该文件本身已经使用 response.getWriter() 来写入任何模板文本。另请参阅链接的 javadocs 的 Throws 部分。

还有如何克服它?

改为在真正的 Java 类中编写 Java 代码。创建一个 extends HttpServlet 的类,将所有 Java 代码移到那里,将其映射到 web.xml 并更改请求 URL 以改为调用 servlet。

另见:

Beginning and intermediate JSP/Servlet tutorials Basic example of an image servlet How to avoid Java code in JSP files

【讨论】:

对不起,但我需要把我的代码放在 jsp 文件中,我通过 ' style='position: absolute ;左:0pt;顶部:0px;' "/> @ama:将 view_image.jsp 转换为映射到 viewImage 的 Servlet,并在您的 JSP 文件中像 <img src='viewImage?pat_acc=<%=Pat_Acct%>' style='position: absolute; left: 0pt; top: 0px;' "/> 一样调用它。 没错。问题出在view_image.jsp。它应该被一个 servlet 类取代。【参考方案3】:

确保消除view_image.jsp 中的所有输出。简单的换行符可以负责生成输出。

例如,如果您有这些声明...

<%@ page import ... %>
<%@ page import ... %>

...你应该这样写它们

<%@ page import ... %><%@ page import ... %><%
...%>

如果您查看已编译的 servlet 代码,您不应该在图像响应之前看到 out.write("\r\n")

更好的方法是将您的 view_image.jsp 更改为 Servlet,但如果您不能这样做,则可以在 jsp 中删除换行符。

【讨论】:

(我的)Intellij 自动制作,感谢您的指出!【参考方案4】:

试试这个,虽然它不是最好的解决方案,但它确实有效。

in.close();
out2.flush();
out.clear();
out = pageContext.pushBody(); 

其中“in”是 InputStream(如果您正在使用),“out2”是新的 response.getOutputStream(),“out”是默认的 JspWriter

【讨论】:

【参考方案5】:
    <%@page import="java.sql.DriverManager"%>
    <%@page import="java.io.InputStream"%>
    <%@page import="java.sql.Connection"%>
    <%@page import="java.sql.PreparedStatement"%>
    <%@page import="java.sql.ResultSet"%>
    <%@page import="java.sql.Statement"%>

  <%
    Connection con=null;
    ResultSet rs = null;
    Statement st = null;
    String sql = null;
    try 
            Class.forName("com.mysql.jdbc.Driver");
            con=DriverManager.getConnection("test","root","root"); 
            st = con.createStatement();
            sql = "select image from projects where projectid='1'";
            System.out.println(sql);
            rs = st.executeQuery(sql); 
            String imgLen = "";
            out.clear();
            while (rs.next()) 
            
                imgLen = rs.getString(1);
                System.out.println(imgLen.length());
                int len = imgLen.length();
                byte[] rb = new byte[len];
                InputStream readImg = rs.getBinaryStream(1);
                int index = readImg.read(rb, 0, len);
                response.reset();
                response.setContentType("image/jpg");
                response.getOutputStream().write(rb, 0, len);
                response.getOutputStream().flush();
                response.getOutputStream().close();
            
            st.close();
            rs.close();
            if (true) return;
         catch (Exception e) e.printStackTrace();
    %>

【讨论】:

最好在答案中添加一些解释,以帮助其他人理解问题/错误。【参考方案6】:

将 view_image.jsp 转换为映射到ViewImage 的 Servlet 并像这样调用它

<img src='<%= request.getContextPath() %>/ViewImage?pat_acc=<%=Pat_Acct%>' style='position: absolute; left: 0pt; top: 0px;' "/> 

在您的 JSP 文件中。

【讨论】:

【参考方案7】:

尝试从 jsp 文件中删除 所有 模板文本。例如,

1 <%@
2    ....
3 %>
4 <%
5    ....
6 %>

在第 3 行和第 4 行之间有一个 '\n',它被视为模板文本,调用 response.getWriter() 将那个 '\n' 写入客户端。在第 6 行之后,也可能有不可见的空格,这会破坏输出流。但是第 5 行可以提前return 来避免这种情况。

【讨论】:

【参考方案8】:

我在最近的工作中也遇到了同样的问题。

我们有一个 servlet 过滤器,我们在其中使用 ServletResponse.getWriter() 方法来写入正文,在一些 Spring MVC 控制器中,我们还使用 response.getOutputStream() 将图像(字节数组)之类的内容写入正文.

由于每个请求都会经过过滤器,并且基于 Java API 文档:

“可以调用此方法(getWriter())或 getOutputStream() 来写入正文,而不是两者。”

这就是为什么我们得到“java.lang.IllegalStateException: getOutputStream() 已经被调用了这个响应”异常的原因。

所以在那个过滤器中,我将代码更改为:

ServletOutputStream sos = response.getOutputStream();
sos.write(newhtml.getBytes("UTF8")); // newHtml is a String.
sos.flush();

它为我解决了这个问题。

【讨论】:

【参考方案9】:

在 Spring 中,你可以通过改变来解决这个问题

            response.getOutputStream().write(cabecera.getBytes());

            response.getWriter().write(cabecera);

【讨论】:

【参考方案10】:

我有这段代码并像这样修复它:

@RequestMapping(value = "xyz", method = RequestMethod.POST)
public String generateReport(HttpServletResponse response, @Valid @ModelAttribute Form form, Errors errors, Model model) 
    if (errors.hasErrors()) 
        model.addAttribute(form);
        return "abcd/xyz";
     else 
        someMethodWhichUsesResponse(response);
    
Earlier:
    return "abcd/xyz";
Fixed by:
    return null;

我返回 null 是因为,通过这种方法,我期待下载。根据here 给出的解释,我解决了我的问题。

【讨论】:

【参考方案11】:

如果您在 servlet 中遇到此问题,那么在从 servlet 向浏览器发送响应时:

PrintWriter out=response.getWriter();

这应该是您可以在 servlet 中编写最终发送到浏览器的 html 代码之后的第一条语句

【讨论】:

以上是关于java.lang.IllegalStateException: getOutputStream() 已经为此响应调用的主要内容,如果未能解决你的问题,请参考以下文章