新版本jdk 和 旧版本jdk验证码生成问题

原创
2016/10/08 13:38
阅读数 189

比较传统的java验证码生成方法是:

import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;

JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(response.getOutputStream());
encoder.encode(image);


现在公司项目要更新jdk 到1.7,这个方法就不能用了,jdk 7 吧sun 下的这个包给丢掉了,如果使用oracle 1.637 以后的jdk 1.6或者用jdk 1.7.x你会发现JPEGCodec,JPEGImageEncoder 就无法导入了

其实在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("/home/opt/cache"); //手动指定的缓存目录
ImageIO.write(image, "JPEG", response.getOutputStream());// 将内存中的图片通过流动形式输

3.把删掉的tomcat缓存目录加上

下面贴一个我写的验证码例子:

前台登录:

<form action="${ctx}/submit" method="post" class="login2" onsubmit="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" onclick="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>

js 验证码调用:

function reloadImage(){
$("#randImageId").attr("src","${ctx}/verify?jasper="+new Date().getTime());
}


后台接收验证码请求:

@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();
}
}


处理验证码生成:

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);
}

}

登录和验证

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;
}

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部