基于java.awt 绘制 自定义图片算式验证码
一、创建绘制图片验证码的类
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.util.Random;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
public class VerifyCode {
// 计算结果
private int result;
public BufferedImage createImage() {
// 图片宽度
int width = 105;
// 图片高度
int height = 32;
// 创建BufferedImage对象
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics graphics = image.getGraphics();
// 设置背景颜色
graphics.setColor(new Color(0xCDDCDC));
graphics.fillRect(0, 0, width, height);
// 画边框
graphics.setColor(Color.black);
graphics.drawRect(0, 0, width - 1, height - 1);
// 随机做干扰线
Random random = new Random();
for (int i = 0; i < 15; i++) {
int x = random.nextInt(width);
int y = random.nextInt(height);
int xl = random.nextInt(12);
int yl = random.nextInt(12);
graphics.drawLine(x, y, x + xl, y + yl);
}
// 生成验证码表达式,如:1+2 / 2*3 / 4 - 2
String verifyCode = this.generateExpression();
// 开始画图
graphics.setColor(new Color(0, 88, 0));
graphics.setFont(new Font("Fixedsys", Font.BOLD, 24));
graphics.drawString(verifyCode + " = ?", 8, 24);
graphics.dispose();
// 计算表达式结果
result = this.calc(verifyCode);
// 返回图片对象
return image;
}
public int getResult() {
return result;
}
/**
* 计算表达式的值
*
* @param expression
* @return
* @see [类、类#方法、类#成员]
*/
private int calc(String expression) {
try {
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("JavaScript");
return (Integer) engine.eval(expression);
} catch (Exception e) {
return 0;
}
}
/**
* 生成验证码表达式:1+2
* @return
* @see [类、类#方法、类#成员]
*/
private String generateExpression() {
Random random = new Random();
// 随机获取操作数 0-9
int number = random.nextInt(10);
int number2 = random.nextInt(10);
//int number3 = random.nextInt(10);
char[] operators = new char[] { '+', '-', '*' };
// 随机拿出一个操作符
char operator1 = operators[random.nextInt(3)];// 0-2
//char operator2 = operators[random.nextInt(3)];
return "" + number +" "+ operator1 +" "+ number2 ;
}
public static void main(String[] args) {
VerifyCode verifyCode = new VerifyCode();
String exp = verifyCode.generateExpression();
System.out.println(exp + "=" + verifyCode.calc(exp));
}
运算算式生成部分,完全可以根据自己的需求来更改,注释中注释了3个数之间的加、减、乘运算,由于除运算结果比较复杂,可能有小数点的出现,所以不考虑在内。
二、创建一个接口,专门供给前端返回验证码图片
我们将这个Http接口定义在controller中,专门供前端发送请求获取。这里的重点在于:如何将图片进行输出、以及避免图片的缓存而导致验证码更换的不及时。
@RequestMapping("/code")
public void code(HttpServletRequest request,
HttpServletResponse response) throws IOException {
//创建验证码对象
VerifyCode vc = new VerifyCode();
//创建验证码图片
BufferedImage image = vc.createImage();
//设置Http响应头 禁止图像缓存
response.setHeader("Cache-Control","no-cache");
response.setHeader("Pragma", "no-cache");
response.setDateHeader("Expires", 0); //响应具体的过期时间
response.setContentType("image/jpeg");
//获取表达式结果存入session
request.getSession().setAttribute("vcode", vc.getResult());
//将图片写回出到前端
ImageIO.write(image, "JPEG", response.getOutputStream());
}
三、接收图片
由于是在html中,我们可以使用thymleaf模板引擎,直接发送http连接到接口,请求验证码图片。
<img th:src="@{/user/code}" />
input type="text" class="form-control" name="code"
id="code" placeholder="验证码">
上面< img >标签中直接使用模板引擎的语法,动态获取图片。
在模板引擎中,@{/} 表示根路径,也就是部署在Web服务器容器上的项目名称。而之后的user/code则表示,去到user路径下的code路径。这也就相当于,我们在controller中对路径进行拦截,代码:
@RequestMapping("/user")
public class UserController{
@RequestMapping("/code")
public void code(...){
....
}
}