验证码图片生成步骤
- 创建BufferedImage对象。
- 获取BufferedImage的画笔,即调用getGraphics()方法获取Graphics对象。
- 调用Graphics对象的setColor()方法和fillRect()方法设置图片背景颜色。
- 调用Graphics对象的setColor()方法和drawLine()方法设置图片干扰线。
- 调用BufferedImaged对象的setRGB()方法设置图片的噪点。
- 调用Graphics对象的setColor()方法、setFont()方法和drawString()方法设置图片验证码。
因为验证码的图片的宽度和高度要根据网站的风格来确定的,所以字体的大小需要根据图片的宽度和高度来确定,用到了小小的技巧。
package util;import java.awt.Color;import java.awt.Font;import java.awt.Graphics;import java.awt.Image;import java.awt.image.BufferedImage;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.util.Random;import javax.imageio.ImageIO;public class Verification { private static final String ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890"; /** * 生成一个宽为width, 高为height, 验证码为code的图片 * @param width 图片的宽 * @param height 图片的高 * @param code 验证码字符串 * @return 返回图片验证码 */ public static BufferedImage getImage(int width, int height, String code){ return getImage(width, height, code, 20); } /** * 生成一个宽为width, 高为height, 验证码为code的图片,图片中干扰线的条数为lineCnt * @param width 图片的宽 * @param height 图片的高 * @param code 验证码字符串 * @param lineCnt 干扰线的条数,建议为10条左右,可根据结果适当调整 * @return 返回图片验证码 */ public static BufferedImage getImage(int width, int height, String code, int lineCnt){ return createImage(width, height, code, lineCnt, 0.01); } /** * 生成一个宽为width, 高为height, 验证码为code的图片,图片中干扰线的条数为lineCnt * 噪声比为noiseRate,即图片中噪音像素点的百分比 * @param width 图片的宽 * @param height 图片的高 * @param code 验证码字符串 * @param lineCnt 干扰线的条数,建议为10条左右,可根据结果适当调整 * @param noiseRate 图片中噪音像素点占总像素的百分比 * @return 返回图片验证码 */ public static BufferedImage getImage(int width, int height, String code, int lineCnt, double noiseRate){ return createImage(width, height, code, lineCnt, noiseRate); } /** * * 生成一个宽为width, 高为height, 验证码为code的图片,图片中干扰线的条数为lineCnt * 噪声比为noiseRate,即图片中噪音像素点的百分比 * @param width 图片的宽 * @param height 图片的高 * @param code 验证码字符串 * @param lineCnt 干扰线的条数,建议为10条左右,可根据结果适当调整 * @param noiseRate 图片中噪音像素点占总像素的百分比 * @return 返回图片验证码 */ private static BufferedImage createImage(int width, int height, String code, int lineCnt, double noiseRate){ int fontWidth = ((int)(width * 0.8)) / code.length(); int fontHeight = (int)(height * 0.7); //为了在任意的width和height下都能生成良好的验证码, //字体的大小为fontWdith何fontHeight中的小者, int fontSize = Math.min(fontWidth, fontHeight); //drawString时要用到 int paddingX = (int) (width * 0.1); int paddingY = height - (height - fontSize) / 2; //创建图像 BufferedImage buffimg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); //获得画笔 Graphics g = buffimg.getGraphics(); //设置画笔的颜色 g.setColor(getRandColor(200, 255)); //然后填充一个矩形,即设置背景色 g.fillRect(0, 0, width, height); // 设置干扰线 for (int i = 0; i < lineCnt; i++) { //随机获取干扰线的起点和终点 int xs = (int)(Math.random() * width); int ys = (int)(Math.random() * height); int xe = (int)(Math.random() * width); int ye = (int)(Math.random() * height); g.setColor(getRandColor(1, 255)); g.drawLine(xs, ys, xe, ye); } // 添加噪点 int area = (int) (noiseRate * width * height); for(int i=0; i<area; ++i){ int x = (int)(Math.random() * width); int y = (int)(Math.random() * height); buffimg.setRGB(x, y, (int)(Math.random() * 255)); } //设置字体 Font font = new Font("Ravie", Font.PLAIN, fontSize); g.setFont(font); for(int i=0; i<code.length(); ++i){ String ch = code.substring(i, i+1); g.setColor(getRandColor(1, 199)); g.drawString(ch, paddingX + fontWidth * i, paddingY); } return buffimg; } /** * 获取随机的颜色,r,g,b的取值在L到R之间 * @param L 左区间 * @param R 右区间 * @return 返回随机颜色值 */ private static Color getRandColor(int L, int R){ if(L > 255) L = 255; if(R > 255) R = 255; if(L < 0) L = 0; if(R < 0) R = 0; int interval = R - L; int r = L + (int)(Math.random() * interval); int g = L + (int)(Math.random() * interval); int b = L + (int)(Math.random() * interval); return new Color(r, g, b); } /** * 随机生成若干个由大小写字母和数字组成的字符串 * @param len 随机生成len个字符 * @return 返回随机生成的若干个由大小写字母和数字组成的字符串 */ public static String getRandCode(int len){ String code = ""; for(int i=0; i<len; ++i){ int index = (int)(Math.random() * ALPHABET.length()); code = code + ALPHABET.charAt(index); } return code; } /** * 将图片转为byte数组 * @param image 图片 * @return 返回byte数组 * @throws IOException */ public static byte[] getByteArray(BufferedImage image) throws IOException{ ByteArrayOutputStream baos = new ByteArrayOutputStream(); ImageIO.write(image, "png", baos); return baos.toByteArray(); //ByteArrayOutputStream 不需要close }}
使用验证码图片
在verificationCode.java这个servlet中调用上面的类生成验证码图片,然后将图片返回给客户端。
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { HttpSession session = request.getSession(); //随机生成字符串,并写入session String code = Verification.getRandCode(4); session.setAttribute("verification", code); BufferedImage image = util.Verification.getImage(100,30, code, 5); response.setContentType("image/png"); OutputStream out = response.getOutputStream(); out.write(util.Verification.getByteArray(image)); out.flush(); out.close(); }
在index.jsp中设置验证码,用户点击验证码时,调用js代码请求服务器得到新的验证码。因为上面的那个生成验证码的servlet会被浏览器缓存,所以js代码中需要给该servlet一个随机的参数,这样浏览器就会向服务器发请求得到新的验证码,而不是去缓存中读取。
<%@page import="util.Verification"%><%@ page language="java" contentType="text/html; charset=UTF-8" 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><script type="text/javascript"> function refreshcode(){ document.getElementById("verification").src= "/verificationCode/verificationCode?hehe="+Math.random(); } </script></head><body> <form action="<%=request.getContextPath()+"/checkVerification" %>" method="post"> 验证码:<input type="text" name="submitVerification"> <img src="/static/imghwm/default1.png" data-src="<%=request.getContextPath()+" class="lazy" id="verification" alt="" title="看不清点击刷新验证码"/verificationCode" %>" onclick="refreshcode()"><br> <input type="submit" name="submit" value="提交"> </form> </body></html>
最后是在checkVerification.java这个servlet中判断用户输入的验证码是否正确,为了方便用户,验证码一般都设置成大小写不敏感,所以要先转化为小写字母再比对。
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { HttpSession session = request.getSession(); String verification = (String)session.getAttribute("verification"); String submitVerification = request.getParameter("submitVerification"); PrintWriter out = response.getWriter(); if(verification!=null && submitVerification!=null){ if(verification.toLowerCase().equals(submitVerification.toLowerCase())){ out.println("yes!!!"); } else{ out.println("no!!!"); } } else{ out.println("no!!!"); } session.removeAttribute("verification");//防止用户重复提交表单 } /** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub doGet(request, response); }
最后运行的效果图如下
该文章在我的个人博客地址是: http://www.alphaway.org/post-464.html

The official account web page update cache, this thing is simple and simple, and it is complicated enough to drink a pot of it. You worked hard to update the official account article, but the user still opened the old version. Who can bear the taste? In this article, let’s take a look at the twists and turns behind this and how to solve this problem gracefully. After reading it, you can easily deal with various caching problems, allowing your users to always experience the freshest content. Let’s talk about the basics first. To put it bluntly, in order to improve access speed, the browser or server stores some static resources (such as pictures, CSS, JS) or page content. Next time you access it, you can directly retrieve it from the cache without having to download it again, and it is naturally fast. But this thing is also a double-edged sword. The new version is online,

The article discusses using HTML5 form validation attributes like required, pattern, min, max, and length limits to validate user input directly in the browser.

This article demonstrates efficient PNG border addition to webpages using CSS. It argues that CSS offers superior performance compared to JavaScript or libraries, detailing how to adjust border width, style, and color for subtle or prominent effect

Article discusses best practices for ensuring HTML5 cross-browser compatibility, focusing on feature detection, progressive enhancement, and testing methods.

The article discusses the HTML <datalist> element, which enhances forms by providing autocomplete suggestions, improving user experience and reducing errors.Character count: 159

The article discusses the HTML <progress> element, its purpose, styling, and differences from the <meter> element. The main focus is on using <progress> for task completion and <meter> for stati

This article explains the HTML5 <time> element for semantic date/time representation. It emphasizes the importance of the datetime attribute for machine readability (ISO 8601 format) alongside human-readable text, boosting accessibilit

The article discusses the HTML <meter> element, used for displaying scalar or fractional values within a range, and its common applications in web development. It differentiates <meter> from <progress> and ex


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

AI Hentai Generator
Generate AI Hentai for free.

Hot Article

Hot Tools

WebStorm Mac version
Useful JavaScript development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

SublimeText3 Chinese version
Chinese version, very easy to use

Safe Exam Browser
Safe Exam Browser is a secure browser environment for taking online exams securely. This software turns any computer into a secure workstation. It controls access to any utility and prevents students from using unauthorized resources.

Dreamweaver Mac version
Visual web development tools
