可以生成纯数字验证码,也可以生成数字+字母组合验证码,取决于使用哪个构造方法
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Date;
import java.util.Random;
/**
* @author shazeys
* @description: 字符图片验证码
* @date 2019/12/9 15:06
*/
public class PicAuthImg {
private static final Logger LOG = LoggerFactory.getLogger(PicAuthImg.class);
public static final String SESSION_PARAM_PICCODE = "picAuthCode";
/** 随机产生数字与字母组合的字符串 取消0,1,l,I,O 容易混淆的值*/
private final String randStr = "23456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ";
private final String randNum = "0123456789";
/** 图片宽 */
private int width = 95;
/** 图片高 */
private int height = 25;
/** 干扰线数量 */
private int lineSize = 40;
/** 随机产生字符数量 */
private int stringNum = 4;
/** 仅数字 */
private boolean onlyNum = false;
/** 需要处理的码 */
private String code ;
/** 验证码图片Buffer */
private BufferedImage buffImg = null;
private Random random = new Random();
/** 使用默认参数 */
public PicAuthImg() {
this.createPicture();
}
public PicAuthImg(boolean onlyNum) {
this.onlyNum = onlyNum;
this.createPicture();
}
/** 指定验证码 */
public PicAuthImg(String code) {
this.code = code;
this.createPictureCode();
}
/** 指定图片大小和验证码 */
public PicAuthImg(int width, int height, int lineSize, String code) {
this.width = width;
this.height = height;
this.lineSize = lineSize;
this.code = code;
this.createPictureCode();
}
public PicAuthImg(int stringNum) {
this.stringNum = stringNum;
this.createPicture();
}
public PicAuthImg(int stringNum, boolean onlyNum) {
this.stringNum = stringNum;
this.onlyNum = onlyNum;
this.createPicture();
}
public PicAuthImg(int width, int height, int lineSize, int stringNum) {
this.width = width;
this.height = height;
this.lineSize = lineSize;
this.stringNum = stringNum;
this.createPicture();
}
public PicAuthImg(int width, int height, int lineSize, int stringNum,boolean onlyNum) {
this.width = width;
this.height = height;
this.lineSize = lineSize;
this.stringNum = stringNum;
this.onlyNum = onlyNum;
this.createPicture();
}
public String getCode() {
return code;
}
public void setOnlyNum(boolean onlyNum){
this.onlyNum=onlyNum;
}
private void createPicture(){
buffImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR);
//产生Image对象的Graphics对象,改对象可以在图像上进行各种绘制操作
Graphics g = buffImg.getGraphics();
//图片大小
g.fillRect(0, 0, width, height);
//字体大小
g.setFont(new Font("Times New Roman", Font.ROMAN_BASELINE, 18));
//字体颜色
g.setColor(getRandColor(110, 133));
// 绘制干扰线
for (int i = 0; i <= lineSize; i++) {
drowLine(g);
}
// 绘制随机字符
String verCode = "";
for (int i = 1; i <= stringNum; i++) {
verCode += drowString(g, i);
}
LOG.info("生成验证码[{}]",verCode);
code = verCode;
g.dispose();
}
private void createPictureCode(){
buffImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR);
//产生Image对象的Graphics对象,改对象可以在图像上进行各种绘制操作
Graphics g = buffImg.getGraphics();
//字体大小
g.setFont(new Font("Times New Roman", Font.ROMAN_BASELINE, 18));
//图片大小
g.fillRect(0, 0, width, height);
//字体颜色
g.setColor(getRandColor(110, 133));
// 绘制干扰线
for (int i = 0; i <= lineSize; i++) {
drowLine(g);
}
// 绘制随机字符
for (int i = 0; i < code.length(); i++) {
drowString(g, i+1,String.valueOf(code.charAt(i)));
}
LOG.info(code);
g.dispose();
}
public void write(HttpServletResponse response){
try {
// 将内存中的图片通过流动形式输出到客户端
ImageIO.write(buffImg, "JPEG", response.getOutputStream());
} catch (Exception e) {
LOG.error("将内存中的图片通过流动形式输出到客户端失败>>>> ", e);
}
}
public void write(HttpServletRequest request, HttpServletResponse response){
request.getSession().removeAttribute(SESSION_PARAM_PICCODE);
request.getSession().setAttribute(SESSION_PARAM_PICCODE,code);
try {
// 将内存中的图片通过流动形式输出到客户端
ImageIO.write(buffImg, "JPEG", response.getOutputStream());
} catch (Exception e) {
LOG.error("将内存中的图片通过流动形式输出到客户端失败>>>> ", e);
}
}
/**
* 获得字体
*/
private Font getFont() {
return new Font("Fixedsys", Font.CENTER_BASELINE, 18);
}
/**
* 获得颜色
*/
private Color getRandColor(int fc, int bc) {
if (fc > 255) {
fc = 255;
}
if (bc > 255) {
bc = 255;
}
int r = fc + random.nextInt(bc - fc - 16);
int g = fc + random.nextInt(bc - fc - 14);
int b = fc + random.nextInt(bc - fc - 18);
return new Color(r, g, b);
}
/**
* 绘制干扰线
*/
private void drowLine(Graphics g) {
int x = random.nextInt(width);
int y = random.nextInt(height);
int xl = random.nextInt(13);
int yl = random.nextInt(15);
g.drawLine(x, y, x + xl, y + yl);
}
/**
* 绘制字符串
*/
private String drowString(Graphics g, int i) {
g.setFont(getFont());
g.setColor(new Color(random.nextInt(101), random.nextInt(111), random
.nextInt(121)));
String rand = String.valueOf(getRandomString());
g.translate(random.nextInt(3), random.nextInt(3));
g.drawString(rand, 13 * i, 16);
return rand;
}
/**
* 绘制字符串
*/
private void drowString(Graphics g, int i, String str) {
g.setFont(getFont());
g.setColor(new Color(random.nextInt(101), random.nextInt(111), random
.nextInt(121)));
g.translate(random.nextInt(3), random.nextInt(3));
g.drawString(str, 13 * i, 16);
}
/**
* 获取随机的字符
*/
public String getRandomString() {
if (onlyNum){
return String.valueOf(randNum.charAt(random.nextInt(randNum.length())));
}
return String.valueOf(randStr.charAt(random.nextInt(randStr.length())));
}
public void write(String path) throws IOException {
OutputStream sos = new FileOutputStream(path);
this.write(sos);
}
public void write(OutputStream sos) throws IOException {
// ImageIO.write(buffImg, "png", sos);
ImageIO.write(buffImg, "jpeg", sos);
sos.close();
}
public static void main(String[] args) {
PicAuthImg pai = new PicAuthImg(5,true);
String path="D:/"+new Date().getTime()+".png";
System.out.println(pai.getCode()+" >"+path);
try {
pai.write(path);
} catch (IOException e) {
e.printStackTrace();
}
}
}