2009-11-21 29 views
49

Tôi google thông báo lỗi getOutputStream() has already been called for this response và nhiều người cho biết đó là vì của không gian hoặc xuống dòng sau khi <% hoặc %>, nhưng trong mã của tôi, không có là một không gian hoặc một dòng mới . Tôi đang sử dụng tomcat6 trên Linux.getOutputStream() đã được kêu gọi phản ứng này

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

nguyên nhân gốc rễ

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) 

Trả lời

43

Ok, bạn nên sử dụng một servlet không phải là một JSP nhưng nếu bạn thực sự cần phải ... thêm chỉ thị này ở phía trên cùng của trang của bạn:

<%@ page trimDirectiveWhitespaces="true" %> 

Hoặc trong phần jsp-config web.xml của bạn

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

Cũng flush/close các OutputStream và trở về khi hoàn tất.

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

Bạn đã xác minh rằng tác phẩm này có hoạt động không? Tôi nghi ngờ nó sẽ làm cho bất kỳ sự khác biệt, container vẫn sẽ gọi 'getWriter', bất kể nội dung trang. – skaffman

+0

Không, nếu không có khoảng trắng bên ngoài '<% %>'. Tuy nhiên, điều này có thể là hành vi thực hiện cụ thể mà sau này tôi sẽ không dựa vào. Theo như tôi biết nó sẽ làm việc tốt trong Tomcat. Nhưng một lần nữa, mã java thuộc về các lớp java, không phải trong các tệp jsp. Giai đoạn. – BalusC

+0

Tôi quên đề cập rằng chỉ thị trimDirectiveWhitespaces là dành cho JSP 2.1 hoặc tốt hơn – RealHowTo

31

Vấn đề ở đây là JSP của bạn được nói chuyện trực tiếp để đáp ứng OutputStream. Điều này về mặt kỹ thuật không bị cấm, nhưng nó không phải là một ý tưởng hay.

Cụ thể, bạn gọi response.getOutputStream() và ghi dữ liệu vào đó. Sau đó, khi công cụ JSP cố gắng xóa bỏ phản hồi, nó không thành công vì mã của bạn đã "xác nhận" phản hồi. Một ứng dụng có thể gọi getOutputStream hoặc getWriter trên bất kỳ phản hồi cụ thể nào, nó không được phép thực hiện cả hai. Động cơ JSP sử dụng getWriter và do đó bạn không thể gọi getOutputStream.

Bạn nên viết mã này làm Servlet, không phải là JSP. JSP chỉ thực sự phù hợp với đầu ra văn bản có trong JSP. Bạn có thể thấy rằng không có đầu ra văn bản thực tế trong JSP của bạn, nó chỉ chứa java.

+0

toàn bộ dự án dựa trên jsp, tôi chỉ cần thêm chức năng để tải xuống PDF – Southsouth

+4

Bạn không thể, không như thế này. JSP là dành cho văn bản, không phải là nhị phân. – skaffman

+4

+1. Mã java thô thuộc về các lớp java. Chỉ sử dụng thẻ tagl/EL trong JSP. Nếu không thể với taglibs/EL, hãy sử dụng một servlet. – BalusC

2

JSP là khung trình bày và thường không được chứa bất kỳ logic chương trình nào trong đó. Như skaffman đã đề xuất, hãy sử dụng các servlet thuần túy hoặc bất kỳ khung công tác web MVC nào để đạt được những gì bạn muốn.

3

Đây là những gì đã làm việc cho tôi trong trường hợp tương tự.

Sau khi bạn hoàn tất việc viết vào ServletOutputStream chỉ cần gọi response.sendRedirect("yourPage.jsp");. Điều đó sẽ gây ra việc bắt đầu một yêu cầu mới từ trình duyệt, do đó tránh viết vào cùng một luồng đầu ra.

6

Thêm dòng sau trong phần cuối của try/catch để tránh những lỗi xuất hiện khi động cơ JSP xả phản ứng qua getWriter()

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

Như đã lưu ý, đây không phải là thực hành tốt nhất , nhưng nó tránh các lỗi trong nhật ký của bạn.

0

Lỗi này xảy ra trong chương trình của tôi vì resultset đang gọi nhiều cột hơn được hiển thị trong Tài liệu PDF so với cơ sở dữ liệu chứa. Ví dụ, bảng chứa 30 trường nhưng chương trình đang gọi 35 (resultset.getString (35))

3

Tôi vừa mới gặp phải sự cố này.

Vấn đề là do phương pháp điều khiển của tôi cố gắng loại trả về là Chuỗi (tên chế độ xem) khi thoát. Khi phương thức sẽ thoát, luồng phản hồi thứ hai sẽ được bắt đầu.

Thay đổi kiểu trả về của phương thức điều khiển thành void giải quyết được sự cố.

Tôi hy vọng điều này sẽ giúp ích nếu có ai khác gặp sự cố này.

3

Tôi gặp sự cố này chỉ lần thứ hai tôi xuất chuyển. Khi tôi đã thêm:

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

sau khi xuất xong, mã của tôi bắt đầu hoạt động mọi lúc.

+0

JSP muốn mở nó để in nội dung HTML, vì vậy nó sẽ mở sau%% cuối cùng của bạn> – ern0

0

Tôi gặp lỗi tương tự bằng cách sử dụng response.getWriter() trước số request.getRequestDispatcher(path).forward(request, response);. Vì vậy, bắt đầu hoạt động tốt khi tôi thay thế nó bằng cách response.getOutputStream()

0

Sử dụng Glassfish 4.0 để thay thế. Điều này hóa ra chỉ là vấn đề trong bản phát hành Glassfish 4.1.1.

PT-BR: Sử dụng o Glasfish 4.0. Este parece ser um problema apenas không có Glassfish 4.1.1.

+0

Bạn có liên kết báo cáo lỗi cho điều này không? – Robert

-1

Trong một số trường hợp trường hợp này xảy ra khi bạn khai báo

Writer out=response.getWriter 

sau khi tuyên bố hoặc sử dụng RequestDispatcher.

Tôi gặp sự cố tương tự này khi tạo đơn giản LoginServlet, nơi tôi đã xác định Writer sau khi khai báo RequestDispatcher.

Thử xác định Writer đối tượng lớp trước lớp RequestDispatcher.

Các vấn đề liên quan