生成图片验证码jsp出现getOutputStream() has already been called for this response异常的原因和解决方法

 

出现此错误一般都是在jsp中使用了输出流,没有妥善处理好的原因

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

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

    解决的办法:

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

 

彩色验证码完整的例子:

  1. <%@ page language="java" contentType="image/jpeg"  pageEncoding="utf-8"%>
  2. <%@ page contentType="image/jpeg" import="java.awt.*,java.awt.image.*,java.util.*,javax.imageio.*" %>
  3. <%@ page import="java.io.OutputStream "%> 
  4. <%!
  5. Color getRandColor(int fc,int bc){
  6. //给定范围获得随机颜色
  7.  Random random = new Random();
  8.  if(fc>255) fc=255;
  9.  if(bc>255) bc=255;
  10.  int r=fc+random.nextInt(bc-fc);
  11.  int g=fc+random.nextInt(bc-fc);
  12.  int b=fc+random.nextInt(bc-fc);
  13.  return new Color(r,g,b);
  14. }
  15. %>
  16. <%
  17. try{
  18. //设置页面不缓存
  19. response.setHeader("Pragma","No-cache");
  20. response.setHeader("Cache-Control","no-cache");
  21. response.setDateHeader("Expires"0);
  22. // 在内存中创建图象
  23. int width=60, height=20;
  24. BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
  25. OutputStream os = response.getOutputStream();
  26. // 获取图形上下文
  27. Graphics g = image.getGraphics();
  28. //生成随机类
  29. Random random = new Random();
  30. // 设定背景色
  31. g.setColor(getRandColor(200,250));
  32. g.fillRect(00, width, height);
  33. //设定字体
  34. g.setFont(new Font("Times New Roman",Font.PLAIN,18));
  35. //画边框
  36. //g.setColor(new Color());
  37. //g.drawRect(0,0,width-1,height-1);
  38. // 随机产生155条干扰线,使图象中的认证码不易被其它程序探测到
  39. g.setColor(getRandColor(160,200));
  40. for (int i=0;i<155;i++){
  41.  int x = random.nextInt(width);
  42.  int y = random.nextInt(height);
  43.  int xl = random.nextInt(12);
  44.  int yl = random.nextInt(12);
  45.  g.drawLine(x,y,x+xl,y+yl);
  46. }
  47. // 取随机产生的认证码(4位数字)
  48. String sRand="";
  49. for (int i=0;i<4;i++){
  50.  //String rand=String.valueOf(random.nextInt(10));  //数字
  51.  //String rand=String.valueOf((char)(Math.round(Math.random() * 25 + 65))); //字母大写 www.itstudy.cn
  52.  String rand=String.valueOf((char)(Math.round(Math.random() * 25 + 97)));   //字母小写
  53.  sRand+=rand;
  54.  // 将认证码显示到图象中
  55.  g.setColor(new Color(20+random.nextInt(110),20+random.nextInt(110),20+random.nextInt(110)));
  56.  //调用函数出来的颜色相同,可能是因为种子太接近,所以只能直接生成
  57.  g.drawString(rand,13*i+6,16);
  58. }
  59. // 将认证码存入SESSION
  60. session.setAttribute("rand",sRand);
  61. // 图象生效
  62. g.dispose();
  63. // 输出图象到页面
  64. ImageIO.write(image, "JPEG", os);
  65. os.flush();
  66. os.close();
  67. os = null ;
  68. response.flushBuffer();
  69. out.clear();
  70. out  =  pageContext.pushBody();
  71. }
  72. catch (IllegalStateException e){
  73.  System.out.println(e.getMessage());
  74.  e.printStackTrace();
  75. }
  76. %>

参考:杨雷 http://blog.csdn.net/ray_1981/archive/2008/03/07/2157447.aspx

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值