/*一共三个部分
* 1. java代码
* 2. servlet配置
* 3. jsp文件
* 分别保存即可
*/
//附效果图
/*
* 验证码 源码 请保存为VerifyCode1.java
*/
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
public class VerifyCode1 extends HttpServlet{
private static VerifyCode1 instance ;
//private static final VerifyCode1 generator = new VerifyCode1();
private final String ATTRIBUTE_NAME = "verifycode";
//验证码长度
private final int CODE_LENGTH = 4;
//随机字符串范围
private final String RAND_RANGE = "abcdefghijklmnopqrstuvwxyz"+
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" +"1234567890";
private Random rand = new Random();
//可选字体
private String[] FontFamily={"Times New Roman","宋体","黑体","Arial Unicode MS","Lucida Sans"};
//选转标志,验证码旋转
private boolean ROTATE_FLAG=true;
//高度,设置旋转后,高度设为30,否则设置成25,效果好一些
private int Height = 30;
private final char[] CHARS = RAND_RANGE.toCharArray();
public VerifyCode1(){
//
}
public static VerifyCode1 getInstance(){
if(instance == null)
instance = new VerifyCode1();
return instance;
}
/**
* 生成随机字符串
* @return 随机字符串
*/
private String getRandString(){
StringBuffer vcode = new StringBuffer();
for (int i = 0; i < CODE_LENGTH; i++)
vcode.append(CHARS[rand.nextInt(CHARS.length)]);
return vcode.toString();
}
/**
* 生成随机颜色
* @param ll 产生颜色值下限(lower limit)
* @param ul 产生颜色值上限(upper limit)
* @return 生成的随机颜色对象
*/
private Color getRandColor(int ll, int ul){
if (ll > 255) ll = 255;
if (ll < 1) ll = 1;
if (ul > 255) ul = 255;
if (ul < 1) ul = 1;
if (ul == ll) ul = ll + 1;
int r = rand.nextInt(ul - ll) + ll;
int g = rand.nextInt(ul - ll) + ll;
int b = rand.nextInt(ul - ll) + ll;
Color color = new Color(r,g,b);
return color;
}
/**
* 生成指定字符串的图像数据
* @param verifyCode 即将被打印的随机字符串
* @return 生成的图像数据
* */
private BufferedImage getImage(String verifyCode){
int width = CODE_LENGTH * 18 + 20;
BufferedImage image = new BufferedImage(width, Height, BufferedImage.TYPE_INT_RGB);
//获取图形上下文
Graphics graphics = image.getGraphics();
Graphics2D g2 = (Graphics2D) graphics;
g2.setColor(getRandColor(100,255));
g2.fillRect(0, 0, width, Height);
//边框
//g2.drawRect(0,0,CODE_LENGTH * 18 + 20,Height);
//5条干扰线
for(int i=0;i<5;i++){
g2.setColor(new Color(rand.nextInt(255),rand.nextInt(255),rand.nextInt(255)));
g2.drawLine(rand.nextInt(width),rand.nextInt(Height),
rand.nextInt(width),rand.nextInt(Height));
}
int fontsize;
int fontstyle = 0;
double oldrot = 0;
String vcode = getRandString();
for (int i=0; i<CODE_LENGTH; i++){
fontsize = Math.abs(rand.nextInt(24));
// 18-24 fontsize
if(fontsize < 12)
fontsize += 12;
if(fontsize < 18)
fontsize += 6;
fontstyle=rand.nextInt(6) ;
g2.setFont(new Font(FontFamily[rand.nextInt(5)], fontstyle, fontsize));
double rot = -0.25 + Math.abs(Math.toRadians(rand.nextInt(25)));
//如果设置选装标志,则旋转文字
if(ROTATE_FLAG){
g2.rotate(-oldrot,10,15);
oldrot = rot;
g2.rotate(rot,15 * i + 10 , 15);
}
float stroke = Math.abs(rand.nextFloat()%30);
g2.setStroke(new BasicStroke(stroke));
String temp = vcode.substring(i, i+1);
g2.setColor(new Color(rand.nextInt(255),rand.nextInt(255),rand.nextInt(255)));
g2.setColor(getRandColor(1,100));
g2.drawString(temp, 18 * i + 10, 20);
}
//图像生效
g2.dispose();
return image;
}
/**
* 将验证码的图像输出
* @param request 用户的请求对象
* @param response 用户的响应对象
* */
public void printImage(HttpServletRequest request,
HttpServletResponse response){
//将ContentType设为"image/jpeg",让浏览器识别图像格式。
response.setContentType("image/jpeg");
//设置页面不缓存
response.setHeader("Pragma", "No-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 2000);
//获得随机验证码
String verifyCode = this.getRandString();
//获得验证码的图像数据
BufferedImage bi = this.getImage(verifyCode);
//把验证码存入session
request.getSession().setAttribute(ATTRIBUTE_NAME, verifyCode);
try{
//获得Servlet输出流
ServletOutputStream outStream = response.getOutputStream();
//创建可用来将图像数据编码为JPEG数据流的编码器
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(outStream);
//将图像数据进行编码
encoder.encode(bi);
//强行将缓冲区的内容输入到页面
outStream.flush();
//关闭输出流
outStream.close();
}catch(IOException ex){
ex.printStackTrace();
}
}
public void doGet(HttpServletRequest request,HttpServletResponse response){
printImage(request,response);
}
/**
* 检查输入的验证码是否正确,若用户输入的验证码与生成的验证码相符则返回true,否则返回false。
* @param request 用户的请求对象
* @return 验证结果
* */
public boolean check(HttpServletRequest request){
if (((String)request.getParameter(ATTRIBUTE_NAME))
.equalsIgnoreCase((String)request.getSession().getAttribute(ATTRIBUTE_NAME))){
request.getSession().removeAttribute(ATTRIBUTE_NAME);
return true;
}
return false;
}
}
//servlet 配置
<servlet>
<servlet-name>GetVerCode</servlet-name>
<servlet-class>VerifyCode1</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>GetVerCode</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
//jsp文件
<%@ page language="java" pageEncoding="utf-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>验证码</title>
</head>
<script>
function changevc(){
var o = document.getElementById("vercode");
o.src="GetVerCode?rnd=" + Math.random();
}
</script>
<body>
<form action="">
验证码:<input type="text" name="vcode">
<img src="GetVerCode" id="vercode">
<a href="javascript:changevc()">看不清</a>
</form>
</body>
</html>