姜太公 发表于 2013-1-27 05:03:34

汉字验证码

package com.toy;import java.util.Random;import java.io.UnsupportedEncodingException;import java.io.OutputStream;import java.awt.image.BufferedImage;import javax.imageio.ImageIO;import java.awt.*;import java.io.*;/** * 一个能生成验证码的类 * 默认四个汉字 * 使用该类生成验证码时 * @author jiangjizhong */public class VerifyCode {    private final Random random = new Random(System.nanoTime());    private int width;    private int height;    private int charNumber = 4;    private float yawpRate = 0.2f; //噪声率    private OutputStream outputStream;    private char[] code;      public VerifyCode() {      //empty    }    /**   * 返回生成的验证码字符串   * @return   */    public String getVerifyCode(){      return new String(code);    }      public VerifyCode(int width, int height) {      this.width = width;      this.height = height;    }    private void drawPane(Graphics2D g2d){      g2d.setColor(Color.BLACK);      g2d.setStroke(new BasicStroke(2.0f));      g2d.drawRect(0, 0, width, height);    }      private void drawChars(Graphics2D g2d){      float scale = 1f;      int size = (int) (scale * height);      int offsetHeight = (height + size) / 2;      StringBuffer sb = new StringBuffer(1);      sb.setLength(1);      g2d.setColor(Color.BLACK);      code = new char;      for (int i = 0; i < charNumber; i++) {            //计算第i个字的x偏移            int offsetWidth = i * size;            //随机大小            int charSize = this.getRandomIntBetween((int) (size * 0.5), size);            //随机样式            int fontStyle = this.getRandomBoolean() ? Font.ITALIC : Font.ITALIC;            g2d.setFont(new Font("隶书", fontStyle, charSize));            //随机颜色            //g2d.setColor(this.getRandomColor());            //随机上移一点            int moveUp = random.nextInt((int) (0.3 * height));            //随机字符            char c = this.getRandomChar();            code = c;            sb.setCharAt(0, c);            g2d.drawString(sb.toString(), offsetWidth, offsetHeight - moveUp);      }    }      private void drawSmallChars(Graphics2D g2d){      final int lines = 5;      int fontSize = this.getHeight() / lines;      int number = this.getWidth() / fontSize;      g2d.setFont(new Font("隶书", Font.PLAIN, fontSize));      g2d.setColor(this.getRandomColor());      for(int i=0; i<10;i++){            StringBuffer sb = new StringBuffer(number);            for(int j=0; j<number; j++){                sb.append(this.getRandomChar());            }            g2d.drawString(sb.toString(), 0, (i + 1) * fontSize);      }    }    /**   * 主要方法,开始生成   */    public void write() {      BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);      Graphics2D g2d = bi.createGraphics();      g2d.setColor(Color.WHITE);      g2d.fillRect(0, 0, width, height);      //画方框9/10期望宽度      this.drawPane(g2d);      //设定字体,字体大小为4/5方框,居中      this.drawChars(g2d);/*补充注释:有些人添加干扰时,喜欢使用随机线条。我认为这个方法一点都不好,不仅是图片极度丑陋,而且根本起不到干扰的作用。*/      //背景上随机10行小字      this.drawSmallChars(g2d);      //添加噪点      int area = (int) (this.getYawpRate() * height * width);      for (int i = 0; i < area; i++) {            int x = random.nextInt(width);            int y = random.nextInt(height);            int rgb = this.getRandomIntColor();            bi.setRGB(x, y, rgb);      }      try {            ImageIO.write(bi, "jpeg", outputStream);      } catch (Exception exc) {            exc.printStackTrace();      }    }    private boolean getRandomBoolean() {      int randInt = random.nextInt(10);      if (randInt > 4) {            return true;      } else {            return false;      }    }    private Color getRandomColor() {      int[] rgb = this.getRandomRgb();      return new Color(rgb, rgb, rgb);    }    private int getRandomIntColor() {      int[] rgb = this.getRandomRgb();      int color = 0;      for (int c : rgb) {            color = color << 8;            color = color | c;      }      return color;    }    private int[] getRandomRgb() {      int[] rgb = new int;      for (int i = 0; i < 3; i++) {            rgb = random.nextInt(255);      }      return rgb;    }    /**   * 返回一个随机汉字字符。   * 采用随机生成两个byte按gb2312编码构成一个String的算法。   * 两个字节在B0A1到D7F9之间,是常用简体字   * 所以,第一个字节在B0(十进制176)到D7(十进制215)之间,第二个字节在A1(十进制161)到F9(十进制249)之间   * @return   */    protected char getRandomChar() {      final int minFirstByte = 176;      final int maxFirstByte = 215;      final int minSecondByte = 161;      final int maxSecondByte = 249;      byte[] b = new byte;      b = (byte) (getRandomIntBetween(minFirstByte, maxFirstByte));      b = (byte) (getRandomIntBetween(minSecondByte, maxSecondByte));      try {            String s = new String(b, "gb2312");            assert s.length() == 1;            return s.charAt(0);      } catch (UnsupportedEncodingException uee) {            //重试            return getRandomChar();      }    }    /**   * 获取两个整数之间的某个随机数,包含较小的整数,不包含较大的整数   * @param first   * @param second   * @return 随机数   */    private int getRandomIntBetween(int first, int second) {      if (second < first) {            int tmp = first;            first = second;            second = tmp;      }      return random.nextInt(second - first) + first;    }      public int getWidth() {      return width;    }/** * 验证码图片的宽度,一般的,宽度应该是高度乘以字符数目 */    public void setWidth(int width) {      this.width = width;    }    public int getHeight() {      return height;    }/** * 验证码图片的高度 */    public void setHeight(int height) {      this.height = height;    }    public OutputStream getOutputStream() {      return outputStream;    }/** * 验证码输出地址,如果是在jsp或servlet里使用,这里的outputStream就是从Response对象里获取的outputStream */    public void setOutputStream(OutputStream outputStream) {      this.outputStream = outputStream;    }    public int getCharNumber() {      return charNumber;    }/*** 生成验证码的字符数量,默认四个*/    public void setCharNumber(int charNumber) {      this.charNumber = charNumber;    }    public float getYawpRate() {      return yawpRate;    }    /**   * 设定噪声率,既图像上出现的噪声像素占全部像素的比例   * @param yawpRate   */    public void setYawpRate(float yawpRate) {      this.yawpRate = yawpRate;    }} 使用该验证码的jsp文件:
 
<%@page contentType="image/jpeg" pageEncoding="UTF-8" import="com.toy.*;"%><%    out.clear();    response.reset();    //设定相应头    //不缓存    response.setHeader("Pragma","No-cache");    response.setHeader("Cache-Control","no-cache");    response.setDateHeader("Expires", 0);    int height = 50;//验证码图片高度    int width = 200;//验证码图片宽度    int charNumber = 4;    if(request.getParameter("height") != null){      height = Integer.parseInt(request.getParameter("height"));    }    if(request.getParameter("width") != null){      width = Integer.parseInt(request.getParameter("width"));    }    if(request.getParameter("charnum") != null){      charNumber = Integer.parseInt(request.getParameter("charNumber"));    }    VerifyCode vc = new VerifyCode(width, height);    vc.setCharNumber(charNumber);    vc.setOutputStream(response.getOutputStream());    vc.write();    session.setAttribute("VerifyCode", vc.getVerifyCode());%>  
页: [1]
查看完整版本: 汉字验证码