效果如:
代码如下:
package com.hh.login;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.imageio.stream.ImageOutputStream;
import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
/**
* 产生验证码的类
* @author lixunhui
*
*/
public class RandomAction extends ActionSupport{
/**
*
*/
private static final long serialVersionUID = -4403753767066645640L;
private ByteArrayInputStream inputStream;
Logger log=Logger.getLogger(RandomAction.class);
public String execute() throws Exception{
// 在内存中创建图象
int width = 85, height =34;
BufferedImage image = new BufferedImage(width, height,BufferedImage.TYPE_INT_RGB);
Graphics g = image.getGraphics();
Random random = new Random();
g.setColor(getRandColor(200, 250));
g.fillRect(0, 0, width, height);
// g.setFont(new Font("Times New Roman", Font.TYPE1_FONT, 29));
g.setColor(getRandColor(160, 200));
for (int i = 0; i < 150; 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);
}
//画边框
g.setColor(new Color(50,143,207));
g.drawRect(0, 0, width-1, height-1);
// 取随机产生的认证码(2位数字)
char[] codeSequence = { '0', '1','2','3', '4', '5', '6', '7', '8', '9'};
//创建集合存放生成的两个数字
List<String> list=new ArrayList<String>();
for (int i = 0; i < 2; i++) {
String rand = String.valueOf(codeSequence[random.nextInt(codeSequence.length)]);
list.add(rand);
}
//先取出来两个数字的和,然后再给list集合添加“+”和“=”以便组成加法算式
int num=Integer.parseInt(list.get(0))+Integer.parseInt(list.get(1));
log.debug("生成的验证码为:"+list.get(0)+"+"+list.get(1)+"=");
list.add(1, "+");
list.add(3, "=");
Map<Integer,Font> fontmap=createFont();
//遍历集合list将加法算是生成图片
for (int j = 0; j < list.size(); j++) {
g.setColor(new Color(20 + random.nextInt(110), 20 + random.nextInt(110), 20 + random.nextInt(110)));
//随机一种字体
g.setFont(fontmap.get((int)(Math.random()*fontmap.size())));
g.drawString(list.get(j)+" ", 13 * j + 6, 30);
}
Object object = ActionContext.getContext().getSession().get("rand");
if(null!=object){
ActionContext.getContext().getSession().remove("rand");
}
// 将认证码存入SESSION
ActionContext.getContext().getSession().put("rand",num);
HttpServletResponse response = ServletActionContext.getResponse();
response.setHeader("Pragma", "No-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);
// 图象生效
g.dispose();
ByteArrayOutputStream output = new ByteArrayOutputStream();
ImageOutputStream imageOut = ImageIO.createImageOutputStream(output);
ImageIO.write(image, "JPEG", imageOut);
imageOut.close();
ByteArrayInputStream input = new ByteArrayInputStream(output.toByteArray());
this.setInputStream(input);
return SUCCESS;
}
/*
* 给定范围获得随机颜色
*/
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);
}
public void setInputStream(ByteArrayInputStream inputStream) {
this.inputStream = inputStream;
}
public ByteArrayInputStream getInputStream() {
return inputStream;
}
/**
* 生成随机字体
* @return
*/
public static Map<Integer,Font> createFont(){
Map<Integer,Font> result=new HashMap<Integer,Font>();
Font font1=new Font("Dialog", Font.BOLD, 19+(int)(Math.random()*16));
Font font2=new Font("Dialog", Font.ITALIC, 19+(int)(Math.random()*16));
Font font3=new Font("Dialog", Font.PLAIN, 19+(int)(Math.random()*16));
Font font4=new Font("DialogInput", Font.BOLD, 19+(int)(Math.random()*16));
Font font5=new Font("DialogInput", Font.ITALIC, 19+(int)(Math.random()*16));
Font font6=new Font("DialogInput", Font.PLAIN, 19+(int)(Math.random()*16));
Font font7=new Font("Monospaced", Font.BOLD, 19+(int)(Math.random()*16));
Font font8=new Font("Monospaced", Font.ITALIC, 19+(int)(Math.random()*16));
Font font9=new Font("Monospaced", Font.PLAIN, 19+(int)(Math.random()*16));
Font font10=new Font("SansSerif", Font.BOLD, 19+(int)(Math.random()*16));
Font font11=new Font("SansSerif", Font.ITALIC, 19+(int)(Math.random()*16));
Font font12=new Font("SansSerif", Font.PLAIN, 19+(int)(Math.random()*16));
Font font13=new Font("Times New Roman", Font.BOLD, 19+(int)(Math.random()*16));
Font font14=new Font("Times New Roman", Font.ITALIC, 19+(int)(Math.random()*16));
Font font15=new Font("Times New Roman", Font.PLAIN, 19+(int)(Math.random()*16));
Font font16=new Font("arial", Font.BOLD, 19+(int)(Math.random()*16));
Font font17=new Font("arial", Font.ITALIC, 19+(int)(Math.random()*16));
Font font18=new Font("arial", Font.PLAIN, 19+(int)(Math.random()*16));
result.put(1, font1);result.put(2, font2);result.put(3, font3);result.put(4, font4);
result.put(5, font5);result.put(6, font6);result.put(7, font7);result.put(8, font8);
result.put(9, font9);result.put(10, font10);result.put(11, font11);result.put(12, font12);
result.put(13, font13);result.put(14, font14);result.put(15, font15);result.put(16, font16);
result.put(17, font17);result.put(18, font18);
return result;
}
}
在struts.xml文件中配置如下:
<!-- 生存图片的action -->
<action name="rand" class="com.hh.login.RandomAction">
<result type="stream">
<param name="contentType">image/jpeg</param>
<param name="inputName">inputStream</param>
</result>
</action>
在页面中使用下面的方法调用验证码:
<tr>
<td>验证码:</td>
<td><input type="text" value="" name="checkcode" class="txt2"/>
<span><img src="rand.action" onclick="changeValidateCodeFun(this)" alt="换一张" title="换一张" name="randImage" class="imagecode"/></span>
</td>
</tr>
JS方法如下:
function changeValidateCodeFun(obj) {
//获取当前的时间作为参数,无具体意义
var timenow = new Date().getTime();
//每次请求需要一个不同的参数,否则可能会返回同样的验证码
//这和浏览器的缓存机制有关系,也可以把页面设置为不缓存,这样就不用这个参数了。
obj.src="rand.action?d="+timenow;
}