>>分享Java Web开发技术,并且对孙卫琴的《Tomcat与Java Web开发技术详解》提供技术支持 书籍支持  卫琴直播  品书摘要  在线测试  资源下载  联系我们
发表一个新主题 开启一个新投票 回复文章 您是本文章第 23719 个阅读者 刷新本主题
 * 贴子主题:  java生成图片验证码--封装生成图片验证码的工具类 回复文章 点赞(0)  收藏  
作者:日月光华    发表时间:2024-04-01 03:23:35     消息  查看  搜索  好友  邮件  复制  引用

java生成图片验证码--封装生成图片验证码的工具类
1、controller方法[\b]

@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、生成图片的方法[\b]

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、效果[\b]
点击在新窗口中浏览原图
CTRL+鼠标滚轮放大或缩小

==========================================================
4、 使用java来画图的api[\b]

// 得到图片缓冲区
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[\b]

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>



  效果:
点击在新窗口中浏览原图
CTRL+鼠标滚轮放大或缩小


程序猿的技术大观园:www.javathinker.net
  Java面向对象编程-->图形用户界面(下)
  JavaWeb开发-->Web运作原理(Ⅲ)
  JSP与Hibernate开发-->数据库事务的并发问题的解决方案
  Java网络编程-->用Spring整合CXF发布Web服务
  精通Spring-->通过Axios访问服务器
  Vue3开发-->Vue Router路由管理器
  JSP 国际化
  JSP 表达式语言
  Servlet的调试技巧
  Servlet 点击计数器范例
  详解在Linux系统中安装Tomcat
  《Tomcat与Java Web》新版即将出炉,业界大咖们力荐
  Java Web开发 快速入门
  Java动态追踪技术探究
  关于JSTL标签库版本的升级和下载
  连接MySQL数据库时 JDBC URL中参数的说明
  web.xml文件中jsp-config元素的用法
  SOAP协议介绍
  Web1.0 ,2.0,3.0 的概念和演变
  我是如何成为一个Java Web开发者的
  理解JavaWeb应用中的绝对URI和相对URI
  更多...
 IPIP: 已设置保密
树形列表:   
不管在[url=https://wmbaccrat.... kericnnoe 2024-04-01 03:23:35
1页 1条记录 当前第1
发表一个新主题 开启一个新投票 回复文章


中文版权所有: JavaThinker技术网站 Copyright 2016-2026 沪ICP备16029593号-2
荟萃Java程序员智慧的结晶,分享交流Java前沿技术。  联系我们
如有技术文章涉及侵权,请与本站管理员联系。