问题解决:这个回应response的getOutputStream()已经被调用过

做个登录时的验证码,运行时出现以下错误:

严重: Servletjsp的Servlet.service()发生意外(exception) java.lang.IllegalStateException: 这个回应response的getOutputStream()已经被调用过

源码如下:

<%@ page language="java" contentType="image/jpeg; charset=gb2312"     pageEncoding="gb2312"%>

<%@ page import="java.awt.*,java.awt.image.*" %> 

 <%@ page import="java.util.*,javax.imageio.*" %>  

 <%!    Color getRandColor(int fc,int bc)

   Random r=new Random();  

   if(fc>255) fc=255;  

   if(bc>200) bc=255;

   int red=fc+r.nextInt(bc-fc); 

   int green=fc+r.nextInt(bc-fc);  i

   nt blue=fc+r.nextInt(bc-fc);  

   return new Color(red,green,blue);

}%>

<%  //设置页面不缓存   

   response.setHeader("Pragma","No-cache");          response.setHeader("cache-Control","no-cache");      response.setDateHeader("Expires",0);    

 //创建随机类    

  Random r=new Random();    

 //在内存中创建图像,宽度,高度    

  int width=80,height=30;    

  BufferedImage pic=new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);    

//获取图形上下文环境   

  Graphics gc=pic.getGraphics();  

 //设定背景颜色并进行填充    

  gc.setColor(getRandColor(200,250));    

  gc.fillRect(0,0,width,height);    

 //设定图形上下文环境字体    

  gc.setFont(new Font("Times New Roman",Font.PLAIN,20));  

 //画边框    

 //gc.setColor(new Color(1));    

 //gc.drawRect(0,0,width-1,height-1);

//随机产生200条干扰直线,使图像中的认证码不易被其他分析程序探测    

  gc.setColor(getRandColor(160,200));    

  for(int i=0;i<200;i++)    

  {      int x1=r.nextInt(width);     

         int y1=r.nextInt(height);     

         int x2=r.nextInt(15);     

         int y2=r.nextInt(15);     

        gc.drawLine(x1,y1,x1+x2,y1+y2);  

   }    

 //随即产生100个干扰点    

  gc.setColor(getRandColor(120,240));    

  for(int i=1;i<100;i++)

  {      int x=r.nextInt(width);     

         int y=r.nextInt(height);      

         gc.drawOval(x,y,0,0);    

  }    

 //随机产生四位数字的验证码    

  String RS="";     String rn="";    

  for(int i=0;i<4;i++)    

  {         //产生十以内随机数字        

        rn=String.valueOf(r.nextInt(10));        

        RS+=rn;        

    //将认证码用drawString函数显示到图像里

    //刚开始写的没下面这句结果字体颜色很淡几乎看不清 

   gc.setColor(new Color(20+r.nextInt(110),20+r.nextInt(110),20+r.nextInt(110)));//使字体颜色效果明显           gc.drawString(rn,13*i+16,16);    

 }    

 //释放图形上下文环境     gc.dispose();    

//将认证码RS存入session中共享   

  session.setAttribute("random",RS);

    //输出生成后的图象到页面   

ImageIO.write(pic,"JPEG",response.getOutputStream());    

 // out.clear();//清除缓冲区里的数据,但不把数据写到客户端里去

// out = pageContext.pushBody();// 重新得到out对象      

  %>

 去掉最后两句的注释后,就不再出错了。原因如下:

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

具体的原因就是在tomcat中jsp编译成servlet之后在函数_jspService(HttpServletRequest request, HttpServletResponse response)的最后有一段这样的代码 finally {       if (_jspxFactory != null) _jspxFactory.releasePageContext(_jspx_page_context);     } 这里是在释放在jsp中使用的对象,会调用response.getWriter(),因为这个方法是和response.getOutputStream()相冲突的!所以会出现以上这个异常。

简单的说就是web容器生成的servlet代码中有out.write(""),这个和JSP中调用的 response.getOutputStream()产生冲突.即Servlet规范说明,不能既调用 response.getOutputStream(), 又调用response.getWriter(),无论先调用哪一个,在调用第二个时候应会抛出 IllegalStateException, 因为在jsp中,out变量实际上是通过response.getWriter得到的, 程序中既用了 response.getOutputStream,又用了out变量,故出现以上错误。

然后当然是要提出解决的办法,其实挺简单的

在使用完输出流以后调用以下两行代码即可: out.clear(); out = pageContext.pushBody();

你可能感兴趣的:(问题解决:这个回应response的getOutputStream()已经被调用过)