网页图片验证码实验心得
来源:互联网 发布:hl中走丝系统编程 编辑:程序博客网 时间:2024/06/06 00:52
方法一,直接在JSP页面中写java代码
checkCodeImage.jsp
<%@ page contentType="image/jpeg" import="java.awt.*,java.awt.image.*,java.util.*,javax.imageio.*,java.io.OutputStream" pageEncoding="gb2312"%>
<%!
Color getRandColor(int fc,int bc){//给定范围获得随机颜色
Random random = new Random();
if(fc>255) fc=255;
if(bc>255) bc=255;
int r=fc+random.nextInt(bc-fc);
int g=fc+random.nextInt(bc-fc);
int b=fc+random.nextInt(bc-fc);
return new Color(r,g,b);
}
%>
<%
//设置页面不缓存
response.setHeader("Pragma","No-cache");
response.setHeader("Cache-Control","no-cache");
response.setDateHeader("Expires", 0);
//生成随机类
Random random = new Random();
// 在内存中创建图象
int width=60;
int height=20;
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
// 获取图形上下文
Graphics g = image.getGraphics();
// 设定背景色
g.setColor(getRandColor(200,250));
g.fillRect(0, 0, width, height);
//设定字体
g.setFont(new Font("Times New Roman",Font.PLAIN,18));
//画边框
//g.setColor(new Color());
//g.drawRect(0,0,width-1,height-1);
// 随机产生155条干扰线,使图象中的认证码不易被其它程序探测到
g.setColor(getRandColor(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);
}
// 取随机产生的认证码(4位数字)
String sRand="";
for (int i=0;i<4;i++){
String rand=String.valueOf(random.nextInt(10));
sRand+=rand;
// 将认证码显示到图象中
g.setColor(new Color(20+random.nextInt(110),
20+random.nextInt(110),
20+random.nextInt(110)));//调用函数出来的颜色相同,可能是因为种子太接近,所以只能直接生成
g.drawString(rand,13*i+6,16);
}
// 将认证码存入SESSION
session.setAttribute("checkCode",sRand);
// 图象生效
g.dispose();
// 输出图象到页面
OutputStream os=response.getOutputStream();
ImageIO.write(image, "JPEG", os);
os.flush();
os.close();
os=null;
response.flushBuffer();
out.clear();
out = pageContext.pushBody();
%>
使用:
<img src="checkCodeImage.jsp" width="60" height="20">
注意:
如果没有红色那段代码会出现
getOutputStream() has already been called for this response异常
解决方法:
http://blog.csdn.net/iron_wang/archive/2009/05/20/4204672.aspx
1.
tomcat5下jsp出现getOutputStream() has already been called for this response异常的原因和解决方法在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()相冲突的!所以会出现以上这个异常。
然后当然是要提出解决的办法,其实挺简单的(并不是和某些朋友说的那样--
将jsp内的所有空格和回车符号所有都删除掉),
在使用完输出流以后调用以下两行代码即可:
out.clear();
out = pageContext.pushBody();
2
getOutputStream() has already been called for this response问题的解决
在jsp向页面输出图片的时候,使用response.getOutputStream()会有这样的提示:java.lang.IllegalStateException:getOutputStream() has already been called for this response,会抛出Exception
原因一:
JSP默认的输出流为PrintWriter ,即<% %>以外的东西所默认的输出方式,如果你尝试在JSP中使用ServletOutputStream就会引起错误.要嘛直接改用Servlet输出(复写service方法),要嘛删除除%><%中的任何东西
(包括HTML标签,空格,回车等东西)应该就可以。
对于这样的情况应该这样来解决,删除%><%之间的所有内容包括空格和换行符,最后也要消除空格和换行符,
最好再加上一句response.reset()。
原因二:
在J2EE的API参考里有这么个:
ServletResponse的getWriter()方法里会抛出这个异常,
IllegalStateException - if the getOutputStream method has already been called
for this response object
而它的getOutputStream()方法里会抛出这个异常.
IllegalStateException - if the getOutputStream method has already been called for this response object
并且两者的函数申明里都有这么样的一句
Either this method or getOutputStream() may be called to write the body, not both.
Either this method or getWriter() may be called to write the body, not both.
以上说明也解释了为什么在往页面中写入图片的时候要使用如下循环格式
OutputStream output=response.getOutputStream();
while((len=in.read(b)) >0)
{
output.write(b,0,len);
}
output.flush();
而不是把response.getOutputStream().write()放到循环体内
在页面中直接写:
<body bgcolor="#ffffff">
<h1>
<%
response.getOutputStream();
%>
</h1>
</body>
将会出现错误消息如下:
java.lang.IllegalStateException: getOutputStream() has already been called for this response
org.apache.catalina.connector.Response.getWriter(Response.java:604)
org.apache.catalina.connector.ResponseFacade.getWriter(ResponseFacade.java:198)
org.apache.jasper.runtime.JspWriterImpl.initOut(JspWriterImpl.java:125)
org.apache.jasper.runtime.JspWriterImpl.flushBuffer(JspWriterImpl.java:118)
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/iron_wang/archive/2009/05/20/4204672.aspx
方法二:在servlet中处理
我的Servlet代码如下:
注意com.sun.image.codec.jpeg包位于jdk目录的rt.jar包中,它不是公开的api,需要将rt.jar复制到web应用程序的web-inf/lib下。
import java.io.IOException;
import java.io.OutputStream;
import java.util.Random;
import java.awt.*;
import java.awt.image.*;
import com.sun.image.codec.jpeg.JPEGEncodeParam;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
import com.sun.image.codec.jpeg.JPEGCodec;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
public class ImageProduceServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//设置ContentType
response.setContentType("text/jpeg");
//设置页面不缓存
response.setHeader("Pragma","No-cache");
response.setHeader("Cache-Control","no-cache");
response.setDateHeader("Expires", 0);
//生成并输出图片
String s=this.createImg(response.getOutputStream());
//session记录生成的随机验证码
HttpSession mySession=request.getSession();
mySession.setAttribute("checkCode", s);
}
private String createImg(OutputStream os){
//生成随机类
Random random = new Random();
// 在内存中创建图象
int width=60;
int height=20;
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
// 获取图形上下文
Graphics g = image.getGraphics();
// 设定背景色
g.setColor(getRandColor(200,250));
g.fillRect(0, 0, width, height);
//设定字体
g.setFont(new Font("Times New Roman",Font.PLAIN,18));
//画边框
//g.setColor(new Color());
//g.drawRect(0,0,width-1,height-1);
// 随机产生155条干扰线,使图象中的认证码不易被其它程序探测到
g.setColor(getRandColor(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);
}
// 取随机产生的认证码(4位数字)
String sRand="";
for (int i=0;i<4;i++){
String rand=String.valueOf(random.nextInt(10));
sRand+=rand;
// 将认证码显示到图象中
g.setColor(new Color(20+random.nextInt(110),
20+random.nextInt(110),
20+random.nextInt(110)));//调用函数出来的颜色相同,可能是因为种子太接近,所以只能直接生成
g.drawString(rand,13*i+6,16);
}
// 图象生效
g.dispose();
// encode:
JPEGImageEncoder encoder =JPEGCodec.createJPEGEncoder(os);
JPEGEncodeParam param = JPEGCodec. getDefaultJPEGEncodeParam(image);
param.setQuality(1.0f, false);
encoder.setJPEGEncodeParam(param);
try {
encoder.encode(image);
} catch(IOException ioe) {
ioe.printStackTrace();
}
return sRand;
}
/**
* 给定范围获得随机颜色
* @param fc
* @param bc
* @return
*/
private Color getRandColor(int fc,int bc){
Random random = new Random();
if(fc>255) fc=255;
if(bc>255) bc=255;
int r=fc+random.nextInt(bc-fc);
int g=fc+random.nextInt(bc-fc);
int b=fc+random.nextInt(bc-fc);
return new Color(r,g,b);
}
}
使用:
<img src="servlet/ImageProduceServlet" width="60" height="20">
解释:
http://www.computersci.net/articles/jdk1.2/docs/guide/2d/api-jpeg/com/sun/image/codec/jpeg/JPEGCodec.html
以上是类
JPEGCodec 的API
本质上,浏览器向服务器请求静态图片如jpeg时,服务器返回的仍然是标准的http响应,只不过http头的contenttype不是text/html,而是image/jpeg而已,因此,我们在servlet中只要设置好contenttype,然后发送图像的数据流,浏览器就能正确解析并显示出图片。在java中,java.awt和java.awt.image包提供了基本的绘制图像的能力,我们可以在内存中绘制好需要的图形,然后编码成jpeg或其他图像格式,最后发送相应给浏览器即可。
下面是使用servlet动态创建图像的详细步骤:
1创建bufferedimage对象,该对象存在内存中,负责保存绘制的图像;
2创建graphics2d对象,该对象负责绘制所需的图像;
3当绘制完成后,调用com.sun.image.codec.jpeg包的jpeg编码器对其编码;
4最后将编码后的数据输出至httpresponse即可。
注意com.sun.image.codec.jpeg包位于jdk目录的rt.jar包中,它不是公开的api,需要将rt.jar复制到web应用程序的web-inf/lib下。
1我们先创建一个最简单的servlet:
public class createimageservlet extends httpservlet {
protected void doget(httpservletrequest request, httpservletresponse response) throws servletexception, ioexception {
response.setcontenttype("image/jpeg");
}
}
我们首先设置了response的contenttype为image/jpeg,这样浏览器就可以正确识别。
2然后,创建一个大小为100x100的bufferedimage对象,准备绘图:
int width = 100;
int height = 100;
bufferedimage bi = new bufferedimage(width, height, bufferedimage.type_int_rgb);
3接着,bufferedimage对象中获取graphics2d对象并绘图:
graphics2d g = bi.creategraphics(); // 创建graphics2d对象
g.setbackground(color.blue);// 填充背景为白色
g.clearrect(0, 0, width, height);
g.setcolor(color.red);// 设置前景色
// 开始绘图:
g.drawline(0, 0, 99, 99); // 绘制一条直线
g.dispose();
bi.flush();// 绘图完成,释放资源
4然后,对bufferedimage进行jpeg编码:
JPEGImageEncoder encoder =JPEGCodec.createJPEGEncoder(out);
JPEGEncodeParam param = JPEGCodec. getDefaultJPEGEncodeParam(bi);
param.setQuality(1.0f, false);
encoder.setJPEGEncodeParam(param);
try {
encoder.encode(bi);
} catch(IOException ioe) {
ioe.printStackTrace();
}
5.编码后的jpeg图像直接输出到了out对象中,
我们只要传入response. getoutputstream()就可以直接输出到httpresponse中。
- 网页图片验证码实验心得
- 网页图片验证码实验心得
- PHP实验图片验证码
- WebSite---前台系统图片验证码心得
- WebSite---前台系统图片验证码心得
- WebSite---前台系统图片验证码心得
- Java利用captcha实验图片验证码
- 获取网页中的验证码图片
- 获取网页中的验证码图片
- 获取网页中的验证码图片
- 获取网页中的验证码图片
- 获取网页中的验证码图片
- C#如何获取网页验证码图片
- C#获取网页中的验证码图片
- struts向网页输出图片验证码
- JAVA生成网页图片验证码
- JAVA网页图片验证码的实现
- 网页编程---生成图片验证码技术
- JavaScript与C#之间函数与变量的相互调用(转)
- 解析KML文件 , 获取Coordinates标签中的经纬度坐标值
- 函数模板与名字空间, 编译错误C2440
- how to create list box example
- BI走下神坛 商业分析或成新宠
- 网页图片验证码实验心得
- “/r/n”回车与换行
- VolumeParticle(1)
- how to use the CAknwaitDialog
- 11
- 匈牙利 规范
- isag webservice axis
- 面向 OLTP 应用程序的重要 SQL Server 2005 性能问题
- Introduction