首先来看看示例的目录结构:
在Jcaptcha的官方文档中有一个 5分钟快速入门的文章, 是介绍快速开发的文章。 有兴趣的可以去上面看看。
这里我发上我的源代码:
web.xml中:
- <?xml version="1.0" encoding="UTF-8"?>
- <!DOCTYPE web-app
- PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
- "http://java.sun.com/dtd/web-app_2_3.dtd">
- <web-app>
- <servlet>
- <servlet-name>jcaptcha</servlet-name>
- <servlet-class>com.ivan.zhang.servlet.ImageCaptchaServlet</servlet-class>
- <load-on-startup>0</load-on-startup>
- </servlet>
- <servlet-mapping>
- <servlet-name>jcaptcha</servlet-name>
- <url-pattern>/jcaptcha</url-pattern>
- </servlet-mapping>
- </web-app>
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"> <web-app> <servlet> <servlet-name>jcaptcha</servlet-name> <servlet-class>com.ivan.zhang.servlet.ImageCaptchaServlet</servlet-class> <load-on-startup>0</load-on-startup> </servlet> <servlet-mapping> <servlet-name>jcaptcha</servlet-name> <url-pattern>/jcaptcha</url-pattern> </servlet-mapping> </web-app>
再需要一个服务类,用来产生Image Service类:
- package com.ivan.zhang.servlet;
- import java.awt.image.BufferedImage;
- import java.io.ByteArrayOutputStream;
- import java.io.IOException;
- import javax.imageio.ImageIO;
- import javax.servlet.ServletConfig;
- import javax.servlet.ServletException;
- import javax.servlet.ServletOutputStream;
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import com.ivan.zhang.CaptchaServiceSingleton;
- import com.octo.captcha.service.CaptchaServiceException;
- import com.sun.image.codec.jpeg.JPEGCodec;
- import com.sun.image.codec.jpeg.JPEGImageEncoder;
- public class ImageCaptchaServlet extends HttpServlet {
- /**
- *
- */
- private static final long serialVersionUID = 1L;
- public void init(ServletConfig servletConfig) throws ServletException {
- super.init(servletConfig);
- }
- protected void doGet(HttpServletRequest httpServletRequest,
- HttpServletResponse httpServletResponse) throws ServletException,
- IOException {
- byte[] captchaChallengeAsJpeg = null;
- // the output stream to render the captcha image as jpeg into
- ByteArrayOutputStream jpegOutputStream = new ByteArrayOutputStream();
- try {
- // get the session id that will identify the generated captcha.
- // the same id must be used to validate the response, the session id
- // is a good candidate!
- String captchaId = httpServletRequest.getSession().getId();
- // call the ImageCaptchaService getChallenge method
- BufferedImage challenge = CaptchaServiceSingleton.getInstance()
- .getImageChallengeForID(captchaId,
- httpServletRequest.getLocale());
- // a jpeg encoder
- JPEGImageEncoder jpegEncoder = JPEGCodec
- .createJPEGEncoder(jpegOutputStream);
- jpegEncoder.encode(challenge);
- } catch (IllegalArgumentException e) {
- httpServletResponse.sendError(HttpServletResponse.SC_NOT_FOUND);
- return;
- } catch (CaptchaServiceException e) {
- httpServletResponse
- .sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
- return;
- }
- captchaChallengeAsJpeg = jpegOutputStream.toByteArray();
- // flush it in the response
- httpServletResponse.setHeader("Cache-Control", "no-store");
- httpServletResponse.setHeader("Pragma", "no-cache");
- httpServletResponse.setDateHeader("Expires", 0);
- httpServletResponse.setContentType("image/jpeg");
- ServletOutputStream responseOutputStream = httpServletResponse
- .getOutputStream();
- responseOutputStream.write(captchaChallengeAsJpeg);
- responseOutputStream.flush();
- responseOutputStream.close();
- }
- }
package com.ivan.zhang.servlet;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.ivan.zhang.CaptchaServiceSingleton;
import com.octo.captcha.service.CaptchaServiceException;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
public class ImageCaptchaServlet extends HttpServlet {
/**
*
*/
private static final long serialVersionUID = 1L;
public void init(ServletConfig servletConfig) throws ServletException {
super.init(servletConfig);
}
protected void doGet(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse) throws ServletException,
IOException {
byte[] captchaChallengeAsJpeg = null;
// the output stream to render the captcha image as jpeg into
ByteArrayOutputStream jpegOutputStream = new ByteArrayOutputStream();
try {
// get the session id that will identify the generated captcha.
// the same id must be used to validate the response, the session id
// is a good candidate!
String captchaId = httpServletRequest.getSession().getId();
// call the ImageCaptchaService getChallenge method
BufferedImage challenge = CaptchaServiceSingleton.getInstance()
.getImageChallengeForID(captchaId,
httpServletRequest.getLocale());
// a jpeg encoder
JPEGImageEncoder jpegEncoder = JPEGCodec
.createJPEGEncoder(jpegOutputStream);
jpegEncoder.encode(challenge);
} catch (IllegalArgumentException e) {
httpServletResponse.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
} catch (CaptchaServiceException e) {
httpServletResponse
.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
return;
}
captchaChallengeAsJpeg = jpegOutputStream.toByteArray();
// flush it in the response
httpServletResponse.setHeader("Cache-Control", "no-store");
httpServletResponse.setHeader("Pragma", "no-cache");
httpServletResponse.setDateHeader("Expires", 0);
httpServletResponse.setContentType("image/jpeg");
ServletOutputStream responseOutputStream = httpServletResponse
.getOutputStream();
responseOutputStream.write(captchaChallengeAsJpeg);
responseOutputStream.flush();
responseOutputStream.close();
}
}
OK,后台的类写完了, 现在我们来看看前台页面的编写:
index.jsp
- <%@ page language="java" contentType="text/html; charset=ISO-8859-1"
- pageEncoding="UTF-8"%>
- <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
- <html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <title>Insert title here</title>
- </head>
- <body>
- <form action="sample.jsp">
- <img src="jcaptcha">
- <input type='text' name='j_captcha_response' value=''>
- </form>
- </body>
- </html>
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="sample.jsp">
<img src="jcaptcha">
<input type='text' name='j_captcha_response' value=''>
</form>
</body>
</html>
sample.jsp: (用来验证的页面 )
- <%@ page language="java" contentType="text/html; charset=ISO-8859-1"
- pageEncoding="UTF-8"%>
- <%@page import="com.octo.captcha.service.CaptchaServiceException"%>
- <%@page import="com.ivan.zhang.CaptchaServiceSingleton"%>
- <%
- Boolean isResponseCorrect = Boolean.FALSE;
- //remenber that we need an id to validate!
- String captchaId = request.getSession().getId();
- //retrieve the response
- String responsestr = request.getParameter("j_captcha_response");
- // Call the Service method
- try {
- isResponseCorrect = CaptchaServiceSingleton.getInstance().validateResponseForID(captchaId, responsestr);
- if(isResponseCorrect){
- }else{
- out.print("It's worng......");
- }
- } catch (CaptchaServiceException e) {
- //should not happen, may be thrown if the id is not valid
- }
- %>
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="UTF-8"%>
<%@page import="com.octo.captcha.service.CaptchaServiceException"%>
<%@page import="com.ivan.zhang.CaptchaServiceSingleton"%>
<%
Boolean isResponseCorrect = Boolean.FALSE;
//remenber that we need an id to validate!
String captchaId = request.getSession().getId();
//retrieve the response
String responsestr = request.getParameter("j_captcha_response");
// Call the Service method
try {
isResponseCorrect = CaptchaServiceSingleton.getInstance().validateResponseForID(captchaId, responsestr);
if(isResponseCorrect){
}else{
out.print("It's worng......");
}
} catch (CaptchaServiceException e) {
//should not happen, may be thrown if the id is not valid
}
%>
这样,我们的第一个版本出来了, 我们来看看效果:
我们看到, 虽然生成了验证码,但是这样的图片给人非常不友好的感觉, 所以我参考Springside中的一样,自己给他设定产生图片的样式:
要实现自定义样式,我们需要一下2个步骤:
1. 告诉Jcaptcha 我要的样式是什么样子.
2. 在提交后,利用我们自己的样式来产生图片.
所以,我们改动一下 :
新加一个类GmailEngine.java(直接拿至Springside ,非常感谢白衣的共享,让我们这样的菜鸟学到很多东西.)
其中代码如下:
- package com.ivan.zhang.servlet;
- import java.awt.Color;
- import java.awt.Font;
- import java.awt.image.ImageFilter;
- import com.octo.captcha.component.image.backgroundgenerator.BackgroundGenerator;
- import com.octo.captcha.component.image.backgroundgenerator.UniColorBackgroundGenerator;
- import com.octo.captcha.component.image.color.RandomListColorGenerator;
- import com.octo.captcha.component.image.deformation.ImageDeformation;
- import com.octo.captcha.component.image.deformation.ImageDeformationByFilters;
- import com.octo.captcha.component.image.fontgenerator.FontGenerator;
- import com.octo.captcha.component.image.fontgenerator.RandomFontGenerator;
- import com.octo.captcha.component.image.textpaster.DecoratedRandomTextPaster;
- import com.octo.captcha.component.image.textpaster.TextPaster;
- import com.octo.captcha.component.image.textpaster.textdecorator.TextDecorator;
- import com.octo.captcha.component.image.wordtoimage.DeformedComposedWordToImage;
- import com.octo.captcha.component.image.wordtoimage.WordToImage;
- import com.octo.captcha.component.word.FileDictionary;
- import com.octo.captcha.component.word.wordgenerator.ComposeDictionaryWordGenerator;
- import com.octo.captcha.component.word.wordgenerator.WordGenerator;
- import com.octo.captcha.engine.image.ListImageCaptchaEngine;
- import com.octo.captcha.image.gimpy.GimpyFactory;
- /**
- * 仿照JCaptcha2.0编写GMail验证码样式的图片引擎.
- *
- * @author calvin
- */
- public class GMailEngine extends ListImageCaptchaEngine {
- @Override
- protected void buildInitialFactories() {
- int minWordLength = 4;
- int maxWordLength = 5;
- int fontSize = 50;
- int imageWidth = 250;
- int imageHeight = 100;
- //word generator
- WordGenerator dictionnaryWords = new ComposeDictionaryWordGenerator(new FileDictionary("toddlist"));
- //word2image components
- TextPaster randomPaster = new DecoratedRandomTextPaster(minWordLength, maxWordLength,
- new RandomListColorGenerator(new Color[] { new Color(23, 170, 27), new Color(220, 34, 11),
- new Color(23, 67, 172) }), new TextDecorator[] {});
- BackgroundGenerator background = new UniColorBackgroundGenerator(imageWidth, imageHeight, Color.white);
- FontGenerator font = new RandomFontGenerator(fontSize, fontSize, new Font[] {
- new Font("nyala", Font.BOLD, fontSize), new Font("Bell MT", Font.PLAIN, fontSize),
- new Font("Credit valley", Font.BOLD, fontSize) });
- ImageDeformation postDef = new ImageDeformationByFilters(new ImageFilter[] {});
- ImageDeformation backDef = new ImageDeformationByFilters(new ImageFilter[] {});
- ImageDeformation textDef = new ImageDeformationByFilters(new ImageFilter[] {});
- WordToImage word2image = new DeformedComposedWordToImage(font, background, randomPaster, backDef, textDef,
- postDef);
- addFactory(new GimpyFactory(dictionnaryWords, word2image));
- }
- }
package com.ivan.zhang.servlet;
import java.awt.Color;
import java.awt.Font;
import java.awt.image.ImageFilter;
import com.octo.captcha.component.image.backgroundgenerator.BackgroundGenerator;
import com.octo.captcha.component.image.backgroundgenerator.UniColorBackgroundGenerator;
import com.octo.captcha.component.image.color.RandomListColorGenerator;
import com.octo.captcha.component.image.deformation.ImageDeformation;
import com.octo.captcha.component.image.deformation.ImageDeformationByFilters;
import com.octo.captcha.component.image.fontgenerator.FontGenerator;
import com.octo.captcha.component.image.fontgenerator.RandomFontGenerator;
import com.octo.captcha.component.image.textpaster.DecoratedRandomTextPaster;
import com.octo.captcha.component.image.textpaster.TextPaster;
import com.octo.captcha.component.image.textpaster.textdecorator.TextDecorator;
import com.octo.captcha.component.image.wordtoimage.DeformedComposedWordToImage;
import com.octo.captcha.component.image.wordtoimage.WordToImage;
import com.octo.captcha.component.word.FileDictionary;
import com.octo.captcha.component.word.wordgenerator.ComposeDictionaryWordGenerator;
import com.octo.captcha.component.word.wordgenerator.WordGenerator;
import com.octo.captcha.engine.image.ListImageCaptchaEngine;
import com.octo.captcha.image.gimpy.GimpyFactory;
/**
* 仿照JCaptcha2.0编写GMail验证码样式的图片引擎.
*
* @author calvin
*/
public class GMailEngine extends ListImageCaptchaEngine {
@Override
protected void buildInitialFactories() {
int minWordLength = 4;
int maxWordLength = 5;
int fontSize = 50;
int imageWidth = 250;
int imageHeight = 100;
//word generator
WordGenerator dictionnaryWords = new ComposeDictionaryWordGenerator(new FileDictionary("toddlist"));
//word2image components
TextPaster randomPaster = new DecoratedRandomTextPaster(minWordLength, maxWordLength,
new RandomListColorGenerator(new Color[] { new Color(23, 170, 27), new Color(220, 34, 11),
new Color(23, 67, 172) }), new TextDecorator[] {});
BackgroundGenerator background = new UniColorBackgroundGenerator(imageWidth, imageHeight, Color.white);
FontGenerator font = new RandomFontGenerator(fontSize, fontSize, new Font[] {
new Font("nyala", Font.BOLD, fontSize), new Font("Bell MT", Font.PLAIN, fontSize),
new Font("Credit valley", Font.BOLD, fontSize) });
ImageDeformation postDef = new ImageDeformationByFilters(new ImageFilter[] {});
ImageDeformation backDef = new ImageDeformationByFilters(new ImageFilter[] {});
ImageDeformation textDef = new ImageDeformationByFilters(new ImageFilter[] {});
WordToImage word2image = new DeformedComposedWordToImage(font, background, randomPaster, backDef, textDef,
postDef);
addFactory(new GimpyFactory(dictionnaryWords, word2image));
}
}
如果有玩过Swing的兄弟,应该会很好理解上面的代码。
继续,我们有了自己的样式类, 接下来我们就要告诉servlet我们需要用哪个样式生成图片。
就有如下,将CaptchaServiceSingleton类修改一下:
- package com.ivan.zhang;
- import com.ivan.zhang.servlet.GMailEngine;
- import com.octo.captcha.engine.GenericCaptchaEngine;
- import com.octo.captcha.service.CaptchaService;
- import com.octo.captcha.service.captchastore.FastHashMapCaptchaStore;
- import com.octo.captcha.service.image.DefaultManageableImageCaptchaService;
- import com.octo.captcha.service.image.ImageCaptchaService;
- /**
- * 按照官方的做法: 一定为单例
- * @author Administrator
- *
- */
- public class CaptchaServiceSingleton {
- private static ImageCaptchaService instance = new DefaultManageableImageCaptchaService(
- new FastHashMapCaptchaStore(), new GMailEngine(), 180,
- 100000 , 75000);
- public static ImageCaptchaService getInstance(){
- return instance;
- }
- }
package com.ivan.zhang;
import com.ivan.zhang.servlet.GMailEngine;
import com.octo.captcha.engine.GenericCaptchaEngine;
import com.octo.captcha.service.CaptchaService;
import com.octo.captcha.service.captchastore.FastHashMapCaptchaStore;
import com.octo.captcha.service.image.DefaultManageableImageCaptchaService;
import com.octo.captcha.service.image.ImageCaptchaService;
/**
* 按照官方的做法: 一定为单例
* @author Administrator
*
*/
public class CaptchaServiceSingleton {
private static ImageCaptchaService instance = new DefaultManageableImageCaptchaService(
new FastHashMapCaptchaStore(), new GMailEngine(), 180,
100000 , 75000);
public static ImageCaptchaService getInstance(){
return instance;
}
}
同样的,修改一下Servlet类:
改动如下:
- package com.ivan.zhang.servlet;
- import java.awt.image.BufferedImage;
- import java.io.ByteArrayOutputStream;
- import java.io.IOException;
- import javax.imageio.ImageIO;
- import javax.servlet.ServletConfig;
- import javax.servlet.ServletException;
- import javax.servlet.ServletOutputStream;
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import com.ivan.zhang.CaptchaServiceSingleton;
- import com.octo.captcha.service.CaptchaServiceException;
- import com.sun.image.codec.jpeg.JPEGCodec;
- import com.sun.image.codec.jpeg.JPEGImageEncoder;
- public class ImageCaptchaServlet extends HttpServlet {
- /**
- *
- */
- private static final long serialVersionUID = 1L;
- public void init(ServletConfig servletConfig) throws ServletException {
- super.init(servletConfig);
- }
- protected void doGet(HttpServletRequest httpServletRequest,
- HttpServletResponse httpServletResponse) throws ServletException,
- IOException {
- genernateCaptchaImage(httpServletRequest, httpServletResponse);
- }
- /**
- * 生成验证码图片.
- */
- private void genernateCaptchaImage(final HttpServletRequest request, final HttpServletResponse response)
- throws IOException {
- response.setHeader("Cache-Control", "no-store");
- response.setHeader("Pragma", "no-cache");
- response.setDateHeader("Expires", 0);
- response.setContentType("image/jpeg");
- ServletOutputStream out = response.getOutputStream();
- try {
- String captchaId = request.getSession(true).getId();
- BufferedImage challenge = (BufferedImage) CaptchaServiceSingleton.getInstance().getChallengeForID(captchaId, request.getLocale());
- ImageIO.write(challenge, "jpg", out);
- out.flush();
- } catch (CaptchaServiceException e) {
- } finally {
- out.close();
- }
- }
- }
package com.ivan.zhang.servlet;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.ivan.zhang.CaptchaServiceSingleton;
import com.octo.captcha.service.CaptchaServiceException;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
public class ImageCaptchaServlet extends HttpServlet {
/**
*
*/
private static final long serialVersionUID = 1L;
public void init(ServletConfig servletConfig) throws ServletException {
super.init(servletConfig);
}
protected void doGet(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse) throws ServletException,
IOException {
genernateCaptchaImage(httpServletRequest, httpServletResponse);
}
/**
* 生成验证码图片.
*/
private void genernateCaptchaImage(final HttpServletRequest request, final HttpServletResponse response)
throws IOException {
response.setHeader("Cache-Control", "no-store");
response.setHeader("Pragma", "no-cache");
response.setDateHeader("Expires", 0);
response.setContentType("image/jpeg");
ServletOutputStream out = response.getOutputStream();
try {
String captchaId = request.getSession(true).getId();
BufferedImage challenge = (BufferedImage) CaptchaServiceSingleton.getInstance().getChallengeForID(captchaId, request.getLocale());
ImageIO.write(challenge, "jpg", out);
out.flush();
} catch (CaptchaServiceException e) {
} finally {
out.close();
}
}
}
OK, 这样我们产生的图片样式就会好看多了。 不相信? OK, 非要上图才有人相信。
截图如下:
再来一下刷新: