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>

 

  效果:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM