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() 已经为此响应调用的主要内容,如果未能解决你的问题,请参考以下文章