验证码源码和java.lang.IllegalStateException解决办法

验证码代码【yanzhengma.jsp】:

<%@ page 
 contentType="image/jpeg" 
 import="java.awt.image.*,java.awt.*,java.util.*,javax.imageio.*"
%>
<%! 
    public Color getRandomColor(int firstcolor,int secondcolor)
    {
        Random random = new Random();
        if(firstcolor>255) firstcolor=255;
        if(secondcolor>255) secondcolor=255;
        int r=firstcolor+random.nextInt(secondcolor-firstcolor);
        int g=firstcolor+random.nextInt(secondcolor-firstcolor);
        int b=firstcolor+random.nextInt(secondcolor-firstcolor);
        return new Color(r,g,b);
   }
%>
<% 
		int width=60,height=20;
		BufferedImage image=new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);	
		Graphics g= image.getGraphics();	
		Random random=new Random();
		g.setColor(getRandomColor(200,250));
		g.fillRect(0, 0, width, height);	
		g.setFont(new Font("Times New Roman",Font.PLAIN,18));	
		g.setColor(getRandomColor(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 yanZhengMa="";
		for (int i=0;i<4;i++){
			int leixing=random.nextInt(62);
			String yanzhengmatemp="r";
			if(leixing<10)
			{
				yanzhengmatemp=String.valueOf(random.nextInt(10));
			}
			else if(leixing<36)
			{
				yanzhengmatemp=((char)(random.nextInt(122-97)+97))+"";
			}
			else
			{
				yanzhengmatemp=((char)(random.nextInt(90-65)+65))+"";
			}
		    yanZhengMa+=yanzhengmatemp;
		    g.setColor(new Color(25+random.nextInt(110),25+random.nextInt(110),25+random.nextInt(110)));
			g.drawString(yanzhengmatemp,13*i+6,16);
		}
	
		session.setAttribute("yanzhengma",yanZhengMa.toLowerCase());
		g.dispose();
		
		//解决java.lang.IllegalStateException: getOutputStream() has already been called
		<span style="color:#FF0000;">out.clear();
		out = pageContext.pushBody(); </span>
		
		ImageIO.write(image, "JPEG", response.getOutputStream());
%>
	


		


登录界面显示验证码界面【login.jsp】:

<%@ page contentType="text/html;charset=gbk" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
	<head>
		<title>登录页面</title>
		<link href="css/login.css" rel="stylesheet" type="text/css"/>
		<link rel="Shortcut Icon" href="images/chinaz1.ico" type="image/x-icon" />
		<script language="JavaScript" src="js/login.js"></script>
		<script language="JavaScript" src="js/position.js"></script>
	</head>
	<body>
	<div id="container">
		<div id="topimg">
<!-- 			<img src="images/login_main.jpg"> -->
		</div>
		
		<div id="loginmain">
		<s:form action="login" theme="simple" method="post" οnsubmit="return check();">
			<table align="center">

				<tr>
					<td>用户名:</td>
					<td><s:textfield id="uid" name="uid"/></td>
					
				</tr>
				<tr>
					<td>密  码:</td>
					<td><s:password id="pwd" name="pwd"/></td>
					
				</tr>
				
				<tr>
					<td>验证码:</td>
					<td valign="middle">
						<s:textfield id="yanzhengma" name="yanzhengma"/>
						<a href="#" οnclick="change();"><img id="yanzhengmatu" src="<span style="color:#FF0000;">yanzhengma.jsp</span>" style="border:0px;" alt="点击换一张"></a>
						<a href="#" οnclick="change();" style="position:absolute;margin-left:60px;margin-top:2px;">换一张</a>
					</td>
					
				</tr>
				<tr>
					<td colspan="2" align="center">
						<s:submit value="登 录" id="submit" cssClass="loginbutton"/>  
						<s:reset value="重 置" cssClass="resetbutton"/>
					</td>
					
				</tr>
			</table>
			<s:textfield id="result" name="result" cssStyle="display:none"/>
		</s:form>
		</div>
	</div>
	
	</body>
</html>

tomcat正常启动。
但是一出来有验证码的页面,后台就会报错:
信息: Server startup in 13157 ms
2008-01-09 21:35:40,390 ERROR [org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/mi].[jsp]] - 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:601)
at org.apache.catalina.connector.ResponseFacade.getWriter(ResponseFacade.java:196)
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:185)
at org.apache.jasper.runtime.JspFactoryImpl.internalReleasePageContext(JspFactoryImpl.java:116)
at org.apache.jasper.runtime.JspFactoryImpl.releasePageContext(JspFactoryImp



在网上查了就是getOutputStream()方法和getWriter()方法只能用一个。但是我没有找到在哪里又调用了getWriter()方法。也不知道怎么改动,这么老是报错心里可不舒服。



最佳答案
 

具体的原因就是
在tomcat中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();

文件代码如下:

OutputStream o=response.getOutputStream();
//输出文件用的字节数组,每次发送500个字节到输出流
byte b[]=new byte[500];
//下载的文件
File fileLoad=new File("f:/2000","book.zip");
//客户使用的保存文件的对话框
response.setHeader("Content-disposition","attachment;filename="+"book.zip");
//通知客户文件的MOME类型
response.setContentType("application/x-tar");
//通知客户文件的长度
long fileLength=fileLoad.length();

String length=String.valueOf(fileLength);

response.setHeader("Content_Length",length);
out.clear();
out = pageContext.pushBody();


//读取文件book.zip,并发送给客户下载
FileInputStream in=new FileInputStream(fileLoad);
int n=0;
while((n=in.read(b))!=-1)
{
o.write(b,0,n);
}

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

// 输出图象到页面
ImageIO.write(image, "JPEG", response.getOutputStream());

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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值