已经为此响应调用了getOutputStream()

时间:2009-11-21 17:37:59

标签: java jsp tomcat

我谷歌错误消息getOutputStream() has already been called for this response 许多人说这是因为<%%>之后的空格或换行符,但在我的代码中,没有空格或换行符。我在linux上使用tomcat6。

<%@
    page import="java.servlet.*,
    javax.servlet.http.*,
    java.io.*,
    java.util.*,
    com.lowagie.text.pdf.*,
    com.lowagie.text.*"
    %><%
    response.setContentType("application/pdf");
    Document document = new Document();
    try{
        ByteArrayOutputStream buffer = new ByteArrayOutputStream();
        PdfWriter.getInstance(document, buffer);
        document.open();
        PdfPTable table = new PdfPTable(2);
        table.addCell("1");
        table.addCell("2");
        table.addCell("3");
        table.addCell("4");
        table.addCell("5");
        table.addCell("6");
        document.add(table);
        document.close();
        DataOutput dataOutput = new DataOutputStream(response.getOutputStream());
        byte[] bytes = buffer.toByteArray();
        response.setContentLength(bytes.length);
        for(int i = 0; i < bytes.length; i++)
        {
        dataOutput.writeByte(bytes[i]);
        }
    }catch(DocumentException e){
        e.printStackTrace();
    }

%>

org.apache.jasper.JasperException: java.lang.IllegalStateException: getOutputStream() has already been called for this response
    org.apache.jasper.servlet.JspServletWrapper.handleJspException(JspServletWrapper.java:522)
    org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:410)
    org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:342)
    org.apache.jasper.servlet.JspServlet.service(JspServlet.java:267)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:717)

根本原因

java.lang.IllegalStateException: getOutputStream() has already been called for this response
    org.apache.catalina.connector.Response.getWriter(Response.java:610)
    org.apache.catalina.connector.ResponseFacade.getWriter(ResponseFacade.java:198)
    org.apache.jasper.runtime.JspWriterImpl.initOut(JspWriterImpl.java:125)
    org.apache.jasper.runtime.JspWriterImpl.flushBuffer(JspWriterImpl.java:118)
    org.apache.jasper.runtime.PageContextImpl.release(PageContextImpl.java:188)
    org.apache.jasper.runtime.JspFactoryImpl.internalReleasePageContext(JspFactoryImpl.java:118)
    org.apache.jasper.runtime.JspFactoryImpl.releasePageContext(JspFactoryImpl.java:77)
    org.apache.jsp.Account.Domain.testPDF_jsp._jspService(testPDF_jsp.java:94)
    org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
    org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:374)
    org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:342)
    org.apache.jasper.servlet.JspServlet.service(JspServlet.java:267)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:717)

14 个答案:

答案 0 :(得分:49)

好的,您应该使用 servlet 而非JSP,但如果您确实需要...在页面顶部添加此指令:

<%@ page trimDirectiveWhitespaces="true" %>

或者在你的web.xml的jsp-config部分

<jsp-config>
  <jsp-property-group>
    <url-pattern>*.jsp</url-pattern>
    <trim-directive-whitespaces>true</trim-directive-whitespaces>
  </jsp-property-group>
</jsp-config>

同样flush / close OutputStream并在完成后返回。

dataOutput.flush();
dataOutput.close();
return;

答案 1 :(得分:35)

这里的问题是您的JSP直接与响应OutputStream对话。这在技术上是不被禁止的,但这不是一个好主意。

具体来说,您调用response.getOutputStream()并向其写入数据。稍后,当JSP引擎尝试刷新响应时,它会失败,因为您的代码已经“声明”了响应。应用程序可以在任何给定的响应上调用getOutputStreamgetWriter,但不允许同时执行这两项操作。 JSP引擎使用getWriter,因此您无法调用getOutputStream

您应该将此代码编写为Servlet,而不是JSP。 JSP仅适用于JSP中包含的文本输出。您可以看到JSP中没有实际的文本输出,它只包含java。

答案 2 :(得分:9)

在try / catch的末尾添加以下内容,以避免JSP引擎通过getWriter()

刷新响应时出现的错误
out.clear(); // where out is a JspWriter
out = pageContext.pushBody();

正如已经指出的那样,这不是最佳做法,但它可以避免日志中的错误。

答案 3 :(得分:4)

我第二次出口时才遇到这个问题。一旦我加入:

response.getOutputStream().flush();
response.getOutputStream().close();

导出完成后,我的代码一直开始工作。

答案 4 :(得分:3)

在类似的情况下,这对我有用。

写完Servlet OutputStream后,只需致电response.sendRedirect("yourPage.jsp");。这将导致从浏览器启动新请求,因此避免写入相同的输出流。

答案 5 :(得分:3)

我刚遇到这个问题。

问题是由我的控制器方法在退出时尝试返回类型字符串(视图名称)引起的。当该方法退出时,将启动第二个响应流。

将控制器方法返回类型更改为 void 解决了问题。

我希望如果其他人遇到这个问题,这会有所帮助。

答案 6 :(得分:2)

JSP是表示框架,通常不应包含任何程序逻辑。正如skaffman建议的那样,使用纯servlet或任何MVC Web框架来实现您想要的目标。

答案 7 :(得分:0)

我的程序中出现此错误,因为结果集在PDF文档中调用的列数多于包含的数据库。例如,该表包含30个字段,但程序调用35(resultset.getString(35))

答案 8 :(得分:0)

我在response.getWriter()之前使用request.getRequestDispatcher(path).forward(request, response);时遇到了同样的错误。因此,当我用response.getOutputStream()

替换它时,开始工作正常

答案 9 :(得分:0)

我遇到了同样的问题,仅添加“ return”就解决了。在FileInputStream的末尾。

这是我的JSP

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
	pageEncoding="ISO-8859-1"%>
<%@ page import="java.io.*"%>
<%@ page trimDirectiveWhitespaces="true"%>

<%

	try {
		FileInputStream ficheroInput = new FileInputStream("C:\\export_x_web.pdf");
		int tamanoInput = ficheroInput.available();
		byte[] datosPDF = new byte[tamanoInput];
		ficheroInput.read(datosPDF, 0, tamanoInput);

		response.setHeader("Content-disposition", "inline; filename=export_sise_web.pdf");
		response.setContentType("application/pdf");
		response.setContentLength(tamanoInput);
		response.getOutputStream().write(datosPDF);

		response.getOutputStream().flush();
		response.getOutputStream().close();

		ficheroInput.close();
		return;

	} catch (Exception e) {

	}
%>

</body>
</html>

答案 10 :(得分:0)

我没有使用JSP,但是当我通过调用PrintWriter的flush()方法或return语句将响应设置为返回JSON对象时遇到了类似的错误。先前的答案,即将return语句包装到try块中,工作方式类似于:错误消失了,因为return statement使方法忽略了try-catch下面的所有代码,特别是在我的情况下,行redirectStrategy.sendRedirect(request,response,destination_addr_string)这似乎修改了导致错误的已提交响应。就我而言,最简单的解决方案是删除行,让客户端应用程序负责重定向。

答案 11 :(得分:0)

我遇到了同样的问题,出现这个问题是因为如果您使用 getWriter()/getOutputStream() 使用多个写入器/输出流,Java 会出现错误。

对我来说,问题是我使用了 @Logging 和 @RestLogging,避免在调用 API 时使用额外的注释。

答案 12 :(得分:-1)

请改用Glassfish 4.0。这只是Glassfish 4.1.1版本中的一个问题。

PT-BR: 使用o Glasfish 4.0。 Este parece ser um problema apenas no Glassfish 4.1.1。

答案 13 :(得分:-1)

在某些情况下,当您声明

时会发生这种情况
Writer out=response.getWriter   
声明或使用RequestDispatcher

我在创建一个简单的LoginServlet时遇到了类似的问题,我在声明Writer后定义了RequestDispatcher

尝试在Writer类之前定义RequestDispatcher类对象。