package com.deroser.mybatisplustest.mybatisplustest.service.impl;
import com.deroser.mybatisplustest.mybatisplustest.service.PicService;
import com.google.common.collect.Maps;
import org.springframework.stereotype.Service;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.security.SecureRandom;
import java.util.Map;
@Service("picService")
public class PicServiceImpl implements PicService {
//定义图片的高度
private static final int WIDTH = 90;
//定义图片的宽度
private static final int HEIGHT = 25;
//定义图片显示验证码的个数
private static final int CODE_COUNT = 4;
//字体高度
private static final int FONT_HEIGHT = 18;
//图片字母组成
private static final char[] CODE_SEQUENCE = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M',
'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '2', '3', '4', '5', '6', '7', '8', '9',};
//干扰线数量
private static final int LINE_NUMBER = 2;
private static final String FONT_NAME = "Times New Romans";
//偏移量
private static final int ANCHORY = 10;
//干扰线最大长度
private static final int LINE_LENGTH_BOUND = 12;
//噪点密度
private static final float YAMP_RATE = 0.01f;
//噪点圆心半径限度
private static final int OVAR_BOUND = 6;
/**
* 生成一个map集合
* code 为生成的验证码
* codePic 为生成的验证码BufferdImage对象
*/
public Map<String, Object> generateCodeAndPic() {
// 1,定义图像buffer
BufferedImage bufferedImage = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
Graphics2D graphics = bufferedImage.createGraphics();
// 2,创建一个随机数生成类
SecureRandom random = new SecureRandom();
// 3,将图像填充为白色
graphics.setColor(createRandomColor(220, 250, random));
// 4,设置形状宽高
graphics.fillRect(0, 0, WIDTH, HEIGHT);
// 5,创建字体,字体的大小根据图片的高度来定
Font font = new Font(FONT_NAME, Font.BOLD, FONT_HEIGHT);
// 6,设置字体
graphics.setFont(font);
// 7,画边框
graphics.setColor(Color.getHSBColor(234, 234, 234));
graphics.drawRect(0, 0, WIDTH - 1, HEIGHT - 1);
// 8,随机产生干扰线
createRandomLine(graphics, random, LINE_NUMBER);
// 9,随机产生噪点
createRandomPoints(graphics,random);
// 10,随机产生字符
StringBuffer randomCode = createRandomChars(graphics, random);
// 11,释放图形上下文
graphics.dispose();
Map<String,Object>map = Maps.newConcurrentMap();
// 12,存放验证码
map.put("code",randomCode);
// 13,存放生成的验证码BufferedImage图像
map.put("codePic",bufferedImage);
return map;
}
private static StringBuffer createRandomChars(Graphics2D graphics, SecureRandom random) {
//randomCode 用于保存随机产生的验证码,以便用户登录后进行验证
StringBuffer randomCode = new StringBuffer();
//随机产生codeCount数字验证码
for (int i = 0; i < CODE_COUNT; i++) {
//1,得到随机产生的验证码数字
String code = String.valueOf(CODE_SEQUENCE[random.nextInt(CODE_SEQUENCE.length)]);
//2,设置字符颜色
graphics.setColor(new Color(50+random.nextInt(100),50+random.nextInt(100),50+random.nextInt(100)));
//3,图片旋转
AffineTransform affine = new AffineTransform();
affine.setToRotation(Math.PI/9*(random.nextBoolean()?1:-1),22.5*i,12);
graphics.setTransform(affine);
//4,画字符
graphics.drawString(code,(WIDTH/CODE_COUNT)*i+5,HEIGHT-5);
//5,将产生的四个随机数组合在一起
randomCode.append(code);
}
return randomCode;
}
private static void createRandomPoints(Graphics2D graphics, SecureRandom random) {
//噪点颜色设置为绿色
graphics.setColor(Color.green);
//计算噪点数量
int area = (int) (YAMP_RATE * WIDTH * HEIGHT);
//打印噪点
for (int i = 0; i < area; i++) {
int x = random.nextInt(WIDTH);//圆心坐标x
int y = random.nextInt(HEIGHT);//圆心坐标y
graphics.drawOval(x,y,random.nextInt(OVAR_BOUND),random.nextInt(OVAR_BOUND));//画圈
}
}
private static void createRandomLine(Graphics2D graphics, SecureRandom random, int lineNumber) {
//设置干扰线颜色
graphics.setColor(Color.BLACK);
for (int i = 0; i < lineNumber; i++) {
int x = random.nextInt(WIDTH);
int y = random.nextInt(HEIGHT);
int x1 = random.nextInt(LINE_LENGTH_BOUND);
int y1 = random.nextInt(LINE_LENGTH_BOUND);
graphics.drawLine(x, y, x + x1, y + y1);
}
}
private static Color createRandomColor(int fc, int bc, SecureRandom random) {
int f = fc;
int b = bc;
if (f > 255) {
f = 255;
}
if (f < 1) {
f = 1;
}
if (b > 255) {
b = 255;
}
if (b < 1) {
b = 1;
}
return new Color(f + random.nextInt(b - f), f + random.nextInt(b - f), f + random.nextInt(b - f));
}
}
package com.deroser.mybatisplustest.mybatisplustest.controller;
import com.deroser.mybatisplustest.mybatisplustest.service.PicService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.RenderedImage;
import java.io.IOException;
import java.util.Map;
@RestController
@RequestMapping(value = "/pic")
public class PicController {
@Autowired
private PicService picService;
@RequestMapping(value = "/verification")
public void getVerification(HttpServletRequest request, HttpServletResponse response){
Map<String, Object> map = picService.generateCodeAndPic();
try{
ImageIO.write((RenderedImage) map.get("codePic"),"jpeg",response.getOutputStream());
}catch (IOException e){
e.printStackTrace();
}
}
}
效果如下图所示