tomcat6下jsp出现getOutputStream() has already been called for this response异常的原因和解决方法

所属分类: 网络编程 / JSP编程 阅读数: 576
收藏 0 赞 0 分享

1.在tomcat6.0下jsp出现getOutputStream() has already been called for this response异常的原因和解决方法

  在tomcat6.0下jsp中出现此错误一般都是在jsp中使用了输出流(如输出图片验证码,文件下载等),没有妥善处理好的原因。

  具体的原因就是:
  在tomcat中jsp编译成servlet之后在函数_jspService(HttpServletRequest request, HttpServletResponse response)的最后有一段这样的代码

复制代码 代码如下:
finally {
    if (_jspxFactory != null) _jspxFactory.releasePageContext(_jspx_page_context);
}

  这里是在释放在jsp中使用的对象,会调用response.getWriter(),因为这个方法是和response.getOutputStream()相冲突的!所以会出现以上这个异常。

  然后当然是要提出解决的办法,其实挺简单的(并不是和某些朋友说的那样--将jsp内的所有空格和回车符号所有都删除掉),在使用完输出流以后调用以下两行代码即可:

复制代码 代码如下:
out.clear();
out = pageContext.pushBody();

  最后这里是一个输出彩色验证码例子(这样的例子几乎随处可见)

imag.jsp

<%@ page import="java.awt.*,java.awt.image.*,java.util.*,javax.imageio.*" %>
<%@ page import="java.io.OutputStream" %>
<%!
  Color getRandColor(int fc,int bc){
    Random random = new Random();
    if(fc>255) fc=255;
    if(bc>255) bc=255;
    int r=fc+random.nextInt(bc-fc);
    int g=fc+random.nextInt(bc-fc);
    int b=fc+random.nextInt(bc-fc);
    return new Color(r,g,b);
  }
 %>
<%
  try{
    response.setHeader("Pragma","No-cache");
    response.setHeader("Cache-Control","no-cache");
    response.setDateHeader("Expires", 0);
    int width=60, height=20;
    BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
    OutputStream os=response.getOutputStream();
    Graphics g = image.getGraphics();
    Random random = new Random();
    g.setColor(getRandColor(200,250));
    g.fillRect(0, 0, width, height);

    g.setFont(new Font("Times New Roman",Font.PLAIN,18));
    g.setColor(getRandColor(160,200));
    for (int i=0;i<155;i++){
      int x = random.nextInt(width);
      int y = random.nextInt(height);
      int xl = random.nextInt(12);
      int yl = random.nextInt(12);
      g.drawLine(x,y,x+xl,y+yl);
     }
    String sRand="";
    for (int j=0;j<4;j++){
      String rand=String.valueOf(random.nextInt(10));
      sRand+=rand;
      g.setColor(new Color(20+random.nextInt(110),20+random.nextInt(110),20+random.nextInt(110)));
      g.drawString(rand,13*j+6,16);
    }
    session.setAttribute("rand",sRand);
    g.dispose();

    ImageIO.write(image, "JPEG",os);
    os.flush();
    os.close();
    os=null;
    response.flushBuffer();
    out.clear();
    out = pageContext.pushBody();
  }catch(IllegalStateException e){
      System.out.println(e.getMessage());
    e.printStackTrace();
  }
%>

  如有不足之处,欢迎斧正!

2.getOutputStream() has already been called for this response问题的解决

  在jsp向页面输出图片的时候,使用response.getOutputStream()会有这样的提示:java.lang.IllegalStateException:getOutputStream() has already been called for this response,会抛出Exception

  原因一:
  JSP默认的输出流为PrintWriter ,即<% %>以外的东西所默认的输出方式,如果你尝试在JSP中使用ServletOutputStream就会引起错误.要嘛直接改用Servlet输出(复写service方法),要嘛删除除%><%中的任何东西(包括HTML标签,空格,回车等东西)应该就可以。对于这样的情况应该这样来解决,删除%><%之间的所有内容包括空格和换行符,最后也要消除空格和换行符,最好再加上一句response.reset()。

  原因二: 

  在J2EE的API参考里有这么个:

  ServletResponse的getWriter()方法里会抛出这个异常:

    IllegalStateException - if the getOutputStream method has already been called for this response object

  而它的getOutputStream()方法里会抛出这个异常:

    IllegalStateException - if the getOutputStream method has already been called for this response object

  并且两者的函数申明里都有这么样的一句

    Either this method or getOutputStream() may be called to write the body, not both.
    Either this method or getWriter() may be called to write the body, not both.


  以上说明也解释了为什么在往页面中写入图片的时候要使用如下循环格式

复制代码 代码如下:
OutputStream output=response.getOutputStream();
while((len=in.read(b)) >0) {
  output.write(b,0,len);
}
output.flush();

而不是把response.getOutputStream().write()放到循环体内

在页面中直接写:

复制代码 代码如下:
<body bgcolor="#ffffff">
<h1>
<%
    response.getOutputStream();
%>
</h1>
</body>

将会出现错误消息如下:

java.lang.IllegalStateException: getOutputStream() has already been called for this response
org.apache.catalina.connector.Response.getWriter(Response.java:604)
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)

以上就是tomcat6下jsp出现getOutputStream() has already been called for this response异常的原因和解决方法的全部内容,希望能给大家一个参考,也希望大家多多支持脚本之家。

更多精彩内容其他人还在看

jsp中使用frameset框架 边框固定不让更改边框的大小

有时候可能要对自己布局好的页面不让用户更改边框的大小,这样我们可以在frame里面添加noresize="noresize"属性就可以实现其中的功能
收藏 0 赞 0 分享

response.getWriter().write()向前台打印信息乱码问题解决

本节主要介绍了response.getWriter().write()向前台打印信息乱码问题解决方法,需要的朋友可以参考下
收藏 0 赞 0 分享

jsp页面中如何将时间戳字符串格式化为时间标签

本节主要介绍了jsp页面中如何将时间戳字符串格式化为时间标签,需要的朋友可以参考下
收藏 0 赞 0 分享

获取上一页面的URL和本页的URL的方法

本节主要介绍了获取上一页面的URL和本页的URL的方法,需要的朋友可以参考下
收藏 0 赞 0 分享

window.top[_CACHE]实现多个jsp页面共享一个js对象

两个js页面要共享一个就js对象,想了半天用window.top['_CACHE']来存放这个变量,即可实现,不同Jsp页面直接的对象共享
收藏 0 赞 0 分享

通过过滤器(Filter)解决JSP的Post和Request中文乱码问题

这篇文章主要介绍了jsp中通过过滤器(Filter)解决JSP的Post和Request中文乱码问题的方法,需要的朋友可以参考下
收藏 0 赞 0 分享

JSP页面的动态包含和静态包含示例及介绍

这篇文章主要介绍了JSP页面的动态包含和静态包含示例及介绍,本文讲解了它们的区别并给出了相应例子,需要的朋友可以参考下
收藏 0 赞 0 分享

JSP中实现判断客户端手机类型并跳转到app下载页面

这篇文章主要介绍了JSP中实现判断客户端手机类型并跳转到app下载页面,实现的原理,是检测浏览器的 USER-AGENT 这个header,然后根据正则表达式来确定客户端类型,需要的朋友可以参考下
收藏 0 赞 0 分享

jsp实现点击help打开chm文件

有个javaweb项目,需要在portal上面点击help即可打开“帮助.chm”文件,下面与大家分享下jsp如何打开chm文件
收藏 0 赞 0 分享

JSP自定义分页标签TAG全过程

这篇文章主要介绍了JSP自定义分页标签TAG全过程,比较实用,需要的朋友可以参考下
收藏 0 赞 0 分享
查看更多