做个登录时的验证码,运行时出现以下错误:
严重: 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();