实现注册码时候出现的错误
在建立SSM框架中,在控制类中建立了验证码控制类
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/captcha")
public class CaptchaController {
/**
* 验证码验证
* @param request
* @param response
* @return
*/
@RequestMapping("/checkCode")
public String CAPTCHA(HttpServletRequest request, HttpServletResponse response) {
String info = null;
/* 获取输入的值 */
String value1 = request.getParameter("name");
/* 获取图片的值 */
HttpSession session = request.getSession();
String value2 = (String) session.getAttribute("checkcode");
/* 对比两个值(字母不区分大小写) */
if (value2.equalsIgnoreCase(value1)) {
info = "验证码输入正确";
} else {
info = "验证码输入错误";
}
System.out.println(info);
request.setAttribute("info", info);
return "logintest";
}
/**
* 生成验证码
* @param request
* @param response
* @return
* @throws IOException
*/
@RequestMapping("/logCheck")
public String logcheck(HttpServletRequest request, HttpServletResponse response) throws IOException {
response.setContentType("image/jpeg");
HttpSession session = request.getSession();
int width = 100;
int height = 60;
// 设置浏览器不要缓存此图片
response.setHeader("Pragma", "No-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);
// 创建内存图像并获得图形上下文
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics g = image.getGraphics();
/*
* 产生随机验证码 定义验证码的字符表
*/
String chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char[] rands = new char[4];
for (int i = 0; i < 4; i++) {
int rand = (int) (Math.random() * 36);
rands[i] = chars.charAt(rand);
}
/*
* 产生图像 画背景
*/
g.setColor(new Color(0xDCDCDC));
g.fillRect(0, 0, width, height);
/*
* 随机产生120个干扰点
*/
for (int i = 0; i < 120; i++) {
int x = (int) (Math.random() * width);
int y = (int) (Math.random() * height);
int red = (int) (Math.random() * 255);
int green = (int) (Math.random() * 255);
int blue = (int) (Math.random() * 255);
g.setColor(new Color(red, green, blue));
g.drawOval(x, y, 1, 0);
}
g.setColor(Color.BLACK);
g.setFont(new Font(null, Font.ITALIC | Font.BOLD, 18));
// 在不同高度输出验证码的不同字符
g.drawString("" + rands[0], 21, 37);
g.drawString("" + rands[1], 36, 35);
g.drawString("" + rands[2], 51, 38);
g.drawString("" + rands[3], 66, 36);
g.dispose();
// 将图像传到客户端
ServletOutputStream sos = response.getOutputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
// ImageIO.write(image, "JPG", baos);
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(response.getOutputStream());
encoder.encode(image);
byte[] buffer = baos.toByteArray();
response.setContentLength(buffer.length);
sos.write(buffer);
baos.close();
sos.close();
session.setAttribute("checkcode", new String(rands));
return null;
// int vlength = 4;
// int weidt = 60;
// int height = 15;
// Object vl = request.getParameter("vl");
// Object w = request.getParameter("w");
// Object h = request.getParameter("h");
// //如果长度不为空
// if(vl != null) {
// vlength = Integer.parseInt(vl.toString());
// }
// if(w != null) {
// weidt = Integer.parseInt(w.toString());
// }
// if(h != null) {
// height = Integer.parseInt(h.toString());
// }
// CpachaUtil cpachaUtil = new CpachaUtil(vlength,weidt,height);
// String generatorVCode = cpachaUtil.generatorVCode();
// request.getSession().setAttribute("loginCpacha", generatorVCode);
// BufferedImage generatorRotateVCodeImage = cpachaUtil.generatorRotateVCodeImage(generatorVCode, true);
// try {
// ServletOutputStream outputStream = response.getOutputStream();
// ImageIO.write(generatorRotateVCodeImage, "gif", outputStream);
// } catch (IOException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
// System.out.println("generatorVCode");
// return generatorVCode;
}
}
在网页上的实现代码如下
<div class="form-group col-5">
<input type="text" class="form-control" id="code" name="code" placeholder="验证码">
</div>
<div class="form-group col-3" style="padding: 0px;">
< img src="${pageContext.request.contextPath}/captcha/logCheck" id="vimg" style="height: 60px;width: 100%;" alt="验证码"/>
</div>
<div class=" col-3" style="padding: 0px;">
< a href=" " id="transform" style="display: block;line-height: 60px;margin-left:20px ;">换一换</ a>
</div>
为了实现验证码刷新需要在请求后面加上时间戳
//时间戳 为了使每次生成图片不一致,即不让浏览器读缓存,所以需要加上时间戳
function chgUrl(url){
var timestamp = (new Date()).valueOf();
url = url.substring(0, 20);
if ((url.indexOf("&") >= 0)) {
url = url + "×tamp=" + timestamp;
} else {
url = url + "?timestamp=" + timestamp;
}
return url;
}
$(function(){
/**
* 重新生成验证码
*/
$("a[id='transform']").click(function(){
/** 重新设置验证码图片的src属性,让它引用一张新的图片 */
var imgsrc = "/captcha/logCheck";
$("#vimg").attr("src",chgUrl(imgsrc));
});
/**
* 验证表单信息
*/
});
在测试中遇到了500错误
javax.imageio.IIOException: Can't create output stream!
javax.imageio.ImageIO.write(ImageIO.java:1574)
cn.suyizhen.controller.CaptchaController.logcheck(CaptchaController.java:116)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:498)
org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190)
org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:892)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:797)
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1039)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:897)
javax.servlet.http.HttpServlet.service(HttpServlet.java:635)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882)
javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118)
主要原因如下:
在使用ImageIO进行图片写操作时,默认会使用缓存目录:${tomcat}/temp,在此缓存目录会生成缓存文件imageio4138671232726624650.tmp(这一串数字应该是当前时间戳,临时文件名),有些生产环境的tomcat,会将temp目录删除,因此报错
4种解决方法如下:
1、在tomcat下新建temp目录;
2、与方法1相似,通过ImageIO.setCacheDirectory(cacheDirectory);设置任意的、存在的缓存目录
3、ImageIO默认是使用缓存目录,可以通过ImageIO.setUseCache(false)来设置,更改缓存策略,不使用文件目录缓存,使用内存缓存
4、不使用ImageIO,换成其它JDK方法
ImageIO.write(bi, "jpg", baos);
换成:
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(response.getOutputStream());
encoder.encode(image);
参考博客(https://blog.csdn.net/cwfreebird/article/details/51820993)






网友评论