java验证码生成的基本流程
1.验证码的生成,我们能够看到是用graphics对象画出来的。对象我们必须要获得graphics对象
1-1、graphics对象的获取,要通过bufferedimage获得
<span style="font-size:18px;">int width=100;//确定框框的大小 int height=40; bufferedimage bfi =new bufferedimage(width, height, bufferedimage.type_int_rgb); graphics g=bfi.getgraphics();//获得graphics对象就可以画图</span>
1-2、一般的验证码背景框都是白色的
<span style="font-size:18px;"> //1,设置背景(白框框) g.setcolor(color.white);//白色的画笔 g.fillrect(0, 0, width, height);//画矩形矩形框框</span>
1-3、保存数据(后台验证使用)和设置字体样式(美观)
string str="";//保存数据 random rom=new random(); //设置字体的大写与粗 g.setfont(new font("a", font.bold,20));
1-4、生成具体的数值,以及随机生成的颜色
for(int i=0;i<4;i++){ int num=rom.nextint(10);//生成的随机数 g.setcolor(new color(rom.nextint(256),rom.nextint(256), rom.nextint(256)));//设置画笔的颜色(随机) g.drawstring(""+num, 20*i, 20+rom.nextint(10));//画出线,x的位置每一之间增加20,y的坐标以20一条线,在线上或者是线下 //ps:位置需要明确些, }
1-5、一般的数字容易被其他软件直接识别出来,为了防黑。稍微加一点干扰线
//画出一些干扰线 for (int i = 0; i < 10; i++) { g.setcolor(new color(rom.nextint(256),rom.nextint(256), rom.nextint(256)));//设置画笔的颜色(随机) g.drawline(rom.nextint(100),rom.nextint(40), rom.nextint(100), rom.nextint(40));//位置也是随机,x,y的值不要超过矩形框框 }
1-6、销毁graphics对象和存储图片
<span style="white-space:pre"> </span>g.dispose();//销毁对象 imageio.write(bfi, "jpeg", res.getoutputstream());//图片用字节流 直接得到 ps::: res是servlet里面的。
这样验证码就生成了,那我们如何导入到前台去呢
2、具体实现
前台代码呈现():
<body> <h1>用户登录</h1><br/> 用户名:<input type="text" name="nametext"/><br/> 密 码:<input type="text" name="psd"/><br/> 请输入验证码:<input type="text"/> <img <span style="color:#ff0000;">src="/img/immg" </span>id="aid"/><a href="javascript:flush()" >看不清</a> </body>
src的地址来源就是从后台发过来的。路径是很有意思的。
2-1步骤
项目里面
myeclipse --> src -->new servlet 出现如下:
点击----》next 出现如下页面:
这个配置会自动到项目里面的web-inf文件夹里面web.xml。这个框框里面的值就是前台 src里面写的需要访问的路径,----> 点击完成就行了。
自动了。生成如下界面:
在这里就可写之前的代码。但是需要注意,我们必须通过覆盖这个方法才能有效:
protected void service(httpservletrequest req, httpservletresponse resp)//自动生成 输入 <span style="font-family: arial, helvetica, sans-serif;">service 补全,自动生成</span> throws servletexception, ioexception { // todo auto-generated method stub super.service(req, resp); }
具体的代码如下:
package cn.hncu.com.servlet; import java.awt.color; import java.awt.font; import java.awt.graphics; import java.awt.image.bufferedimage; import java.io.fileoutputstream; import java.io.ioexception; import java.util.random; import javax.imageio.imageio; import javax.servlet.servletexception; import javax.servlet.servletrequest; import javax.servlet.servletresponse; import javax.servlet.http.httpservlet; import javax.servlet.http.httpservletrequest; import javax.servlet.http.httpservletresponse; public class imgdemo extends httpservlet { @override public void service(servletrequest req, servletresponse res) throws servletexception, ioexception { int width=100;//确定框框的大小 int height=40; bufferedimage bfi =new bufferedimage(width, height, bufferedimage.type_int_rgb); graphics g=bfi.getgraphics();//获得graphics对象就可以画图 //1,设置背景(白框框) g.setcolor(color.white);//白色的画笔 g.fillrect(0, 0, width, height);//画矩形矩形框框 //2,具体生成随机数 string str="";//保存数据 random rom=new random(); //设置字体的大写与粗 g.setfont(new font("a", font.bold,20)); //画出具体的图片 for(int i=0;i<4;i++){ int num=rom.nextint(10);//生成的随机数 g.setcolor(new color(rom.nextint(256),rom.nextint(256), rom.nextint(256)));//设置画笔的颜色(随机) g.drawstring(""+num, 20*i, 20+rom.nextint(10));//画出线,x的位置每一之间增加20,y的坐标以20一条线,在线上或者是线下 //ps:位置需要明确些, } //画出一些干扰线 for (int i = 0; i < 10; i++) { g.setcolor(new color(rom.nextint(256),rom.nextint(256), rom.nextint(256)));//设置画笔的颜色(随机) g.drawline(rom.nextint(100),rom.nextint(40), rom.nextint(100), rom.nextint(40));//位置也是随机,x,y的值不要超过矩形框框 } g.dispose(); imageio.write(bfi, "jpeg", res.getoutputstream());//图片用字节流 直接得到 } }<span style="font-family: arial, helvetica, sans-serif; background-color: rgb(255, 255, 255);"> </span>
前台代码:
<%@ page language="java" import="java.util.*" pageencoding="utf-8"%> <% string path = request.getcontextpath(); string basepath = request.getscheme()+"://"+request.getservername()+":"+request.getserverport()+path+"/"; %> <!doctype html public "-//w3c//dtd html 4.01 transitional//en"> <html> <head> <base href="<%=basepath%>"> <title>my jsp 'img.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="this is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> <script type="text/javascript"> function flush(){ var text=document.getelementbyid("aid"); var date =new date(); var tt=date.gettime(); text.src="/img/immg?"+tt; } </script> </head> <body> <h1>用户登录</h1><br/> 用户名:<input type="text" name="nametext"/><br/> 密 码:<input type="text" name="psd"/><br/> 请输入验证码:<input type="text"/> <img src="/img/immg" id="aid"/><a href="javascript:flush()" >看不清</a> </body> </html>
对于前台代码需要解释一下:
当我们的的验证码传过来看不清的时候需要刷新,而浏览器有自动记忆的功能,当没有新的参数传进来的时候,浏览器是不会刷新的,所以我们需要手动的去写一个js控制参数传,我们知道,只有时间是不会变化的,所有我们采用时间来作为参数传递。
ps:自己坑了一段时间的问题:验证码的路径问题。前端的“/”表示 tomcat目录,在项目内部,如web.xml中“/”表示该项目下。也就是说,他们两个的目录差了一层。
最后附上自己在测试的时候的代码以及修改数字形状的问题,如改成2d的效果更不错。都有很明显的记录。
package cn.hncu.com; import java.awt.color; import java.awt.font; import java.awt.graphics; import java.awt.graphics2d; import java.awt.geom.affinetransform; import java.awt.image.bufferedimage; import java.io.filenotfoundexception; import java.io.fileoutputstream; import java.io.ioexception; import java.util.random; import javax.imageio.imageio; import org.junit.test; public class demoimg { @test public void test() throws exception{ string str="9988"; int width=60; int height=30; //通过bufferedimage对象获得graphics对象 bufferedimage bfi=new bufferedimage(width, height, bufferedimage.type_int_bgr); graphics g=bfi.getgraphics(); g.drawstring(str, 10,10); g.dispose();//类似于io中的关流 imageio.write(bfi , "jpeg", new fileoutputstream("f:\\ex\\a.jpg")); //bfi为画布,将画布写到文件中jpeg为指定文件格式 } @test public void test2() throws exception{ int width=100; int height=40; bufferedimage bfi =new bufferedimage(width, height, bufferedimage.type_int_rgb); graphics g=bfi.getgraphics();//获得graphics对象就可以画图 //1,设置背景(白框框) g.setcolor(color.white);//白色的画笔 g.fillrect(0, 0, width, height); //2,具体生成随机数 string str="";//保存数据 random rom=new random(); //设置字体的大写与粗 g.setfont(new font("a", font.bold,20)); //画出具体的图片 for(int i=0;i<4;i++){ int num=rom.nextint(10);//生成的随机数 g.setcolor(new color(rom.nextint(256),rom.nextint(256), rom.nextint(256)));//设置画笔的颜色(随机) g.drawstring(""+num, 20*i, 20+rom.nextint(10));//画出线,x的位置每一之间增加20,y的坐标以20一条线,在线上或者是线下 //ps:位置需要明确些, } //画出一些干扰线 for (int i = 0; i < 10; i++) { g.setcolor(new color(rom.nextint(256),rom.nextint(256), rom.nextint(256)));//设置画笔的颜色(随机) g.drawline(rom.nextint(100),rom.nextint(40), rom.nextint(100), rom.nextint(40));//位置也是随机,x,y的值不要超过矩形框框 } g.dispose(); imageio.write(bfi, "jpeg", new fileoutputstream("f:\\ex\\b.jpg")); } //画出可以变化的情况 //字体能够旋转的验证码 @test public void test3() throws ioexception{ int width=100; int height=40; bufferedimage bfi =new bufferedimage(width, height, bufferedimage.type_int_rgb); graphics g=bfi.getgraphics(); graphics2d g2d=(graphics2d) g; random rom =new random(); g2d.setcolor(color.white);//设置画笔的颜色 g2d.fillrect(0, 0, width, height);//画出一个白色的矩形 g2d.setfont(new font("a", font.bold, 20)); for(int i=0;i<4;i++){ int num=rom.nextint(10); //旋转,放缩 affinetransform aff=new affinetransform(); //aff.rotate(math.random(), i*18, height-20);//旋转 aff.scale(0.6+math.random(), 0.6+math.random());//缩放 g2d.setcolor(new color(rom.nextint(256),rom.nextint(256),rom.nextint(256))); g2d.settransform(aff); g2d.drawstring(""+num, i*18, height-25); } g2d.dispose(); imageio.write(bfi, "jpeg", new fileoutputstream("f:\\ex\\c.jpg")); } }
以上就是关于java生成验证码的基本流程,还附带了自己亲自的测试的代码,希望这些都能帮到大家。