- 验证码工具类:
1
packagecom.newcapec.utils;
2
3
importcom.sun.image.codec.jpeg.JPEGCodec;
4
importcom.sun.image.codec.jpeg.JPEGImageEncoder;
5
6
importjava.awt.*;
7
importjava.awt.image.BufferedImage;
8
importjava.io.FileOutputStream;
9
importjava.io.IOException;
10
importjava.io.OutputStream;
11
importjava.util.Random;
12
13
/**
14
* <p>Title: ValidateCode.java</p>
15
* <p>Description: 验证码工具类</p>
16
*/
17
publicclassValidateCode {
18
// 图片的宽度。
19
privateintwidth=120;
20
// 图片的高度。
21
privateintheight=40;
22
// 验证码字符个数
23
privateintcodeCount=4;
24
// 验证码干扰线数
25
privateintlineCount=30;
26
// 验证码
27
privateStringcode=null;
28
// 验证码图片Buffer
29
privateBufferedImagebuffImg=null;
30
31
privatechar[] codeSequence= { 'A','a', 'B','b', 'C','c', 'D','d', 'E','e', 'F','f', 'g','H','h',
32
'J','j', 'K','k','L', 'M','m', 'N','n', 'P','p', 'Q','q', 'R','r', 'S','s', 'T', 'U','u', 'V', 'W','w',
33
'X','x', 'Y', 'Z', '2', '3', '4', '5', '6', '7', '8', '9'};
34
35
// 生成随机数
36
privateRandomrandom=newRandom();
37
38
publicValidateCode() {
39
this.createCode();
40
}
41
42
/**
43
*
44
* @param width
45
* 图片宽
46
* @param height
47
* 图片高
48
*/
49
publicValidateCode(intwidth, intheight) {
50
this.width=width;
51
this.height=height;
52
this.createCode();
53
}
54
55
/**
56
*
57
* @param width
58
* 图片宽
59
* @param height
60
* 图片高
61
* @param codeCount
62
* 字符个数
63
* @param lineCount
64
* 干扰线条数
65
*/
66
publicValidateCode(intwidth, intheight, intcodeCount, intlineCount) {
67
this.width=width;
68
this.height=height;
69
this.codeCount=codeCount;
70
this.lineCount=lineCount;
71
this.createCode();
72
}
73
74
publicvoidcreateCode() {
75
RandomheightRandom=newRandom();
76
intcodeX=0;
77
intfontHeight=0;
78
fontHeight=height-heightRandom.nextInt(7)-7;// 字体的高度
79
codeX=width/ (codeCount+1);// 每个字符的宽度
80
81
// 图像buffer
82
buffImg=newBufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
83
Graphics2Dg=buffImg.createGraphics();
84
85
// 将图像填充为白色
86
g.setColor(Color.WHITE);
87
g.fillRect(0, 0, width, height);
88
89
// 创建字体
90
ImgFontByteimgFont=newImgFontByte();
91
Fontfont=imgFont.getFont(fontHeight);
92
g.setFont(font);
93
94
// 绘制干扰线
95
for (inti=0; i<lineCount; i++) {
96
intxs=getRandomNumber(width);
97
intys=getRandomNumber(height);
98
intxe=xs+getRandomNumber(width/8);
99
intye=ys+getRandomNumber(height/8);
100
g.setColor(getRandomColor());
101
g.drawLine(xs, ys, xe, ye);
102
}
103
104
105
StringBufferrandomCode=newStringBuffer();
106
107
// int x = 5;
108
// 随机产生验证码字符
109
for (inti=0; i<codeCount; i++) {
110
inth=height-8;
111
intw= (i+1) *codeX+heightRandom.nextInt(4);
112
StringstrRand=String.valueOf(codeSequence[random
113
.nextInt(codeSequence.length)]);
114
// 设置字体颜色
115
g.setColor(getRandomColor());
116
117
intdegree=newRandom().nextInt() %10;
118
g.rotate(degree*Math.PI/180,(w+codeX-5)/2, (h+fontHeight)/2);
119
// 设置字体位置
120
g.drawString(strRand, w, h ); //getRandomNumber(height / 2) + 25
121
g.rotate(-degree*Math.PI/150, (w+codeX-5)/2, (h+fontHeight)/2);
122
randomCode.append(strRand);
123
}
124
code=randomCode.toString();
125
}
126
127
/** 获取随机颜色 */
128
privateColorgetRandomColor() {
129
intr=getRandomNumber(225);
130
intg=getRandomNumber(225);
131
intb=getRandomNumber(225);
132
returnnewColor(r, g, b);
133
}
134
135
/** 获取随机数 */
136
privateintgetRandomNumber(intnumber) {
137
returnrandom.nextInt(number);
138
}
139
140
publicvoidwrite(Stringpath) throwsIOException {
141
OutputStreamsos=newFileOutputStream(path);
142
this.write(sos);
143
}
144
145
publicvoidwrite(OutputStreamsos) throwsIOException {
146
// ImageIO.write(buffImg, "png", sos);
147
JPEGImageEncoderencoder=JPEGCodec.createJPEGEncoder(sos);
148
encoder.encode(buffImg);
149
sos.close();
150
}
151
152
publicBufferedImagegetBuffImg() {
153
returnbuffImg;
154
}
155
156
publicStringgetCode() {
157
returncode;
158
}
159
160
/** 字体样式类 */
161
classImgFontByte {
162
publicFontgetFont(intfontHeight) {
163
returnnewFont("Arial", Font.PLAIN, fontHeight);
164
}
165
}
166
167
168
}
169
- 使用
1
publicvoidscaptcha(){
2
HttpServletResponseresponse=ServletActionContext.getResponse();
3
response.reset();
4
// 设置响应的类型格式为图片格式
5
response.setContentType("image/jpeg");
6
// 禁止图像缓存。
7
response.setHeader("Pragma", "no-cache");
8
response.setHeader("Cache-Control", "no-cache");
9
response.setDateHeader("Expires", 0);
10
ValidateCodeinstance=newValidateCode();
11
CookieUtil.setCookie(response, "scaptcha", instance.getCode().toUpperCase(), null, -1);
12
try {
13
instance.write(response.getOutputStream());
14
} catch (IOExceptione) {
15
e.printStackTrace();
16
}
17
}
在使用ImageIO.write时,发现在Linux平台上,会出现异常:
1
javax.imageio.IIOException: Can't create output stream
1
检查tomcat的日志,终于真相大白:
2
3
javax.imageio.IIOException: Can't create output stream!
4
5
atjavax.imageio.ImageIO.write(ImageIO.java:1521)
6
7
Causedby: javax.imageio.IIOException: Can't create cache file!
8
9
atjavax.imageio.ImageIO.createImageOutputStream(ImageIO.java:395)
10
11
atjavax.imageio.ImageIO.write(ImageIO.java:1519)
12
13
... 34more
14
Causedby: java.io.IOException: 系统找不到指定的路径。
15
16
原来是ImageIO.write(image, "jpeg", response.getOutputStream());
查看日志,发现是由找不到文件引起
1
Java.nio.file.NoSuchFileException: xxx.../temp/imageio4138671232726624650.tmp
- 主要原因如下:
在使用ImageIO进行图片写操作时,默认会使用缓存目录:${tomcat}/temp,在此缓存目录会生成缓存文件imageio4138671232726624650.tmp(这一串数字应该是当前时间戳,临时文件名),有些生产环境的tomcat,会将temp目录删除,因此报错
- 4种解决方法如下:
- 在tomcat下新建temp目录;
- 与方法1相似,通过ImageIO.setCacheDirectory(cacheDirectory);设置任意的、存在的缓存目录
- ImageIO默认是使用缓存目录,可以通过ImageIO.setUseCache(false)来设置,更改缓存策略,不使用文件目录缓存,使用内存缓存
- 不使用ImageIO,换成其它JDK方法
1
ImageIO.write(bi, "jpg", baos);
2
换成:
3
JPEGImageEncoderencoder=JPEGCodec.createJPEGEncoder(response.getOutputStream());
4
encoder.encode(image);