一、大概思路
- 创建验证码控制类VerifyCodeController,控制类下有初始化图片的方法和响应前端请求的方法
- 编写前端页面
- 利用ajax连接前端和后台,进行图片的动态生成和验证
实际效果图:

具体实现
1.验证码控制类VerifyCodeController
package com.bill.controller;
import com.alibaba.fastjson.JSONObject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.Random;
/**
* @author zkc
*/
@Controller
@RequestMapping("verify")
public class VerifyCodeController {
// 验证码图片的宽度。
private int width = ;
// 验证码图片的高度。
private int height = ;
// 验证码字符个数
private int codeCount = ;
private int x = ;
// 字体高度
private int fontHeight;
private int codeY;
//验证码图片上会出现的字母和数字
char[] codeSequence = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
/**
* 初始化验证图片属性
*/
public void init() throws ServletException {
// 从web.xml中获取初始信息
// 宽度
String strWidth ="80";
// 高度
String strHeight ="30";
// 字符个数
String strCodeCount = "4";
// 将配置的信息转换成数值
try {
if (strWidth != null && strWidth.length() != ) {
width = Integer.parseInt(strWidth);
}
if (strHeight != null && strHeight.length() != ) {
height = Integer.parseInt(strHeight);
}
if (strCodeCount != null && strCodeCount.length() != ) {
codeCount = Integer.parseInt(strCodeCount);
}
} catch (NumberFormatException e) {
}
x = width / (codeCount + );
fontHeight = height - ;
codeY = height - ;
}
@RequestMapping(value="/code.action",method= RequestMethod.GET)
public void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, java.io.IOException {
init();
// 定义图像buffer
BufferedImage buffImg = new BufferedImage(width, height,
BufferedImage.TYPE_INT_RGB);
Graphics2D g = buffImg.createGraphics();
// 创建一个随机数生成器类
Random random = new Random();
// 将图像填充为白色
g.setColor(Color.WHITE);
g.fillRect(, , width, height);
// 创建字体,字体的大小应该根据图片的高度来定。
Font font = new Font("Fixedsys", Font.PLAIN, fontHeight);
// 设置字体。
g.setFont(font);
// 画边框。
g.setColor(Color.BLACK);
g.drawRect(, , width - , height - );
// 随机产生160条干扰线,使图象中的认证码不易被其它程序探测到。
g.setColor(Color.BLACK);
for (int i = ; i < ; i++) {
int x = random.nextInt(width);
int y = random.nextInt(height);
int xl = random.nextInt();
int yl = random.nextInt();
g.drawLine(x, y, x + xl, y + yl);
}
// randomCode用于保存随机产生的验证码,以便用户登录后进行验证。
StringBuffer randomCode = new StringBuffer();
int red = , green = , blue = ;
// 随机产生codeCount数字的验证码。
for (int i = ; i < codeCount; i++) {
// 得到随机产生的验证码数字。
String strRand = String.valueOf(codeSequence[random.nextInt()]);
// 产生随机的颜色分量来构造颜色值,这样输出的每位数字的颜色值都将不同。
red = random.nextInt();
green = random.nextInt();
blue = random.nextInt();
// 用随机产生的颜色将验证码绘制到图像中。
g.setColor(new Color(red, green, blue));
g.drawString(strRand, (i + ) * x, codeY);
// 将产生的四个随机数组合在一起。
randomCode.append(strRand);
}
// 将四位数字的验证码保存到Session中。
HttpSession session = req.getSession();
session.setAttribute("validateCode", randomCode.toString());
// 禁止图像缓存。
resp.setHeader("Pragma", "no-cache");
resp.setHeader("Cache-Control", "no-cache");
resp.setDateHeader("Expires", );
resp.setContentType("image/jpeg");
// 将图像输出到Servlet输出流中。
ServletOutputStream sos = resp.getOutputStream();
ImageIO.write(buffImg, "jpeg", sos);
sos.close();
}
//响应前端请求的方法
@RequestMapping(value="/checkVerifyCode.action",method= RequestMethod.POST)
@ResponseBody
public Object checkVerifyCode(@RequestParam(value = "verifyCode") String verifyCode,HttpServletRequest req, HttpServletResponse resp){
JSONObject jsobjcet = new JSONObject();
String flag = null;
if(verifyCode!=null){
HttpSession session = req.getSession();
//获取图片中的验证码
String validateCode= (String) session.getAttribute("validateCode");
//输入的与图片中的进行比较
if(validateCode!=null&&validateCode.equals(verifyCode.toUpperCase())){
jsobjcet.put("valid", true);
flag = "true";
}else{
jsobjcet.put("valid", false);
flag = "false";
}
}else{
jsobjcet.put("valid", false);
flag = "false";
}
return flag;
}
}
2.前端页面代码(jsp页面)
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP 'index.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<script type="text/javascript" src="js/jquery-1.11.0.js"></script>
<script type="text/javascript">
$(function(){
$("form").submit(function(e){
if($("#tel").val()==""){
alert("手机号不能为空");
e.preventDefault();
}else if($("#pwd").val()==""){
alert("密码不能为空");
e.preventDefault();
}else if($("input[name=validateCode]").val()==""){
alert("验证码不能为空");
e.preventDefault();
}else{
<!-- 获取输入的验证码 -->
var verifyCode=$("input[name=validateCode]").val();
<!-- 通过ajax方式将值传到后台 -->
$.ajax({
url:"verify/checkVerifyCode.action",<!-- 要传的地址 -->
type:"post", <!-- 传值的方式 -->
data:{"verifyCode":verifyCode}, <!-- 传的数据(json对象) -->
async:false, <!-- 是否异步 -->
success:function(result){ <!-- 成功后执行的代码 -->
if(result=="false"){
alert("验证码错误");
e.preventDefault();
}else{
$("form").submit();
}
}
});
}
});
<!-- 刷新图片 -->
$("#refresh").unbind("click").bind("click",function(){
<!-- 传递一个随机数给后台 -->
$("#verify").attr("src","verify/code.action?r"+Math.random());
});
});
</script>
</head>
<body>
<form action="login.action" method="post">
<table>
<tr>
<td>手机号码:</td>
<td><input type="text" name="tel" id="tel"/></td>
</tr>
<tr>
<td>服务密码:</td>
<td><input type="password" name="pwd" id="pwd"/></td>
</tr>
<tr>
<!-- 验证码 -->
<td>验证码:</td>
<td><input type="text" name="validateCode" id="code"/></td>
<td>
<!-- 验证码图片 -->
<img src="verify/code.action" id="verify"/>
<!-- 点击更换验证码图片 -->
<a id="refresh">看不清?</a>
</td>
</tr>
</table>
<input type="submit" value="登录"/>
</form>
</body>
</html>
由于我用了spring框架,所以还需要配置一下xml文件,下面是配置信息
1.web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>billplatform</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<!-- Spring -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mybatis.xml</param-value>
</context-param>
<!-- Spring监听 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Spring MVC -->
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>*.action</url-pattern> <!-- 拦截所有.action请求 -->
</servlet-mapping>
<!-- 过滤器统一字符 -->
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
2.springmvc.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">
<!-- 注解扫描(扫描所有包下)-->
<context:component-scan base-package="com.bill.*"></context:component-scan>
<!-- 配置视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 配置视图的前缀
<property name="prefix" value=""></property>-->
<!-- 配置视图的后缀
<property name="suffix" value=".jsp"></property> -->
</bean>
</beans>
以上就是我在spring框架下用ajax实现的一个简单的验证码功能,第一次写博客,很多地方不足,欢迎大家能指出,谢谢。