getOutputStream() уже был вызван для этого ответа


Я google сообщение об ошибке getOutputStream() has already been called for this response и многие люди сказали, что это из-за пробела или новой строки после <% или %>, но в моем коде нет пробела или новой строки. Я использую tomcat6 на linux.

<%@
    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)
11 52

11 ответов:

хорошо, вы должны использовать сервлет не JSP но если вам действительно нужно... добавить эту директиву в верхней части страницы:

<%@ page trimDirectiveWhitespaces="true" %>

или в разделе JSP-config ваш веб.xml

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

и flush/close the OutputStream и вернуться, когда закончите.

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

проблема здесь в том, что ваш JSP разговаривает непосредственно с ответом OutputStream. Технически это не запрещено, но это очень плохая идея.

в частности, вы называете response.getOutputStream() и записать данные на это. Позже, когда механизм JSP пытается сбросить ответ, он терпит неудачу, потому что ваш код уже "заявил" ответ. Приложение может либо вызвать getOutputStream или getWriter на любой данный ответ, это не разрешается делать оба. Двигатели JSP используют getWriter, и поэтому вы не можете звоните getOutputStream.

вы должны писать этот код как сервлет, а не JSP. Jsp действительно подходят только для текстового вывода, содержащегося в JSP. Вы можете видеть, что в вашем JSP нет фактического вывода текста, он содержит только java.

добавьте следующее В конце try / catch, чтобы избежать ошибки, которая появляется, когда двигатель JSP сбрасывает ответ через getWriter ()

out.clear(); // where out is a JspWriter
out = pageContext.pushBody();

Как уже было отмечено, это не лучшая практика, но она позволяет избежать ошибок в логах.

Я только что испытал эту проблему.

проблема была вызвана моим методом контроллера, пытающимся вернуть тип строка (имя представления) когда она выходит. Когда метод выйдет, будет инициирован второй поток ответа.

изменение типа возврата метода контроллера на пустота проблема решена.

Я надеюсь, что это поможет, если кто-то еще испытывает эту проблему.

У меня была эта проблема только во второй раз, когда я пошел на экспорт. Однажды я добавил:

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

после завершения экспорта мой код начал работать все время.

вот что сработало для меня в подобном случае.

после того, как вы закончите писать в ServletOutputStream просто позвони response.sendRedirect("yourPage.jsp");. Это приведет к инициализации нового запроса из браузера, поэтому избегайте записи в тот же выходной поток.

JSP-это структура представления s и, как правило, не должна содержать в себе никакой программной логики. Как skaffman предложил, использовать чистые сервлеты, или любой веб-фреймворк с MVC для того, чтобы достичь того, чего вы хотите.

эта ошибка возникла в моей программе, потому что результирующий набор вызывал больше столбцов для отображения в PDF-документе, чем в базе данных. Например, таблица содержит 30 полей, но программа вызывала 35 (resultset.getString (35))

я получил ту же ошибку, используя response.getWriter() до request.getRequestDispatcher(path).forward(request, response);. Так что начните работать нормально, когда я заменяю его на response.getOutputStream()

вместо того, чтобы использовать сервер GlassFish 4.0. Это, оказывается, проблема только в версии GlassFish в 4.1.1.

PT-BR: Используйте o Glasfish 4.0. Este parece ser um problema apenas no Glassfish 4.1.1.

в некоторых случаях это происходит при объявлении

Writer out=response.getWriter   

после объявления или используя RequestDispatcher.

я столкнулся с этой подобной проблемой при создании простого LoginServlet, где определено Writer после объявления RequestDispatcher.

попробовать определением Writer объект класса перед RequestDispatcher класса.