驗證碼圖片生成步驟
創建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 id="verification" src="<%=request.getContextPath()+"/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); }最後運行的效果圖如下
以上就是本文的全部內容,希望對大家的學習有所幫助。