好多人,用java输出验证码喜欢用
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(response.getOutputStream());
encoder.encode(image);
其实在oracle 收购sun 之后有了 import javax.imageio.ImageIO; 这个方法来替代原来的方法;不过如果直接用
ImageIO.write(image, "JPEG", response.getOutputStream());
一般情况下不会出现问题,但是有的时候你会发现会出现一个异常:
javax.imageio.IIOException: Can't create output stream!
at javax.imageio.ImageIO.write(ImageIO.java:1521)
这个问题出现的原因,是你吧tomcat (或者其他web容器)的缓存目录给删掉了,所以写图片文件的时候会发生IO读写错误,
解决的办法有:
1.
ImageIO.setUseCache(true); //不使用缓存
2.
ImageIO.setUseCache(true);
ImageIO.setCacheDirectory(CommonToolsUtil.checkFileDir(FileContents.CATCHPATH));
ImageIO.write(image, "JPEG", response.getOutputStream());// 将内存中的图片通过流动形式输
自己手动指定缓存目录
3.
就是把删掉的web容器的缓存目录加上。
附上一个我写的例子:
1.前台的登录:
<form action="${ctx}/submit" method="post" class="login2" οnsubmit="return submitFun(this);">
<div class="user">
<span class="tb">用户名:</span>
<input id="usernameId" name="username" type="text" class="username" maxlength="20" value="" />
</div>
<div class="user">
<span class="tb">密 码:</span>
<input id="passwordId" name="password" type="password" class="keyword" maxlength="20" value="" />
</div>
<div class="user">
<span class="tb">验证码:</span>
<input id="checkId" name="check" type="text" class="yz" maxlength="4" />
<img class="log" id="randImageId" οnclick="reloadImage()" style="width:80px;height:26px;" src="${ctx}/verify" />
</div>
<div class="clear"></div>
<div align="center">
<input name="" type="submit" class="J_Submit" id="J_SubmitStatic" value="登陆"/>
<input name="" type="reset" class="J_Reset" id="J_ResetStatic" value="重置"/>
</div>
</form>
2.js验证码调用:
function reloadImage(){
$("#randImageId").attr("src","${ctx}/verify?jasper="+new Date().getTime());
}
3.后台接受验证码请求:
@RequestMapping(value = "/verify")
public void verify(HttpServletRequest request, HttpServletResponse response) {
response.setContentType("image/jpeg");// 设置相应类型,告诉浏览器输出的内容为图片
response.setHeader("Pragma", "No-cache");// 设置响应头信息,告诉浏览器不要缓存此内容
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expire", 0);
ValidateCode randomValidateCode = new ValidateCode();
try {
randomValidateCode.getRandcode(request, response);// 输出图片方法
} catch (Exception e) {
e.printStackTrace();
}
}
4.处理和生成验证码:
package com.shcmct.jsshxx.common;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.Serializable;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import com.google.common.collect.Maps;
import com.shcmct.jsshxx.utils.CommonToolsUtil;
public class ValidateCode implements Serializable {
private static final long serialVersionUID = 1998838254579545736L;
public static final String RANDOMCODEKEY = "verify";
private Random random = new Random();
public static Map<String, String> validataMap = Maps.newHashMap(), valicodeMap = Maps.newHashMap();
static {
initValiData();
}
// 随机产生的字符串
/****
* 图片宽度,高度,干扰线大小,字符数量
*/
private int width = 80, height = 26, lineSize = 40;
/*
* 获得字体
*/
private Font getFont() {
return new Font("Fixedsys", Font.CENTER_BASELINE, 18);
}
/*
* 获得颜色
*/
private Color getRandColor(int fc, int bc) {
if (fc > 255) {
fc = 255;
}
if (bc > 255) {
bc = 255;
}
int r = fc + random.nextInt(bc - fc - 16), g = fc + random.nextInt(bc - fc - 14), b = fc + random.nextInt(bc - fc - 18);
return new Color(r, g, b);
}
/**
* 生成随机图片
*/
public void getRandcode(HttpServletRequest request, HttpServletResponse response) {
HttpSession session = request.getSession();
// BufferedImage类是具有缓冲区的Image类,Image类是用于描述图像信息的类
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR);
Graphics g = image.getGraphics();// 产生Image对象的Graphics对象,改对象可以在图像上进行各种绘制操作
g.fillRect(0, 0, width, height);
g.setFont(new Font("Times New Roman", Font.ROMAN_BASELINE, 18));
g.setColor(getRandColor(110, 133));
// 绘制干扰线
for (int i = 0; i <= lineSize; i++) {
drowLine(g);
}
// 绘制随机字符
String randomString = drowString(g);
session.removeAttribute(RANDOMCODEKEY);
session.setAttribute(RANDOMCODEKEY, randomString);
g.dispose();
try {
ImageIO.setUseCache(true);
ImageIO.setCacheDirectory(CommonToolsUtil.checkFileDir(FileContents.CATCHPATH));
ImageIO.write(image, "JPEG", response.getOutputStream());// 将内存中的图片通过流动形式输出到客户端
} catch (Exception e) {
e.printStackTrace();
}
}
private static void initValiData() {
validataMap.put("9+9=", "18");
validataMap.put("7*7=", "49");
validataMap.put("3*2=", "6");
validataMap.put("5+3=", "8");
validataMap.put("6*6=", "36");
validataMap.put("5+2=", "7");
validataMap.put("8+8=", "16");
validataMap.put("100+1=", "101");
validataMap.put("8-3=", "5");
validataMap.put("3-1=", "2");
validataMap.put("1*1=", "1");
validataMap.put("2+1=", "3");
Constents.validataMap.putAll(validataMap);
AtomicInteger atomicInteger = new AtomicInteger(0);
for (Map.Entry<String, String> tempMap : validataMap.entrySet()) {
if (null != tempMap) {
String valiCode = tempMap.getKey();
valicodeMap.put(atomicInteger.toString(), valiCode);
atomicInteger.addAndGet(1);
}
}
}
/*
* 绘制字符串
*/
private String drowString(Graphics g) {
String randomString = "";
g.setFont(getFont());
g.setColor(new Color(random.nextInt(101), random.nextInt(111), random.nextInt(121)));
int ramdom = random.nextInt(validataMap.size());
randomString = valicodeMap.get(ramdom + "");
g.translate(random.nextInt(3), random.nextInt(3));
g.drawString(randomString, 13 * 2, 16);
return randomString;
}
/*
* 绘制干扰线
*/
private void drowLine(Graphics g) {
int x = random.nextInt(width), y = random.nextInt(height), xl = random.nextInt(13), yl = random.nextInt(15);
g.drawLine(x, y, x + xl, y + yl);
}
}
5.登录和验证码验证:
String verify = (String) WebUtils.getSessionAttribute(request, "verify"), strcheck = StringUtils.trim(check), valiData = Constents.validataMap
.get(verify);
request.getSession().removeAttribute("verify");
if (!StringUtils.equalsIgnoreCase(strcheck, valiData)) {
result.put("status", 0);
result.put("msg", "输入的验证码不匹配");
return result;
}