java数字和中文算数验证码的实现

网友投稿 285 2022-12-01


java数字和中文算数验证码的实现

本文介绍了java数字和中文算数验证码的实现,分享给大家,具体如下:

效果图

本文代码 https://gitee.com/tothis/java-record/tree/master/src/main/java/com/example/captcha

中文实现参考 https://gitee.com/whvse/EasyCaptcha.git

数字实现参考 https://jb51.net/article/190561.htm

代码如下

中文算法

package com.example.captcha;

import lombok.extern.slf4j.Slf4j;

import java.awt.*;

import java.awt.image.BufferedImage;

import java.util.HashMap;

import java.util.Map;

import java.util.Random;

/**

* @author 李磊

* @datetime 2020/7/9 20:10

* @description

*/

@Slf4j

public class ChineseCaptcha {

// 宽度

private static final int IMAGE_WIDTH = 160;

// 高度

private static final int IMAGE_HEIGHT = 40;

// 字体大小

private static final int FONT_SIZE = 28;

// 干扰线数量

private static final int IMAGE_DISTURB_LINE_NUMBER = 15;

// 后缀

private static final String SUFFIX = "等于?";

// 汉字数字

private static final String SOURCE = "零一二三四五六七八九十乘除加减";

// 计算类型

private static final Map calcType = new HashMap<>();

private static final Random RANDOM = new Random();

static {

// 对应SOURCE下标

calcType.put("*", 11);

calcType.put("/", 12);

calcType.put("+", 13);

calcType.put("-", 14);

}

// 计算公式

private String content;

// 计算结果

private int result;

/**

* 生成图像验证码

*/

public BufferedImage create() {

createMathChar();

BufferedImage image = new BufferedImage(IMAGE_WIDTH, IMAGE_HEIGHT, BufferedImage.TYPE_INT_RGB);

Graphics g = image.getGraphics();

// 字体颜色

g.setColor(Color.WHITE);

// 背景颜色

g.fillRect(0, 0, IMAGE_WIDTH, IMAGE_HEIGHT);

g.setColor(color());

// 图片边框

g.drawRect(0, 0, IMAGE_WIDTH - 1, IMAGE_HEIGHT - 1);

g.setColor(color());

for (int i = 0; i < IMAGE_DISTURB_LINE_NUMBER; i++) {

// 绘制干扰线

int x1 = RANDOM.nextInt(IMAGE_WIDTH);

int y1 = RANDOM.nextInt(IMAGE_HEIGHT);

int x2 = RANDOM.nextInt(13);

int y2 = RANDOM.nextInt(15);

g.drawLine(x1, y1, x1 + x2, y1 + y2);

}

StringBuilder builder = new StringBuilder();

for (int i = 0, j = content.length(); i < j; i++) {

int index;

if (i == 1) {

index = calcType.get(String.valueOf(content.charAt(i)));

} else {

index = Integer.parseInt(String.valueOf(content.charAt(i)));

}

String ch = String.valueOf(SOURCE.charAt(index));

builder.append(ch);

drawString((Graphics2D) g, ch, i);

}

drawString((Graphics2D) g, SUFFIX, 3);

content = builder.append(SUFFIX).toString();

g.dispose();

return image;

}

private void createMathChar() {

StringBuilder number = new StringBuilder();

// 10以内数字

int xx = RANDOM.nextInt(10);

int yy = RANDOM.nextInt(10);

// 0~3 对应加减乘除

int round = (int) Math.round(Math.random() * 3);

if (round == 0) {

this.result = yy + xx;

number.append(yy);

number.append("+");

number.append(xx);

} else if (round == 1) {

this.result = yy - xx;

number.append(yy);

number.append("-");

number.append(xx);

} else if (round == 2) {

this.result = yy * xx;

number.append(yy);

number.append("*");

number.append(xx);

} else {

// 0不可为被除数 yy对xx取余无余数

if (!(xx == 0) && yy % xx == 0) {

this.result = yy / xx;

number.append(yy);

number.append("/");

number.append(xx);

} else {

this.result = yy + xx;

number.append(yy);

number.append("+");

number.append(xx);

}

}

this.content = number.toString();

log.info("数字计算公式 {}", this.content);

}

private void drawString(Graphics2D g2d, String s, int i) {

g2d.setFont(new Font("黑体", Font.BOLD, FONT_SIZE));

int r = RANDOM.nextInt(255);

int g = RANDOM.nextInt(255);

int b = RANDOM.nextInt(255);

g2d.setColor(new Color(r, g, b));

int x = RANDOM.nextInt(3);

int y = RANDOM.nextInt(2);

g2d.translate(x, y);

int angle = new Random().nextInt() % 15;

g2d.rotate(angle * Math.PI / 180, 5 + i * 25, 20);

g2d.drawString(s, 5 + i * 25, 30);

g2d.rotate(-angle * Math.PI / 180, 5 + i * 25, 20);

}

// 获取随机颜色

private Color color() {

int r = RANDOM.nextInt(256);

int g = RANDOM.nextInt(256);

int b = RANDOM.nextInt(256);

return new Color(r, g, b);

}

public String content() {

return content;

}

public int result() {

return result;

}

}

数字算法

此代码使用了ttf字体 字体在此处 https://gitee.com/tothis/java-record/tree/master/src/main/resources/font

package com.example.captcha;

import lombok.SneakyThrows;

import java.awt.*;

import java.awt.image.BufferedImage;

import java.util.Random;

/**

* @author 李磊

* @datetime 2020/7/9 20:16

* @description

*/

public class NumberCaptcha {

// 宽度

private static final int IMAGE_WIDTH = 160;

// 高度

private static final int IMAGE_HEIGHT = 40;

// 字体大小

private static final int FONT_SIZE = 28;

// 字体目录

private static final String FONT_PATH = "/font/";

// 字体列表

private static final String[] FONT_NAMES = {

"actionj.ttf", "epilog.ttf", "headache.ttf"

, "lexo.ttf", "prefix.ttf", "robot.ttf"

};

private static final Random RANDOM = new Random();

// 计算公式

private String content;

// 计算结果

private int result;

/**

* 生成随机验证码

*/

private void createMathChar() {

StringBuilder number = new StringBuilder();

int xx = RANDOM.nextInt(10);

int yy = RANDOM.nextInt(10);

// 0~3 对应加减乘除

int round = (int) Math.round(Math.random() * 3);

if (round == 0) {

this.result = yy + xx;

number.append(yy);

number.append("+");

number.append(xx);

} else if (round == 1) {

this.result = yy - xx;

number.append(yy);

number.append("-");

number.append(xx);

} else if (round == 2) {

this.result = yy * xx;

number.append(yy);

number.append("x");

number.append(xx);

} else {

// 0不可为被除数 yy对xx取余无余数

if (!(xx == 0) && yy % xx == 0) {

this.result = yy / xx;

number.append(yy);

number.append("/");

number.append(xx);

} else {

this.result = yy + xx;

number.append(yy);

number.append("+");

number.append(xx);

}

}

content = number.append("=?").toString();

}

// 获取随机颜色

private Color color() {

int r = RANDOM.nextInt(256);

int g = RANDOM.nextInt(256);

int b = RANDOM.nextInt(256);

return new Color(r, g, b);

}

/**

* 随机画干扰圆

*

* @param num 数量

* @param g Graphics2D

*/

private void drawOval(int num, Graphics2D g) {

for (int i = 0; i < num; i++) {

g.setColor(color());

int j = 5 + RANDOM.nextInt(10);

g.drawOval(RANDOM.nextInt(IMAGE_WIDTH - 25), RANDOM.nextInt(IMAGE_HEIGHT - 15), j, j);

}

}

@SneakyThrows

private Font font() {

int index = RANDOM.nextInt(FONT_NAMES.length);

Font font = Font.createFont(Font.TRUETYPE_FONT

, getClass().getResourceAsStream(FONT_PATH + FONT_NAMES[index]))

.deriveFont(Font.BOLD, FONT_SIZE);

return font;

}

/**

* 生成验证码图形

*/

public BufferedImage create() {

createMathChar();

char[] chars = content.toCharArray();

BufferedImage image = new BufferedImage(IMAGE_WIDTH, IMAGE_HEIGHT, BufferedImage.TYPE_INT_RGB);

Graphics2D g2d = (Graphics2D) image.getGraphics();

// 填充背景

g2d.setColor(Color.WHITE);

g2d.fillRect(0, 0, IMAGE_WIDTH, IMAGE_HEIGHT);

// 抗锯齿

g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALhBcYWuJuLJUE_ANTIALIAS_ON);

// 画干扰圆

drawOval(2, g2d);

// 画字符串

g2d.setFont(font());

FontMetrics fontMetrics = g2d.getFontMetrics();

// 每一个字符所占的宽度

int fx = IMAGE_WIDTH / chars.length;

// 字符左填充

int flp = 10;

for (int i = 0; i < chars.length; i++) {

String item = String.valueOf(chars[i]);

g2d.setColor(color());

// 文字的纵坐标

int fy = IMAGE_HEIGHT - ((IMAGE_HEIGHT - (int) fontMetrics

.getStringBounds(item, g2d).getHeight()) >> 1);

g2d.drawString(item, flp + i * fx + 3, fy - 3);

}

g2d.dispose();

return image;

}

public String content() {

return content;

}

public int result() {

return result;

}

}

测试类

package com.example.captcha;

import com.greenpineyu.fel.FelEngine;

import com.greenpineyu.fel.FelEhttp://ngineImpl;

import lombok.SneakyThrows;

import javax.imageio.ImageIO;

import java.awt.image.BufferedImage;

import java.io.File;

/**

* @author 李磊

* @datetime 2020/7/9 20:10

* @description

*/

public class Main {

@SneakyThrows

public static void main(String[] args) {

// 图片类型

String IMAGE_TYPE = "png";

ChineseCaptcha chinese = new ChineseCaptcha();

NumberCaptcha number = new NumberCaptcha();

for (int i = 0; i < 10; i++) {

BufferedImage image1 = chinese.create();

// 输出文件

ImageIO.write(image1, IMAGE_TYPE, new File("D:/data/a" + i + ".png"));

System.out.println(chinese.content() + ' ' + chinese.result());

BufferedImage image2 = number.create();

// 输出文件

ImageIO.write(image2, IMAGE_TYPE, new File("D:/data/b" + i + ".png"));

System.out.println(number.content() + ' ' + number.result());

}

}

}

如需要多级运算如1+2-3*4/5 则需要使用表达式引擎计算 如下为使用fel计算表达式

// fel计算表达式

FelEngine fel = new FelEngineImpl();

System.out.println(3 * 2 + 1);

System.out.println(fel.eval("3*2+1"));

System.out.println(3 * (2 + 1));

System.out.println(fel.eval("3*(2+1)"));


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Java实现中文算数验证码的实现示例(算数运算+
下一篇:详解springboot+mybatis
相关文章

 发表评论

暂时没有评论,来抢沙发吧~