首先要有生成验证码图片和验证码文字的逻辑
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package cn.bingou.util; import java.awt.Color; import java.awt.Font; import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.OutputStream; import java.util.Random; import javax.imageio.ImageIO; /** * 动态生成图片 */ public class VerifyCode { // {"宋体", "华文楷体", "黑体", "华文新魏", "华文隶书", "微软雅黑", "楷体_GB2312"} private static String[] fontNames = { "宋体", "华文楷体", "黑体", "微软雅黑", "楷体_GB2312" }; // 可选字符 //"23456789abcdefghjkmnopqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ"; private static String codes = "23456789abcdefghjkmnopqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ"; // 背景色 private Color bgColor = new Color(255, 255, 255); // 基数(一个文字所占的空间大小) private int base = 30; // 图像宽度 private int width = base * 4; // 图像高度 private int height = base; // 文字个数 private int len = 4; // 设置字体大小 private int fontSize = 22; // 验证码上的文本 private String text; private BufferedImage img = null; private Graphics2D g2 = null; /** * 生成验证码图片 */ public void drawImage(OutputStream outputStream) { // 1.创建图片缓冲区对象, 并设置宽高和图像类型 img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); // 2.得到绘制环境 g2 = (Graphics2D) img.getGraphics(); // 3.开始画图 // 设置背景色 g2.setColor(bgColor); g2.fillRect(0, 0, width, height); StringBuffer sb = new StringBuffer();// 用来装载验证码上的文本 for (int i = 0; i < len; i++) { // 设置画笔颜色 -- 随机 // g2.setColor(new Color(255, 0, 0)); g2.setColor(new Color(getRandom(0, 150), getRandom(0, 150),getRandom(0, 150))); // 设置字体 g2.setFont(new Font(fontNames[getRandom(0, fontNames.length)], Font.BOLD, fontSize)); // 旋转文字(-45~+45) int theta = getRandom(-45, 45); g2.rotate(theta * Math.PI / 180, 7 + i * base, height - 8); // 写字 String code = codes.charAt(getRandom(0, codes.length())) + ""; g2.drawString(code, 7 + i * base, height - 8); sb.append(code); g2.rotate(-theta * Math.PI / 180, 7 + i * base, height - 8); } this.text = sb.toString(); // 画干扰线 for (int i = 0; i < len + 2; i++) { // 设置画笔颜色 -- 随机 // g2.setColor(new Color(255, 0, 0)); g2.setColor(new Color(getRandom(0, 150), getRandom(0, 150), getRandom(0, 150))); g2.drawLine(getRandom(0, 120), getRandom(0, 30), getRandom(0, 120), getRandom(0, 30)); } /** * 绘制边框 */ // 设置边框的颜色 g2.setColor(Color.GRAY); // 绘制边框 g2.drawRect(0, 0, width-1, height-1); // 4.保存图片到指定的输出流 try { ImageIO.write(this.img, "JPEG", outputStream); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); }finally{ // 5.释放资源 g2.dispose(); } } /** * 获取验证码字符串 * @return */ public String getCode() { return this.text; } /* * 生成随机数的方法 */ private static int getRandom(int start, int end) { Random random = new Random(); return random.nextInt(end - start) + start; } public static void main(String[] args) throws Exception { VerifyCode vc = new VerifyCode(); vc.drawImage(new FileOutputStream("d:/vc.jpg")); System.out.println("执行成功~!"); } }
在前台添加一个验证码的点击事件,当用户点击验证码时自动切换验证码
// 为img标签添加一个点击事件 $("#valiImage").click(function(){ // 每次点击修改src属性的值,在后面拼接一个不同的参数 // 获取当前时间的毫秒值表示 var timeStr=new Date().getTime(); // 将毫秒之直接拼接在url后面,保证每次点击url的值不同 var url="/ValiImageServlet?time="+timeStr; // 使用生成的url给img标签的src属性赋值 $("#valiImage").attr("src",url); });
此时会请求后台处理逻辑 ValiImageServlet
package cn.bingou.web; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import cn.bingou.util.VerifyCode; public class ValiImageServlet extends HttpServlet { public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 1.接收请求 // 2.调用工具类,生成验证码图片 VerifyCode vc=new VerifyCode(); // 3.将生成的验证码图片存入response实体中 vc.drawImage(resp.getOutputStream()); // 4.控制浏览器不要缓存验证码 // 获取验证码字符串 String text=vc.getCode(); // 将生成的验证码文本输出到控制台 System.out.println("text="+text); // 获取用户的Session对象 HttpSession session=req.getSession(); // 将正确的验证码文本传入Session作用域 session.setAttribute("text", text); // 不要缓存验证码 resp.setHeader("Pragma", "no-cache"); resp.setHeader("Cache-Control", "no-cache"); } public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
后台ValiImageServlet将从VerifyCode得到的验证码图片和文字传输到前台,通过session作用域传递
前台点击提交表单按钮,表单信息将会传输到RegistServlet进行验证
package cn.bingou.web; import java.io.IOException; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import cn.bingou.util.JDBCUtils; import cn.bingou.util.WebUtils; public class RegistServlet extends HttpServlet { public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 1.请求乱码问题 // 请求乱码-POST请求 req.setCharacterEncoding("utf-8"); // 应答乱码问题 resp.setContentType("text/html;charset=utf-8"); // 2.接收表单参数 String username = req.getParameter("username"); String password = req.getParameter("password"); String password2 = req.getParameter("password2"); String nickname = req.getParameter("nickname"); String email = req.getParameter("email"); String valistr = req.getParameter("valistr"); // 3.验证表单 // 1)非空验证 if(WebUtils.isEmpty(username)){ // 用户名为空验证 // 向request作用域中添加错误提示信息 req.setAttribute("errMsg", "用户名不能为空!"); // 将请求转发给regist.jsp,forward():请求转发 req.getRequestDispatcher("/regist.jsp").forward(req, resp); // 如果用户输入为空,直接返回 return; } if(WebUtils.isEmpty(password)){ // 密码为空验证 req.setAttribute("errMsg", "密码不能为空!"); req.getRequestDispatcher("/regist.jsp").forward(req, resp); return; } if(WebUtils.isEmpty(nickname)){ // 昵称为空验证 req.setAttribute("errMsg", "昵称不能为空!"); req.getRequestDispatcher("/regist.jsp").forward(req, resp); return; } if(WebUtils.isEmpty(email)){ // 邮箱为空验证 req.setAttribute("errMsg", "邮箱不能为空!"); req.getRequestDispatcher("/regist.jsp").forward(req, resp); return; } // 2)密码一致验证 if(!password.equals(password2)){ // 如果密码与确认密码不一样,则输出错误 req.setAttribute("errMsg", "密码不一致"); req.getRequestDispatcher("/regist.jsp").forward(req, resp); return; } // 3)邮箱格式验证 // abc@123.163.com String reg="^\\w+@\\w+(\\.\\w+)+$"; if(!email.matches(reg)){ req.setAttribute("errMsg", "邮箱格式不符"); req.getRequestDispatcher("/regist.jsp").forward(req, resp); return; } // 4)用户名是否存在 String sql1="select * from user where username=?"; Connection conn = null; PreparedStatement ps = null; ResultSet rs=null; try { conn=JDBCUtils.getConnection(); ps=conn.prepareStatement(sql1); ps.setString(1, username); rs=ps.executeQuery(); while(rs.next()){ // 寻找用户名,直到找到为止 req.setAttribute("errMsg", "用户名已存在"); req.getRequestDispatcher("/regist.jsp").forward(req, resp); return; } } catch (SQLException e) { e.printStackTrace(); throw new RuntimeException("验证用户名时数据库出现异常:"+e.getMessage()); } finally{ JDBCUtils.close(conn, ps, rs); } // 5)验证码验证 if(WebUtils.isEmpty(valistr)){ // 验证码为空验证 req.setAttribute("errMsg", "验证码不能为空!"); req.getRequestDispatcher("/regist.jsp").forward(req, resp); return; } else{ // 验证码不为空,执行验证码内容验证 // 获取保存在session中的正确验证码 HttpSession session=req.getSession(false);// 如果当前Session没有就为null boolean flag=true; // 默认验证码没有问题 if(session==null && session.getAttribute("text")==null){ // 没有session对象,或者session中没有正确的验证码文本 flag=false; }else{ String text=(String) session.getAttribute("text"); if(!valistr.equalsIgnoreCase(text)){ // 用户输入的文本和正确文本不一致 flag=false; } } if(flag==false){ // 向request作用域中添加错误提示信息 req.setAttribute("errMsg", "验证码错误"); // 将请求转发给regist.jsp req.getRequestDispatcher("/regist.jsp").forward(req, resp); return; } } // 4.数据存入数据库 // 验证信息没有问题,将用户提交的注册信息提交到数据库 String sql2="insert into user values(null,?,?,?,?)"; Connection conn2=null; PreparedStatement ps2=null; try { conn2=JDBCUtils.getConnection(); ps2=conn2.prepareStatement(sql2); ps2.setString(1, username); ps2.setString(2, password); ps2.setString(3, nickname); ps2.setString(4, email); ps2.executeUpdate(); int i=ps2.executeUpdate(); if(i>0){ // 保存成功-提示成功信息,定时刷新到首页 resp.getWriter().write("<h1 style='text-align:center;color:red'>恭喜您,注册成功!3秒后自动跳转首页</h1>"); // 实现定时刷新 resp.setHeader("refresh", "3;url="+req.getContextPath()+"/index.jsp"); }else{ req.setAttribute("errMsg", "注册出现异常,请稍后重试..."); req.getRequestDispatcher("/regist.jsp").forward(req, resp); return; } } catch (SQLException e) { e.printStackTrace(); throw new RuntimeException("注册数据出现异常:"+e.getMessage()); } finally{ JDBCUtils.close(conn2, ps2, rs); } } public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }