zoukankan      html  css  js  c++  java
  • java生成图片验证码--封装生成图片验证码的工具类

    博客部分内容转载自 LonlySnow的博客:后台java 实现验证码生成

    1、controller方法

    @RequestMapping(value = "/verifycode/img", method = RequestMethod.GET)
    @ApiOperation("generate image verification code")
    public void generateImgVerificationCode(HttpServletRequest request, HttpServletResponse response) {
        
        try {
            // int width = 200;
            // int height = 69;
            int width = 129;
            int height = 40;
            BufferedImage verifyImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
    
            // 生成对应宽高的初始图片
            // 生成验证码字符并加上噪点,干扰线,返回值为验证码字符
            String randomText = UtilFunctions.drawRandomText(width, height, verifyImg);
            
            request.getSession().setAttribute("img_verify_code", randomText.toUpperCase());
            request.getSession().setAttribute("img_verify_time", System.currentTimeMillis());
            
            response.setContentType("image/png"); // 必须设置响应内容类型为图片,否则前台不识别
            OutputStream os = response.getOutputStream(); // 获取文件输出流
            ImageIO.write(verifyImg, "png", os); // 输出图片流
    
            os.flush();
            os.close();
        } catch (Exception e) {
            UtilFunctions.log.error("msg: {}, exception: {}", e.toString(), e);
            UtilFunctions.reportError(e.toString(), e);
        }
    }

    2、生成图片的方法

    public static String drawRandomText(int width, int height, BufferedImage verifyImg) {
    
        Graphics2D graphics = (Graphics2D) verifyImg.getGraphics();
        graphics.setColor(Color.WHITE);// 设置画笔颜色-验证码背景色
        graphics.fillRect(0, 0, width, height);// 填充背景
        // graphics.setFont(new Font("微软雅黑", Font.BOLD, 40));
        graphics.setFont(new Font("微软雅黑", Font.BOLD, 30));
        
        // 数字和字母的组合
        //String baseNumLetter = "123456789abcdefghijklmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ";
        //String baseNumLetter = "2345678abcdefhijkmnpqrstuvwxyzABCDEFGHJKLMNPQRTUVWXY";
        String baseNumLetter = "123456789";
        StringBuffer sBuffer = new StringBuffer();
        int x = 10; // 旋转原点的 x 坐标
        String ch = "";
    
        Random random = new Random();
        Color textColor = getRandomColor();
        for (int i = 0; i < 4; i++) {
            // graphics.setColor(getRandomColor());
            graphics.setColor(textColor);
            // 设置字体旋转角度
            int degree = random.nextInt() % 30; // 角度小于30度
            int dot = random.nextInt(baseNumLetter.length());
            ch = baseNumLetter.charAt(dot) + "";
            sBuffer.append(ch);
            // 正向旋转
            graphics.rotate(degree * Math.PI / 180, x, 45);
            //graphics.drawString(ch, x, 45);
            graphics.drawString(ch, x, 30);
            // 反向旋转
            graphics.rotate(-degree * Math.PI / 180, x, 45);
            //x += 48;
            x += 30;
        }
    
        // 画干扰线
        for (int i = 0; i < 6; i++) {
            // 设置随机颜色
            graphics.setColor(getRandomColor());
            // 随机画线
            graphics.drawLine(random.nextInt(width), random.nextInt(height), random.nextInt(width),
                    random.nextInt(height));
        }
    
        // 添加噪点
    //        for (int i = 0; i < 30; i++) {
    //            int x1 = random.nextInt(width);
    //            int y1 = random.nextInt(height);
    //            graphics.setColor(getRandomColor());
    //            graphics.fillRect(x1, y1, 2, 2);
    //        }
        return sBuffer.toString();
    }
    
    private static Color getRandomColor() {
        Random ran = new Random();
        Color color = new Color(ran.nextInt(256), ran.nextInt(256), ran.nextInt(256));
        return color;
    }

     

    3、效果

    ==========================================================

    4、 使用java来画图的api

    // 得到图片缓冲区
    BufferedImage bi = new BufferedImage(150, 70, BufferedImage.TYPE_INT_RGB);
    // 得到它的绘制环境(画图的笔)
    Graphics2D g2 = (Graphics2D) bi.getGraphics();
    
    g2.setColor(Color.WHITE);// 设置画笔颜色,即后面背景色为白色
    g2.fillRect(0, 0, 150, 70);// 填充整张图片(其实就是设置背景色)
    
    g2.setColor(Color.BLUE);// 设置画笔颜色,即后面边框颜色为蓝色
    g2.drawRect(0, 0, 150 - 1, 70 - 1);// 设置边框
    
    g2.setFont(new Font("宋体", Font.BOLD, 18));// 设置字体名称、样式、字号
    g2.setColor(Color.BLACK);// 设置画笔颜色,即后面字符串颜色为黑色
    g2.drawString("HelloWorld", 20, 40);// 设置字符"H"左下角坐标,向图片上写字符串
    
    ImageIO.write(bi, "JPEG", new FileOutputStream("D:/a.jpg"));// 保存图片

    5、生成验证码图片的工具类VerifyCode

    package com.oy.demo;
    
    import java.awt.BasicStroke;
    import java.awt.Color;
    import java.awt.Font;
    import java.awt.Graphics2D;
    import java.awt.image.BufferedImage;
    import java.io.IOException;
    import java.io.OutputStream;
    import java.util.Random;
    
    import javax.imageio.ImageIO;
    
    public class VerifyCode {
        private int w = 70;
        private int h = 35;
         private Random r = new Random();
         // {"宋体", "华文楷体", "黑体", "华文新魏", "华文隶书", "微软雅黑", "楷体_GB2312"}
        private String[] fontNames  = {"宋体", "华文楷体", "黑体", "微软雅黑", "楷体_GB2312"};
        //可选字符
        private String codes  = "23456789abcdefghjkmnopqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ";
        //背景色
        private Color bgColor  = new Color(255, 255, 255);
        private String text ;
        
        //生成随机的颜色
        private Color randomColor () {
            int red = r.nextInt(150);
            int green = r.nextInt(150);
            int blue = r.nextInt(150);
            return new Color(red, green, blue);
        }
        
        //生成随机字体
        private Font randomFont () {
            int index = r.nextInt(fontNames.length);
            String fontName = fontNames[index];
            int style = r.nextInt(4);  //生成随机样式,0:无样式,1:粗体,2:斜体,3:粗体+斜体
            int size = r.nextInt(5) + 24; //生成随机字号
            return new Font(fontName, style, size);
        }
        
        //画干扰线
        private void drawLine (BufferedImage image) {
            int num  = 3; //总共画三条干扰线
            Graphics2D g2 = (Graphics2D)image.getGraphics();
            for(int i = 0; i < num; i++) { //生成两个点的左边,即4个值
                int x1 = r.nextInt(w);
                int y1 = r.nextInt(h);
                int x2 = r.nextInt(w);
                int y2 = r.nextInt(h); 
                g2.setStroke(new BasicStroke(1.5F)); 
                g2.setColor(Color.BLUE);   //设置干扰线颜色为蓝色
                g2.drawLine(x1, y1, x2, y2);
            }
        }
        
        //随机生成一个字符
        private char randomChar () {
            int index = r.nextInt(codes.length());
            return codes.charAt(index);
        }
        
        //创建BufferedImage
        private BufferedImage createImage () {
            BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); 
            Graphics2D g2 = (Graphics2D)image.getGraphics(); 
            g2.setColor(this.bgColor);
            g2.fillRect(0, 0, w, h);
             return image;
        }
        
        public BufferedImage getImage () {
            BufferedImage image = createImage(); //创建图片缓冲区
            Graphics2D g2 = (Graphics2D)image.getGraphics();//得到绘制环境,画笔
            StringBuilder sb = new StringBuilder();//用来装载生成的验证码文本
            // 向图片中画4个字符
            for(int i = 0; i < 4; i++)  {
                String s = randomChar() + "";   //随机生成一个字符
                sb.append(s); 
                float x = i * 1.0F * w / 4; //设置当前字符的x轴坐标
                g2.setFont(randomFont());  //设置随机字体
                g2.setColor(randomColor()); //设置随机颜色
                g2.drawString(s, x, h-5);  //画图
            }
            this.text = sb.toString();  //把生成的字符串赋给this.text
            drawLine(image); //添加干扰线
            return image;        
        }
        
        //返回验证码图片上的文本
        public String getText () {
            return text;
        }
        
        //保存图片到指定的输出流
        public static void output (BufferedImage image, OutputStream out) 
                    throws IOException {
            ImageIO.write(image, "JPEG", out);
        }
    }

      VerifyCode的使用

    @Test
    public void fun() throws FileNotFoundException, IOException {
        VerifyCode verifyCode = new VerifyCode();
        BufferedImage bi = verifyCode.getImage();// 随机的
        System.out.println(verifyCode.getText());// 打印图片上的文本内容
        VerifyCode.output(bi, new FileOutputStream("d:/b.jpg"));
    }

      创建一个Servlet:使用VerifyCode返回图片验证码

    public class VerifyCodeServlet extends HttpServlet {
        public void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            /*
             * a、生成图片; b、保存图片上的文本到session域中; c、把图片响应给客户端。
             */
            VerifyCode vc = new VerifyCode();
            BufferedImage bi = vc.getImage(); // 生成图片
            request.getSession().setAttribute("session_verifyCode", vc.getText()); // 保存图片上的文本到session域中
            VerifyCode.output(bi, response.getOutputStream());// 把图片响应给客户端
        }
    }

      login.jsp

    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
    <%
    String path = request.getContextPath();
    String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
    %>
    
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
      <head>
        <base href="<%=basePath%>">
        
        <title>My JSP 'login.jsp' starting page</title>
        
        <meta http-equiv="pragma" content="no-cache">
        <meta http-equiv="cache-control" content="no-cache">
        <meta http-equiv="expires" content="0">    
        <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
        <meta http-equiv="description" content="This is my page">
        <!--
        <link rel="stylesheet" type="text/css" href="styles.css">
        -->
    
      </head>
      
      <body>
        <h2>登录页面</h2>
        
        <%
            /*
             * 查找名为"uname"的Cookie,如果存在,将该Cookie的值赋给变量uname
             */
            String uname="";
            Cookie[] cs=request.getCookies(); //获取所有Cookie
            if(null!=cs){   //如果存在Cookie
                for(Cookie c:cs){  //遍历所有Cookie
                    if("uname".equals(c.getName())){  //查找名为"uname"的Cookie
                        uname=c.getValue();    //把名为"uname"的Cookie的值赋给变量uname
                    }
                }
            }
         %>
         
         <!-- 显示登录错误信息 -->
        <div style="color:red;">
        <%
            String msg=(String)request.getAttribute("msg");
            if(null!=msg){
                out.print(msg);
            }
         %>
        </div>
        
        <%
            String message_verifyCode="";
            String msg_verifyCode=(String)request.getAttribute("msg_verifyCode");
            if(null!=msg_verifyCode){
            message_verifyCode=msg_verifyCode;
            }
         %>
        
        <!-- 如果存在名为"uname"的Cookie,将其该Cookie的值输出到用户名文本框 -->
        <form action="/day11_2/LoginServlet" method="post">
            用户名:<input type="text" name="username" value="<%=uname %>"/><br/>
            密     码:<input type="password" name="password"/><br/>
            验证码:<input type="text" size="4" name="verifyCode"/>
            <img id="id_img" src="/day11_2/VerifyCodeServlet"/>
            <a href="javascript:_change()">看不清,换一张</a>
            <span style="color:red"><%= message_verifyCode %></span>
            <br/>
            <input type="submit" value="登录"/>
            </form>
            
      </body>
      
      <script type="text/javascript">
            function _change(){
                //获取<img>元素对象
                var imgEle=document.getElementById("id_img");
                //给<img>元素的src属性赋值为"/day11_2/VerifyCodeServlet"
                //"?a="+new Date().getTime()是为了防止浏览器缓存的影响
                imgEle.src="/day11_2/VerifyCodeServlet?a="+new Date().getTime();
                //alert(1);//用来测试代码
        
            }
        </script>
    </html>

      效果:

  • 相关阅读:
    利用javascript的prototype来实现stirng类的扩展并实现string的insert方法
    利用笔记本共享WIFI热点及利用Android手机共享WIFI热点
    语言模型发展综述
    基于阻变存储器阵列的低功耗神经网络存算一体结构研究进展综述
    2021年度总结
    【20220102】连岳摘抄
    【20220103】攻城计
    【20220104】人生很长
    【20220106】带孩子看牙医
    【20220110】怀孕不是一个人的事情
  • 原文地址:https://www.cnblogs.com/xy-ouyang/p/10973063.html
Copyright © 2011-2022 走看看