注,本代码引用来之张孝祥的最新力作<深入体验java web开发内幕-核心基础>,保留所有权利。
此段servlet完整展示了动态验证码的生成过程,通俗易懂,不愧为张老师所写的代码,在此遇到一个问题,就是常说的javax.servlet包无法引入,我按要求都把servlet包放入了lib目录中,可还是一样找不到,因此实际调试效果还没看到。
首先是一个简单的登录页面。
Check_login.htm
<html>
<head>
<title>实现验证码功能</title>
</head>
<body>
<h1>带有验证码功能的登录演示</h1>
<form action="LogonFormServlet">
<table>
<tr>
<td>用户名:</td>
<td><input type="text" name="userName"></td>
</tr>
<tr>
<td>密码:</td>
<td><input type="password" name="password"></td>
</tr>
<tr>
<td>验证码:</td>
<td><input type="text" value="mildo" name="passport"><img src="CheckCodeServlet"></td>
</tr>
<tr colspan="2">
<td><input type="submit" value="登录"></td>
</tr>
</table>
</form>
</body>
</html>
接下来就是生成图片验证码的Servlet了,源代码: CheckCodeServlet.java
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.awt.*;
import java.awt.image.*;
import javax.imageio.ImageIO;

public class CheckCodeServlet extends HttpServlet
 ...{
private static int WIDTH=60;
private static int HIGHT=20;
public void doGet(HttpServletRequest request,HttpServletResponse response)
throws IOException,ServletException
 ...{
HttpSession session = Request.session();
response.setContent("image/jpeg");
ServletOutputStream sos = response.getOutputStream();
//设置浏览器不要缓存图片
response.setHead("Pragma","No-cache");
response.setHead("Cache-Control","no-cache");
response.setDateHead("Expires",0);
//创建内建图像,并获得上下文
BufferedImage image = new BufferedImage(WIDTH,HIGHT,BufferedImage.TYPE_INT_RGB);
Graphics g = image.getGraphics();
//生成随机认证码
char [] rands = new generateCheckCode();
//产生图像
drawBackgrounds(g);
drawRands(g,rands);
//结束图像绘制,完成输出
g.dispose();
//输出到客户端
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ImageIO.write(image,"jpeg",bos);
byte [] buf = bos.toByteArray();
response.setContentLength(buf.length);
//下面的语句也可以写成 bos.write(sos);
sos.wirte(buf);
bos.close();
sos.close();
//将当前验证码插入到session中
session.setAttribute("check_code",new String(rands));
}
private char[] generateCheckCode()
 ...{
//定义验证码的字符集
String str = "0123456789abcdefghjklmnopqrstuvwxyz";
char [] rands = new char[4];
for(int i=0;i<4;i++)
 ...{
int rand = (int)(Math.random()*36);
rands[i] = chars.charAt(rand);
}
return rands;
}
private void drawRands(Graphics g,char[] rands)
 ...{
g.setColor(Color.black);
g.setFont(new Font(null,Font.ITALIC|Font.BOLD,18));
//在不同的高度输出验证码的字符
g.drawString(""+rands[0],1,16);
g.drawString(""+rands[1],16,18);
g.drawString(""+rands[2],32,15);
g.drawString(""+rands[3],51,17);
System.out.println(rands);
}
private void drawBackground(Graphics g)
 ...{
//画背景
g.setColor(Color.cyan);
g.fillRect(0,0,WIDTH,HIGHT);
//添加随机120个杂点
for(int i=0;i<120;i++)
 ...{
int x = (int)(Math.random()*WIDTH);
int y = (int)(Math.random()*HIGHT);
int red = (int)(Math.random()*255);
int blue = (int)(Math.random()*255);
int green = (int)(Math.random()*255);
g.setColor(new Color(red,green,blue));
g.drawOval(x,y,1,0);
}
}
}
用来验证的servlet代码: LogonFormServlet.java
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.awt.*;
import java.awt.image.*;
import javax.imageio.ImageIO;

public class CheckCodeServlet extends HttpServlet
 ...{
private static int WIDTH=60;
private static int HIGHT=20;
public void doGet(HttpServletRequest request,HttpServletResponse response)
throws IOException,ServletException
 ...{
HttpSession session = Request.session();
response.setContent("image/jpeg");
ServletOutputStream sos = response.getOutputStream();
//设置浏览器不要缓存图片
response.setHead("Pragma","No-cache");
response.setHead("Cache-Control","no-cache");
response.setDateHead("Expires",0);
//创建内建图像,并获得上下文
BufferedImage image = new BufferedImage(WIDTH,HIGHT,BufferedImage.TYPE_INT_RGB);
Graphics g = image.getGraphics();
//生成随机认证码
char [] rands = new generateCheckCode();
//产生图像
drawBackgrounds(g);
drawRands(g,rands);
//结束图像绘制,完成输出
g.dispose();
//输出到客户端
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ImageIO.write(image,"jpeg",bos);
byte [] buf = bos.toByteArray();
response.setContentLength(buf.length);
//下面的语句也可以写成 bos.write(sos);
sos.wirte(buf);
bos.close();
sos.close();
//将当前验证码插入到session中
session.setAttribute("check_code",new String(rands));
}
private char[] generateCheckCode()
 ...{
//定义验证码的字符集
String str = "0123456789abcdefghjklmnopqrstuvwxyz";
char [] rands = new char[4];
for(int i=0;i<4;i++)
 ...{
int rand = (int)(Math.random()*36);
rands[i] = chars.charAt(rand);
}
return rands;
}
private void drawRands(Graphics g,char[] rands)
 ...{
g.setColor(Color.black);
g.setFont(new Font(null,Font.ITALIC|Font.BOLD,18));
//在不同的高度输出验证码的字符
g.drawString(""+rands[0],1,16);
g.drawString(""+rands[1],16,18);
g.drawString(""+rands[2],32,15);
g.drawString(""+rands[3],51,17);
System.out.println(rands);
}
private void drawBackground(Graphics g)
 ...{
//画背景
g.setColor(Color.cyan);
g.fillRect(0,0,WIDTH,HIGHT);
//添加随机120个杂点
for(int i=0;i<120;i++)
 ...{
int x = (int)(Math.random()*WIDTH);
int y = (int)(Math.random()*HIGHT);
int red = (int)(Math.random()*255);
int blue = (int)(Math.random()*255);
int green = (int)(Math.random()*255);
g.setColor(new Color(red,green,blue));
g.drawOval(x,y,1,0);
}
}
}
这些做好了,当然要对servlet进行注册和映射了,web.xml
<servlet-name>CheckCodeServlet</servlet-name>
<servlet-class>CheckCodeServlet</servlet-class>
</servlet>

<servlet>
<servlet-name>LogonFormServlet</servlet-name>
<servlet-class>LogonFormServlet</servlet-class>
</servlet>

<servlet-mapping>
<serlet-name>CheckCodeServlet</serlet-name>
<url-pattern>/CheckCodeServlet</url-pattern>
</servlet-mapping>
<servlet-mapping>
<serlet-name>LogonFormServlet</serlet-name>
<url-pattern>/LogonFormServlet</url-pattern>
</servlet-mapping>
|