<%@ page language="java" import="java.util.*" pageEncoding="GBK"
import="java.awt.*,java.awt.image.*,javax.imageio.*"%><%
/*
使用方法:在需要显示验证码的html代码中使用<img p">
在需判断session的时候判断session.getAttribute("vcode")
*/
try{
int codeLength=4;//验证码长度
int mixTimes=5;//模糊程度参数
Color bgColor=getRandColor(200, 250);//背景颜色
Color bfColor=new Color(0,0,0);//字体颜色
boolean ifRandomColor=true;//单个字符是否颜色随机
boolean ifMixColor=true;//模糊线是否颜色随机 //设置页面不缓存
response.setHeader("Pragma", "No-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);
// 在内存中创建图象
int width = 13*codeLength+6, height = 20;
BufferedImage image = new BufferedImage(width, height,BufferedImage.TYPE_INT_RGB);
// 获取图形上下文
Graphics g = image.getGraphics();
// 设定背景色
g.setColor(bgColor);
g.fillRect(0, 0, width, height);
//设定字体
g.setFont(new Font("Times New Roman", Font.PLAIN, 18));
//画边框
g.setColor(new Color(33,66,99));
g.drawRect(0,0,width-1,height-1);
// 随机产生干扰线,使图象中的认证码不易被其它程序探测到
g.setColor(getRandColor(160, 200));
for (int i = 0; i < mixTimes*codeLength/10; i++) {
if(ifMixColor)
g.setColor(getRandColor(160, 200));
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);
}
// 取随机产生的认证码(codeLength位数字)
String sRand = "";
String rand;
String letters="abcdefghijklmnopqrstuvwxyz0123456789";
for (int i = 0; i < codeLength; i++) {
int l=random.nextInt(36);
rand = letters.substring(l,l+1);
sRand = sRand+rand;
// 将认证码显示到图象中
if(ifRandomColor)
g.setColor(getRandColor(20,110,0));
else
g.setColor(bfColor);
//调用函数出来的颜色相同,可能是因为种子太接近,所以只能直接生成
g.drawString(rand, 13 * i + 6, 16);
}
// 将认证码存入SESSION
session.setAttribute("vcode", sRand);
System.out.println("vcode.jsp生成的验证:"+sRand);
// 图象生效
g.dispose();
// 输出图象到页面
ImageIO.write(image, "PNG", response.getOutputStream());
}catch(Exception e){}
%>
<%!
//给定范围获得随机颜色
private static Random random=new Random();
private Color getRandColor(int fc, int bc) {
return getRandColor(fc, bc, fc);
}
private Color getRandColor(int fc, int bc,int interval) {
if (fc > 255) {
fc = 255;
}
if (bc > 255) {
bc = 255;
}
int r = fc + random.nextInt(bc - interval);
int g = fc + random.nextInt(bc - interval);
int b = fc + random.nextInt(bc - interval);
return new Color(r, g, b);
}
%>
运行之后,能够生成验证码,而且也能够正确验证。
问题是:这句代码:ImageIO.write(image, "PNG", response.getOutputStream());
总是报异常!java.lang.IllegalStateException: getOutputStream() has already been called for this response这段代码是在学校做项目,老师提供的。项目现在做好了,但总是这里有点瑕疵,心里总是不舒服。
因为代码是拷贝回来的,我也不知道怎么修改。请问怎样修改呢?谢谢!
解决方案 »
- 问个lucene和庖丁解丁结合的问题
- 循环显示数据的问题
- 搞了三天的分页了!可是这里还是有点问题.高手来指点指点
- 求救:如何用JAVA搜索word或者excel文件里的字符
- 要在每一条记录指定的值的后面追加个字符串,改怎么做?
- 200分,请问jbuilder里如何操作hibernate?hibernate的配置文件没有提示功能?只能硬编码吗?那还不如写SQL来得自如快速?
- 急!求教关于String 对象 与 ORACLE 的CLOB字段问题?????????
- 请教高手,如何使用jsp+javabean来修改目录服务中的数据?在线等待,参与有分,分不够再加!
- 大家帮我看一下这个程序到底错在哪里?
- JSP界面的的传输值
- txt文件下载,很多人问过,但是...
- 关于Quartz动态设置时间
楼主【siu5】截止到2008-07-15 23:33:31的历史汇总数据(不包括此帖):
发帖的总数量:30 发帖的总分数:585 每贴平均分数:19
回帖的总数量:39 得分贴总数量:2 回帖的得分率:5%
结贴的总数量:24 结贴的总分数:445
无满意结贴数:8 无满意结贴分:370
未结的帖子数:6 未结的总分数:140
结贴的百分比:80.00 % 结分的百分比:76.07 %
无满意结贴率:33.33 % 无满意结分率:83.15 %
楼主加油
因为Application Server在处理编译jsp时对于%>和<%之间的内容一般是原样输出,而且默认是PrintWriter,
而你却要进行ImageIO.write图片输出,这样做相当于试图在Servlet中使用两种输出机制,
就会发生:getOutputStream() has already been called for this response的错误
详细请见《More Java Pitfill》一书的第二部分 Web层Item 33:试图在Servlet中使用两种输出机制 270
还要请问:把代码放在Servlet里面的话,在页面的代码应该怎样写呢?
原来我的代码是:<img src=vcode.jsp>
其实我也曾经考虑放在Servlet里面,但当时并不知道放在servlet里面可以解决异常的问题,而是觉得这个JSP文件,其实全部都是java代码,好像并不应该放在作为界面层的JSP文件里面。
但我又不知道<img>标签的代码应该怎样修改。另外,我还从来没试过把.JSP改成.JAVA文件哩,是不是把几个<% %>之间的代码改成相应的几个方法?
还请继续赐教。谢谢!
2.在web.xml里配置servlet
<servlet>
<servlet-name>Image</servlet-name>
<!--servlet类的全名,即包括包名+类名-->
<servlet-class>com.test.servlet.Image</servlet-class>
<load-on-startup>10</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Image</servlet-name>
<!--这里配置访问路径-->
<url-pattern>/servlet/Image</url-pattern>
</servlet-mapping>
3.页面上引用
<img src="servlet/Image">
out=pageContext.pushBody();
在jsp里清除out也可以排除异常