1

1. 先看前端页面的验证码图片与html代码:/register.jsp
验证码图片

<h1>注册校验</h1>
<table width="80%" border="0" cellspacing="2" class="upline">
    <tr>
        <td style="text-align:right; width:20%">输入校验码:</td>
        <td style="width:50%"><input type="text" class="textinput" /></td>
        <td>&nbsp;</td>
    </tr>
    <tr>
        <td style="text-align:right;width:20%;">&nbsp;</td>
        <td colspan="2" style="width:50%">
            <img src="${pageContext.request.contextPath}/imageCode" width="180" height="30" class="textinput" style="height:30px;" id="img" />&nbsp;&nbsp;
            <a href="javascript:void(0);" onclick="changeImage()">看不清换一张</a>
        </td>
    </tr>
</table>

2. 根据上面代码可以看到验证码图片的src地址指向了一个名为"imageCode"的Servlet。此Servlet代码如下:ImageCodeServlet.java

@SuppressWarnings("serial")
@WebServlet("/imageCode")
public class ImageCodeServlet extends HttpServlet {
    public void doGet(HttpServletRequest req, HttpServletResponse res)
            throws ServletException, IOException {
        //req.setCharacterEncoding("utf-8");
        //res.setContentType("text/html;charset=utf-8");
        // 设置http响应的文件MIME类型为图片
        res.setContentType("image/jpeg");
        // 不让浏览器记录此图片的缓存
        res.setDateHeader("expries", -1);
        res.setHeader("Cache-Control", "no-cache");
        res.setHeader("Pragma", "no-cache");
        // 这里调用了一个工具类VerifyCodeUtils来生成指定位数(也可指定内容)的验证码字符串
        String verifyCode = VerifyCodeUtils.generateVerifyCode(5);
        // 将生成验证码字符串保存到session域中,方面进行表单验证
        req.getSession().setAttribute("verifyCode", verifyCode);
        // 生成图片并写到响应输出流里. 因为register.jsp页面里的验证码图片宽高分别为180,30.这里使保持一致
        VerifyCodeUtils.outputImage(180, 30, res.getOutputStream(), verifyCode);
    }

    public void doPost(HttpServletRequest req, HttpServletResponse res)
            throws ServletException, IOException {
        doGet(req, res);
    }
}

3. 生成验证码图片的工具类--VerifyUtils.java

import java.awt.Color;  
import java.awt.Font;  
import java.awt.Graphics2D;  
import java.awt.LinearGradientPaint;  
import java.awt.Paint;  
import java.awt.geom.AffineTransform;  
import java.awt.image.BufferedImage;  
import java.io.File;  
import java.io.FileOutputStream;  
import java.io.IOException;  
import java.io.OutputStream;  
import java.util.Arrays;  
import java.util.Random;  
  
import javax.imageio.ImageIO;  
  
public class VerifyCodeUtils{  
    // 可自定义验证码字符源
    public static final String VERIFY_CODES = "123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";  
  
  
    /** 
     * 使用系统默认字符源生成验证码 
     * @param verifySize 验证码长度 
     * @return 
     */  
    public static String generateVerifyCode(int verifySize){  
        return generateVerifyCode(verifySize, VERIFY_CODES);  
    }  
    /** 
     * 使用指定源生成验证码 
     * @param verifySize 验证码长度 
     * @param sources   验证码字符源 
     * @return 
     */  
    public static String generateVerifyCode(int verifySize, String sources){  
        if(sources == null || sources.length() == 0){  
            sources = VERIFY_CODES;  
        }  
        int codesLen = sources.length();  
        Random rand = new Random(System.currentTimeMillis());  
        StringBuilder verifyCode = new StringBuilder(verifySize);  
        for(int i = 0; i < verifySize; i++){  
            verifyCode.append(sources.charAt(rand.nextInt(codesLen-1)));  
        }  
        return verifyCode.toString();  
    }  
      
    /** 
     * 生成随机验证码文件,并返回验证码值 
     * @param w 图片宽(像素)
     * @param h 图片高(像素)
     * @param outputFile 
     * @param verifySize 
     * @return 
     * @throws IOException 
     */  
    public static String outputVerifyImage(int w, int h, File outputFile, int verifySize) throws IOException{  
        String verifyCode = generateVerifyCode(verifySize);  
        outputImage(w, h, outputFile, verifyCode);  
        return verifyCode;  
    }  
      
    /** 
     * 输出随机验证码图片流,并返回验证码值 
     * @param w 
     * @param h 
     * @param os 
     * @param verifySize 
     * @return 
     * @throws IOException 
     */  
    public static String outputVerifyImage(int w, int h, OutputStream os, int verifySize) throws IOException{  
        String verifyCode = generateVerifyCode(verifySize);  
        outputImage(w, h, os, verifyCode);  
        return verifyCode;  
    }  
      
    /** 
     * 生成指定验证码图像文件 
     * @param w 
     * @param h 
     * @param outputFile 
     * @param code 
     * @throws IOException 
     */  
    public static void outputImage(int w, int h, File outputFile, String code) throws IOException{  
        if(outputFile == null){  
            return;  
        }  
        File dir = outputFile.getParentFile();  
        if(!dir.exists()){  
            dir.mkdirs();  
        }  
        try{  
            outputFile.createNewFile();  
            FileOutputStream fos = new FileOutputStream(outputFile);  
            outputImage(w, h, fos, code);  
            fos.close();  
        } catch(IOException e){  
            throw e;  
        }  
    }  
      
    /** 
     * 输出指定验证码图片流 
     * @param w 
     * @param h 
     * @param os 
     * @param code 
     * @throws IOException 
     */  
    public static void outputImage(int w,  
                            int h,  
                            OutputStream os,  
                            String code) throws IOException{  
        int verifySize = code.length();  
        BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);  
        Random rand = new Random();  
        Graphics2D g2 = image.createGraphics();  
        Color[] colors = new Color[5];  
        Color[] colorSpaces = new Color[] { Color.WHITE, Color.CYAN,  
                Color.GRAY, Color.LIGHT_GRAY, Color.MAGENTA, Color.ORANGE,  
                Color.PINK, Color.YELLOW };  
        float[] fractions = new float[colors.length];  
        for(int i = 0; i < colors.length; i++){  
            colors[i] = colorSpaces[rand.nextInt(colorSpaces.length)];  
            fractions[i] = rand.nextFloat();  
        }  
        Arrays.sort(fractions);  
        Paint linearPaint = new LinearGradientPaint(0, 0, w, h, fractions, colors);  
        Paint linearPaint2 = new LinearGradientPaint(0, 0, w, h, new float[]{0.3f, .6f, .8f, .9f}, new Color[]{Color.BLUE, Color.BLACK, Color.GREEN, Color.BLUE});  
        //设置图片背景为白色  
        g2.setPaint(Color.WHITE);  
        g2.fillRect(0, 0, w, h);  
        //设置图片渐变背景  
        g2.setPaint(linearPaint);  
        g2.fillRoundRect(0, 0, w, h, 5, 5);  
          
        g2.setPaint(linearPaint2);  
        int fontSize = (int) (Math.min(w/verifySize, h));  
        Font font = new Font("微软雅黑", Font.BOLD, fontSize);  
        g2.setFont(font);  
        char[] chars = code.toCharArray();  
        for(int i = 0; i < verifySize; i++){  
            AffineTransform affine = new AffineTransform();  
            affine.setToRotation(Math.PI / 4 * rand.nextDouble() * (rand.nextBoolean() ? 1 : -1), (w / verifySize) * i + fontSize/2, h/2);  
            g2.setTransform(affine);  
            g2.drawChars(chars, i, 1, (w / verifySize) * i, h/2 + fontSize /2);  
        }  
        g2.dispose();  
        ImageIO.write(image, "jpg", os);  
    }  
  
    public static void main(String[] args) throws IOException{  
        File dir = new File("F:/verifies");  
        int w = 200, h = 80;  
        for(int i = 0; i < 100; i++){  
            String verifyCode = generateVerifyCode(4);  
            File file = new File(dir, verifyCode + ".jpg");  
            outputImage(w, h, file, verifyCode);  
        }  
    }  
}  

4. 实现点击"看不清楚,换一图片"功能的js代码:/register.jsp:

<script type="text/javascript">
    function changeImage() {
        document.getElementById("img").src = "${pageContext.request.contextPath}/imageCode?time=" + new Date().getTime();
    }
</script>

点击换一张效果


uangianlap
6 声望0 粉丝