zoukankan      html  css  js  c++  java
  • 自己动手实现一次性图片验证码

      以前碰到注册登录需要图形验证码的时候,一般都是到网络上直接淘一个,也不读代码,直接就用了,今天静下来,从头到尾读了一遍代码,自己又照着写了一遍,加上了完整的注释,下面介绍步骤,首先新建一个web项目,src新建一个class类:

      1 import java.awt.BasicStroke;
      2 import java.awt.Color;
      3 import java.awt.Font;
      4 import java.awt.Graphics;
      5 import java.awt.Graphics2D;
      6 import java.awt.image.BufferedImage;
      7 import java.io.FileNotFoundException;
      8 import java.io.FileOutputStream;
      9 import java.io.IOException;
     10 import java.io.OutputStream;
     11 import java.util.Random;
     12 
     13 import javax.imageio.ImageIO;
     14 
     15 public class VCode {
     16 
     17     private int w;// 图片宽
     18     private int h;// 图片高
     19     private Color bgColor = new Color(240, 240, 240);// 背景色
     20     private Random random = new Random();// 随机数对象
     21     // 设置字体范围
     22     private String[] fontNames = { "宋体", "华文楷体", "黑体", "华文新魏", "华文隶书", "微软雅黑",
     23             "楷体" };
     24     //设置字体样式范围
     25     private int[] fontstyles = { 0, 1, 2, 3 };
     26     //设置字号范围
     27     private int[] fontSizes={24,25,26,27,28};
     28     //设置所有字符串范围
     29     private String codes="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
     30     
     31     
     32     //无参构造方法
     33     public VCode() {
     34     }
     35     
     36     //带宽和高的构造函数 
     37     public VCode(int w, int h) {
     38         super();
     39         this.w = w;
     40         this.h = h;
     41     }
     42 
     43 
     44     // 返回一张背景图片
     45     private BufferedImage createImage() {
     46         /**
     47          * 1:创建图片 2:设置背景色
     48          */
     49         // 1:创建图片
     50         BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
     51         // 2:设置背景色
     52         Graphics g = img.getGraphics();
     53         g.setColor(bgColor);
     54         g.fillRect(0, 0, w, h);
     55 
     56         return img;
     57     }
     58 
     59     // 随机返回字体颜色
     60     private Color randomColor() {
     61         int r = random.nextInt(256);
     62         int g = random.nextInt(256);
     63         int b = random.nextInt(256);
     64         return new Color(r, g, b);
     65     }
     66 
     67     // 随机返回字体样式
     68     private Font randomFont() {
     69         //随机生成字体下标,随机从给定的范围内获取一个字体
     70         int index=random.nextInt(fontNames.length);
     71         String name=fontNames[index];
     72 
     73         //随机生成字体样式下表,随机从给定的返回内获取到一个字体样式
     74         index=random.nextInt(fontstyles.length);
     75         int style = fontstyles[index];
     76 
     77         //随机生成字体大小下标,随机从给定的返回内获取到一个字体大小
     78         index=random.nextInt(fontSizes.length);
     79         int size = fontSizes[index];
     80 
     81         return new Font(name, style, size);
     82     }
     83 
     84     // 随机返回字体内容
     85     private String randomChar() {
     86         int index=random.nextInt(codes.length());
     87         
     88         return codes.charAt(index)+"";
     89     }
     90 
     91     //随即返回几条干扰线
     92     private void getLine(BufferedImage img){
     93         //设置干扰线的宽度为1.5倍宽,随机画五条
     94         Graphics2D g=(Graphics2D)img.getGraphics();
     95         g.setColor(Color.BLACK);
     96         g.setStroke(new BasicStroke(1.5f));
     97         for(int i=0;i<5;i++){
     98             int x1=random.nextInt(w);
     99             int y1=random.nextInt(h);
    100             int x2=random.nextInt(w);
    101             int y2=random.nextInt(h);
    102             g.drawLine(x1, y1, x2, y2);
    103             
    104         }
    105         
    106     }
    107     // 用户调用该方法获取图片
    108     public BufferedImage getImage() {
    109         /**
    110          * 随机生成字符,字符范围0-9A-Za-z, 设置字体,字号,是否粗体 都是随机 字符的颜色
    111          */
    112         BufferedImage img = createImage();
    113 
    114         this.getLine(img);
    115         // 获取画笔
    116         Graphics g = img.getGraphics();
    117         // 画内容
    118         for (int i = 0; i < 4; i++) {
    119             g.setColor(this.randomColor());// 获取随机颜色
    120             g.setFont(this.randomFont());// 获取随机字体
    121             g.drawString(this.randomChar(), w / 4 * i, h - 5);// 获取字符串随机内容
    122         }
    123         return img;
    124     }
    125     
    126     //用户调用该方法保存图片到本地
    127     public void saveImage(BufferedImage img,OutputStream ous){
    128         
    129         try {
    130             ImageIO.write(img, "JPEG", ous);
    131         } catch (FileNotFoundException e) {
    132             e.printStackTrace();
    133         } catch (IOException e) {
    134             e.printStackTrace();
    135         }
    136     }
    137 }

    接下来新建一个servlet:

     1 package com.wang.verifySode;
     2 
     3 import java.awt.Color;
     4 import java.awt.Font;
     5 import java.awt.Graphics;
     6 import java.awt.image.BufferedImage;
     7 import java.io.FileOutputStream;
     8 import java.io.IOException;
     9 import java.io.PrintWriter;
    10 
    11 import javax.imageio.ImageIO;
    12 import javax.servlet.ServletException;
    13 import javax.servlet.http.HttpServlet;
    14 import javax.servlet.http.HttpServletRequest;
    15 import javax.servlet.http.HttpServletResponse;
    16 
    17 public class BServlet extends HttpServlet {
    18 
    19     public void doGet(HttpServletRequest request, HttpServletResponse response)
    20             throws ServletException, IOException {
    21         
    22         VCode v=new VCode(70, 35);
    23         BufferedImage img=v.getImage();
    24         v.saveImage(img, response.getOutputStream());
    25         
    26     }
    27 
    28 }

    在你需要加验证码的地方,如注册页面中适当地方加入:

    <img id="img" alt="" src="/tools/BServlet"><a href="javascript:changeNext()">看不清楚,换一张</a>

    这里需要说一下,因为验证码有一个"看不清楚 换一张"的功能,所以需要加一个javascript函数,如下:

    <script type="text/javascript">
        function changeNext(){
            var a=document.getElementById("img");
            a.src="/tools/BServlet?a="+new Date().getTime();
        }
    </script>

    为了避免浏览器的图片缓存问题而导致点击后无法随机下一张图片,这里在超链接后面加一个永不重复的参数,可以避免这个问题,见上面代码.

    配置项目,开浏览器,运行,完美~

  • 相关阅读:
    PHP-redis中文文档
    thinkphp5操作redis系列教程】列表类型之lRange,lGetRange
    微信小程序利用canvas生成海报分享图片
    layui 富文本 图片上传 后端PHP接口
    Redis 学习笔记(十二)Redis 复制功能详解 ----- (error) READONLY You can't write against a read only slave
    php 从2维数组组合为四维数组分析(项目中前台侧边栏导航三级分类显示)
    MySQL中的外键是什么、有什么作用
    微信小程序之自定义模态弹窗(带动画)实例
    【JZOJ4805】【NOIP2016提高A组模拟9.28】跟踪
    【JZOJ4804】【NOIP2016提高A组模拟9.28】成绩调研
  • 原文地址:https://www.cnblogs.com/fingerboy/p/5152683.html
Copyright © 2011-2022 走看看