直接上图,验证码可以设置字符个数,字符颜色,背景颜色,旋转角度,新的字体。
请注意加载新字体那一块代码,一定要注册一下,不然带不出文字。
自己看代码吧。。。
package com.ukWord.servlet;
import com.ukWord.util.AppConst;
import org.apache.commons.lang3.StringUtils;
import sun.font.FontDesignMetrics;
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;
import java.util.Random;
public class SecurityCodeServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private int width = 173;
private int height = 24;
private int fontSize = height;
private int securityCodeLength = 4;
private int interferingLineCount = 20;
private Font font = new Font("Times New Romans", Font.BOLD, fontSize);
private String charStr = "A0KLBMNC2PD3QRE4STF5UVG6WXH7YZ8J9秋花惨淡秋草黄耿耿秋灯秋夜长已觉秋窗秋不尽那堪风雨助凄凉";
private String[] chars;
private int charWidth;
private int charHeight;
@Override
public void init() throws ServletException {
try{
Properties config = new Properties();
config.load(SecurityCodeServlet.class.getResourceAsStream("/config.properties"));
String withStr = config.getProperty("security.code.width");
if(StringUtils.isNotEmpty(withStr)){
this.width = Integer.parseInt(withStr);
}
String securityCodeLengthStr = config.getProperty("security.code.length");
if(StringUtils.isNotEmpty(securityCodeLengthStr)){
this.securityCodeLength = Integer.parseInt(securityCodeLengthStr);
}
String interferingLineCountStr = config.getProperty("security.code.interfering.line.count");
if(StringUtils.isNotEmpty(interferingLineCountStr)){
this.interferingLineCount = Integer.parseInt(interferingLineCountStr);
}
String fontStr = config.getProperty("security.code.fontStyle");
if(StringUtils.isNotEmpty(fontStr)){
if(!StringUtils.contains(fontStr, ".ttf")){
this.font = new Font(fontStr, Font.BOLD, fontSize);
}else{
this.font = registerFont(fontStr);
}
}
String charsStr = config.getProperty("security.code.text");
if(StringUtils.isNotEmpty(charsStr)){
this.charStr = charsStr;
}
this.chars = new String[charsStr.length()];
for(int i = 0; i < charsStr.length(); i++){
this.chars[i] = String.valueOf(charsStr.charAt(i));
}
FontMetrics fontMetrics = FontDesignMetrics.getMetrics(this.font);
this.charWidth = fontMetrics.stringWidth("M");
this.charHeight = fontMetrics.getHeight();
}catch(Exception e){
e.printStackTrace();
}
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
Random random = new Random();
BufferedImage buffImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics2D g = buffImg.createGraphics();
g.setFont(this.font);
//画背景
g.setColor(this.getRandomColor(random, 200, 55));
g.fillRect(0, 0, width, height);
//画边框
g.setColor(this.getRandomColor(random, 100, 155));
g.drawRect(0, 0, width-1, height-1);
//画干扰线
g.setColor(this.getRandomColor(random, 0, 255));
g.setStroke(new BasicStroke(1f));
for (int i = 0; i < this.interferingLineCount; i++) {
int x = random.nextInt(this.width);
int y = random.nextInt(this.height);
int xl = random.nextInt(this.width);
int yl = random.nextInt(this.height);
g.drawLine(x, y, x + xl, y + yl);
}
//画旋转文字
int charX = 0;
List<String> chartList = this.getRandomString(random);
int charsRealWidth = this.charWidth * this.securityCodeLength;
if(this.width > charsRealWidth){
charX = (this.width - charsRealWidth)/2;
}
double radianPercent = 0D;
int chartY = this.height - 5;
for(String chart : chartList){
g.setColor(this.getRandomColor(random, 80, 120));
radianPercent = Math.PI * (random.nextInt(60)/180D);
if(random.nextBoolean()) radianPercent = -radianPercent;
g.rotate(radianPercent, charX + 9, chartY);
g.drawString(chart, charX, chartY);
g.rotate(-radianPercent, charX + 9, chartY);
charX += this.charWidth;
}
//释放此图形的上下文以及它使用的所有系统资源
g.dispose();
//设置response类型
response.setContentType("image/jpeg");
//取消缓存
response.setHeader("Pragma", "no-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);
//输出图像
ServletOutputStream os = response.getOutputStream();
ImageIO.write(buffImg, "jpeg", os);
os.close();
//设置Session,将字符串转换成小写
request.getSession().setAttribute(AppConst.SECURITY_CODE_SESSION_KEY, StringUtils.join(chartList, "").toLowerCase());
}catch (Exception e) {
e.printStackTrace();
}
}
private Font registerFont(String fontStr) throws Exception {
InputStream fontInputStream = SecurityCodeServlet.class.getClassLoader().getResourceAsStream(fontStr);
Font fontNew = Font.createFont(Font.TRUETYPE_FONT, fontInputStream);
Font fontNewPt = fontNew.deriveFont(Font.BOLD, this.fontSize);
fontInputStream.close();
//注意这里,如果不注册文字的话,什么都画不出来
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
ge.registerFont(fontNew);
return fontNewPt;
}
private List<String> getRandomString(Random random){
List<String> chartList = new LinkedList<String>();
for(int i = 0; i < this.securityCodeLength; i++){
String character = this.chars[random.nextInt(this.chars.length)];
character = (random.nextBoolean() == true ? character.toUpperCase() : character.toLowerCase());
chartList.add(character);
}
return chartList;
}
private Color getRandomColor(Random random, int start, int max){
int r = start + random.nextInt(max);
int g = start + random.nextInt(max);
int b = start + random.nextInt(max);
return new Color(r, g, b);
}
}