生成验证码图片主要通过Java AWT中的Graphics对象画图操作,实际操作中,Controller接口可以接收前端随机参数,并保存该参数和生成的验证码的缓存关系,当提交表单时,用于校验表单中的随机码和验证码。
下面通过单元测试简单调试验证码图片的生成。
package com.study.demo.util;
import org.junit.Test;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class CaptchaCodeUtilTest {
private Random random = new Random();
private int width = 160;
private int height = 80;
@Test
public void draw(){
// 获取图片验证码,可以保存至缓存中
drawCaptchaCode(getRandomStr());
}
private void drawCaptchaCode(String captchaCode){
// BufferedImage是Image的一个子类,Image和BufferedImage的主要作用就是将一副图片加载到内存中。
BufferedImage buffImg = new BufferedImage(width,height, BufferedImage.TYPE_INT_RGB);
// Graphics类是所有图形上下文的抽象基类,允许应用程序绘制在各种设备上实现的组件,以及屏幕上的图像
Graphics graphics = buffImg.getGraphics();
// 设置背景色(范围)
int bcb = 200, bce = 255;
graphics.setColor(getRandomColor(bcb, bce));
graphics.fillRect(0, 0, width, height);
// 设置干扰线
drawLine(graphics);
// 填充字符
drawString(graphics, captchaCode);
try {
// 输出到某个文件中
OutputStream os = new FileOutputStream(new File("F:/Test/code.png"));
ImageIO.write(buffImg, "png", os);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 填充字符串
*/
private void drawString(Graphics graphics, String captchaCode) {
char [] chars = captchaCode.toCharArray();
int x = 5;
for (char aChar : chars) {
int size = 40 + random.nextInt(30);
Font font = getRandomFont(size);
FontMetrics fm = sun.font.FontDesignMetrics.getMetrics(font);
int fontWidth = fm.charWidth('A');
graphics.setFont(getRandomFont(size));
graphics.setColor(getRandomColor(0, 200));
graphics.drawString(String.valueOf(aChar), x + 5, height - random.nextInt(15));
x += fontWidth;
}
}
/**
* 设置干扰线
* abstract void drawLine(int x1, int y1, int x2, int y2)
* 在该图形上下文的坐标系中的点 (x1, y1)和 (x2, y2)之间绘制一行,使用当前颜色
*/
private void drawLine(Graphics graphics) {
float [] lineWith = new float[]{1f,2f,3f,4f,5f};
for (int i = 0; i < 10; i ++) {
int y1 = 5 + random.nextInt(height - 10);
int y2 = 5 + random.nextInt(height - 10);
Graphics2D g2 = (Graphics2D)graphics;
// 设置线条粗细
g2.setStroke(new BasicStroke(lineWith[random.nextInt(lineWith.length)]));
g2.setColor(getRandomColor(1, 255));
g2.drawLine(0, y1, width, y2);
}
}
/**
* 获取随机颜色
* 范围:1 - 255
*/
private Color getRandomColor(int begin, int end){
int r = begin + random.nextInt(end - begin);
int g = begin + random.nextInt(end - begin);
int b = begin + random.nextInt(end - begin);
return new Color(r, b, g);
}
/**
* 获取随机字体
*/
private Font getRandomFont(int size) {
List<Font> fonts = new ArrayList<>();
fonts.add(new Font("Ravie", Font.PLAIN, size));
fonts.add(new Font("Fixedsys", Font.PLAIN, size));
fonts.add(new Font("Antique Olive Compact", Font.PLAIN, size));
fonts.add(new Font("Gill Sans Ultra Bold", Font.PLAIN, size));
fonts.add(new Font("Wide Latin", Font.PLAIN, size));
return fonts.get(random.nextInt(fonts.size()));
}
/**
* 得到随机字符
*/
private String getRandomStr() {
String charStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890";
String randomStr = "";
for (int i = 0; i < 4; i++) {
int index = random.nextInt(charStr.length());
randomStr = randomStr.concat(String.valueOf(charStr.charAt(index)));
}
return randomStr;
}
}
运行单元测试后,本地生成的图片如下: