生成图片验证码产生的一个异常

之前在做一个注册页面的时候想要实现一个验证码功能,于是采用了以下代码:

image.jsp//生成验证码

 1 Color getRandColor(int fc,int bc)
 2 {
 3      Random random = new Random();
 4      if(fc>255) fc=255;
 5      if(bc>255) bc=255;
 6      int r=fc+random.nextInt(bc-fc);
 7      int g=fc+random.nextInt(bc-fc);
 8      int b=fc+random.nextInt(bc-fc);
 9      return new Color(r,g,b);
10 }
11 %>
12 <%
13     out.clear();//这句针对resin服务器,如果是tomacat可以不要这句
14     response.setHeader("Pragma","No-cache");
15     response.setHeader("Cache-Control","no-cache");
16     response.setDateHeader("Expires", 0);
17 
18     int width=60, height=20;
19     BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
20 
21     Graphics g = image.getGraphics();
22     Random random = new Random();
23 
24     g.setColor(getRandColor(200,250));
25     g.fillRect(0, 0, width, height);
26 
27     g.setFont(new Font("Times New Roman",Font.PLAIN,18));
28 
29     g.setColor(getRandColor(160,200));
30     for (int i=0;i<155;i++)
31     {
32         int x = random.nextInt(width);
33         int y = random.nextInt(height);
34         int xl = random.nextInt(12);
35         int yl = random.nextInt(12);
36         g.drawLine(x,y,x+xl,y+yl);
37     }
38     char c[] = new char[62];
39 
40     for (int i = 97, j = 0; i < 123; i++, j++) {
41         c[j] = (char) i;
42     }
43     for (int o = 65, p = 26; o < 91; o++, p++) {
44         c[p] = (char) o;
45     }
46     for (int m = 48, n = 52; m < 58; m++, n++) {
47         c[n] = (char) m;
48     }        
49     String sRand="";
50     for (int i=0;i<4;i++){
51         int x = random.nextInt(62);
52         String rand=String.valueOf(c[x]);
53         sRand+=rand;
54         g.setColor(new Color(20+random.nextInt(110),20+random.nextInt(110),20+random.nextInt(110)));
55         g.drawString(rand,13*i+6,16);
56     }
57 
58     // 将认证码存入SESSION
59     session.setAttribute("rand",sRand);
60 
61     g.dispose();
62     try{
63     ImageIO.write(image, "JPEG", response.getOutputStream());
64     }catch(Exception e){
65         e.printStackTrace();
66     }finally{
67         if(response.getOutputStream()!=null){
68             try{
69                 response.getOutputStream().close();
70             }catch(Exception e){
71                 e.printStackTrace();
72             }
73         }
74     }

加载验证码

1  function loadimage(){
2     document.getElementById("randImage").src = "image.jsp?"+Math.random();
3   }

效果如图:

但是会报一个异常:

严重: Servlet.service() for servlet jsp threw exception
java.lang.IllegalStateException: getOutputStream() has already been called for this response
 at org.apache.catalina.connector.Response.getWriter(Response.java:610)
 at org.apache.catalina.connector.ResponseFacade.getWriter(ResponseFacade.java:198)
 at org.apache.jasper.runtime.JspWriterImpl.initOut(JspWriterImpl.java:125)
 at org.apache.jasper.runtime.JspWriterImpl.flushBuffer(JspWriterImpl.java:118)
 at org.apache.jasper.runtime.PageContextImpl.release(PageContextImpl.java:188)
 at org.apache.jasper.runtime.JspFactoryImpl.internalReleasePageContext(JspFactoryImpl.java:118)
 at org.apache.jasper.runtime.JspFactoryImpl.releasePageContext(JspFactoryImpl.java:77)
 at org.apache.jsp.image_jsp._jspService(image_jsp.java:148)
 at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
 at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
 at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:374)
 at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:342)
 at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:267)
 at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
 at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
 at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
 at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
 at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
 at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
 at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
 at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
 at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
 at org.apache.coyote.http11.Http11AprProcessor.process(Http11AprProcessor.java:859)
 at org.apache.coyote.http11.Http11AprProtocol$Http11ConnectionHandler.process(Http11AprProtocol.java:574)
 at org.apache.tomcat.util.net.AprEndpoint$Worker.run(AprEndpoint.java:1527)
 at java.lang.Thread.run(Thread.java:662) 

一开始我觉得是文件流没有关闭,所以给加了一个try-catch(上面代码是加了之后的),但是依然没有效果,最终询问老师。老师给加了两行代码:

 out.clear();
 out = pageContext.pushBody();

之后就没有异常了。

 

在网上搜了一下out = pageContext.pushBody();

由于jsp container在处理完成请求后会调用releasePageContet方法释放所用的PageContext object,并且同时调用getWriter方法,由于getWriter方法与在jsp页面中使用流相关的getOutputStream方法冲突,所以会造成这种异常,解决办法是:只需要在jsp页面的最后加上两条语句: 

out.clear();
out=pageContext.pushBody();

即可(其中out,pageContext均为jsp内置对象!)

 

下面一篇随笔将会对pageContext对象做一些笔记。

posted @ 2012-08-24 09:20  动感蚂蚁  阅读(319)  评论(0编辑  收藏  举报