教育行業(yè)A股IPO第一股(股票代碼 003032)

全國咨詢/投訴熱線:400-618-4000

JAVA培訓(xùn)之生成驗(yàn)證碼圖片

更新時(shí)間:2016年09月21日10時(shí)18分 來源:傳智播客JAVA培訓(xùn)學(xué)院 瀏覽次數(shù):

生成驗(yàn)證碼圖片
驗(yàn)證碼是Completely Automated Public Turing test to tell Computers and Humans Apart(全自動(dòng)區(qū)分計(jì)算機(jī)和人類的圖靈測(cè)試)的縮寫,是一種區(qū)分用戶是計(jì)算機(jī)還是人的公共全自動(dòng)程序,可以防止:惡意破解密碼、刷票、論壇灌水、有效防止某個(gè)黑客對(duì)某一特定注冊(cè)用戶,用特定程序暴力破解方式進(jìn)行不斷的登錄嘗試。實(shí)際上驗(yàn)證碼是現(xiàn)在很多網(wǎng)站通行的方式,我們利用比較簡(jiǎn)易的方式實(shí)現(xiàn)了這個(gè)功能。
下面我們就來學(xué)習(xí)如何自動(dòng)生成一個(gè)驗(yàn)證碼圖片,案例的源代碼點(diǎn)擊此處進(jìn)行下載,具體如下:

1.生成字符驗(yàn)證碼

大家想必在登錄某個(gè)網(wǎng)站的時(shí)候都輸入過驗(yàn)證碼,如圖1-1所示:
圖1-1 驗(yàn)證碼
下面通過一個(gè)案例來學(xué)習(xí)如何自動(dòng)生成一個(gè)驗(yàn)證碼圖片:
(1)創(chuàng)建一個(gè)web應(yīng)用,名稱為Example1,在該應(yīng)用下的src目錄下新建一個(gè)Class類,名稱為ImageTest,主要代碼如例1-1所示:
例1-1 ImageTest.java
public class ImageTest {
    @Test
public void fun1() throws FileNotFoundException, IOException{
       /*
        * 1. 創(chuàng)建圖片緩沖區(qū)
        * 2. 設(shè)置其寬高
        * 3. 得到這個(gè)圖片的繪制環(huán)境(得到畫筆)
        * 4. 保存起來
        */
       BufferedImage bi = new BufferedImage(70, 35, BufferedImage.TYPE_INT_RGB);
       Graphics2D g = (Graphics2D)bi.getGraphics();//得到繪制環(huán)境
       g.setColor(Color.WHITE);//把環(huán)境設(shè)置為白色
       g.fillRect(0, 0, 70, 35);//填充矩形!填充矩形,從0,0點(diǎn)開始,寬70,高35,即整個(gè)圖片,即為圖片設(shè)置背景色
       g.setColor(Color.RED);//把環(huán)境設(shè)置為紅色
       g.drawString("Hello", 2, 35-2);//向圖片上寫入字符串,其中2,2表示x,y軸的坐標(biāo)
       ImageIO.write(bi, "JPEG", new FileOutputStream("F:/xxx.jpg"));
}
}
在例1-1中,首先要獲得圖片緩沖區(qū),即BufferedImage類的一個(gè)對(duì)象,BufferedImage類的構(gòu)造方法中,第一個(gè)參數(shù)和第二個(gè)參數(shù)表示圖片的長(zhǎng)和寬,第三個(gè)參數(shù)是圖片的類型;然后獲取繪制環(huán)境,也可以理解為獲取當(dāng)前圖片的畫筆,使用該對(duì)象可以設(shè)置一系列的屬性,例如圖片的背景顏色、填充形狀等。最后使用ImageIO類的write()方法將當(dāng)前畫好的圖片寫到指定的輸出流中。
(2)測(cè)試fun1()方法,去F盤查看生成的圖片效果如何,如圖1-2所示:
圖1-2 繪制的圖片
如圖1-2所示,繪制的圖片背景色是白色,字符串“Hello”的顏色是紅色,該字符串的位置也是由我們自己設(shè)置的,可以調(diào)整。

2.生成字母驗(yàn)證碼

通過以上對(duì)自動(dòng)繪制圖片的了解,下面我們來完成另外一個(gè)繪制圖片的類,這個(gè)類相較于上面的ImageTest類要復(fù)雜很多,如下所示:
(1)在ImageTest同包下新建一個(gè)Class類,名稱為VerifyCode,下面我們對(duì)類中的方法進(jìn)行一一介紹。首先來看該類的成員變量,如例1-2所示:
例1-2 VerifyCode.java類中的成員變量
public class VerifyCode {
    private int w = 70;
    private int h = 35;
    private Random r = new Random();
    // {"宋體", "華文楷體", "黑體", "華文新魏", "華文隸書", "微軟雅黑", "楷體_GB2312"}
    private String[] fontNames  = {"宋體", "華文楷體", "黑體", "微軟雅黑", "楷體_GB2312"};
    // 可選字符
    private String codes="23456789abcdefghjkmnopqrstuvwxyzABCDEFGHJKMNPQRSTUV
                              WXYZ";
    // 背景色
    private Color bgColor  = new Color(255, 255, 255);
    // 驗(yàn)證碼上的文本
    private String text ;
例1-2中,成員變量w、h分別表示圖片的長(zhǎng)和寬;成員變量r是Random類型的對(duì)象,用來生成隨機(jī)數(shù);成員變量fontNames是列舉驗(yàn)證圖片中驗(yàn)證碼的字體類型;成員變量codes是列舉驗(yàn)證碼的所有的可選字符;成員變量bgColor是驗(yàn)證圖片的背景色;成員變量text是圖片上的驗(yàn)證碼。
(2)VerifyCode類的生成隨機(jī)顏色的方法,主要代碼如例1-3所示:
例1-3  randomColor()方法
    // 生成隨機(jī)的顏色
private Color randomColor () {
       int red = r.nextInt(150);
       int green = r.nextInt(150);
       int blue = r.nextInt(150);
       return new Color(red, green, blue);
}
例1-3中,r是Random類型的對(duì)象,r.nextInt(int n)方法返回一個(gè)偽隨機(jī)數(shù),它是取自此隨機(jī)數(shù)生成器序列的、在 0(包括)和指定值n(不包括)之間均勻分布的 int值。其中局部變量red、green、blue分別代表顏色的RGB的紅、綠、藍(lán)三個(gè)通道的顏色值。該方法返回的是隨機(jī)產(chǎn)生的顏色。
(3)VerifyCode類的生成隨機(jī)字體的方法,主要代碼如例1-4所示:
例1-4  randomFont()方法
// 生成隨機(jī)的字體
private Font randomFont () {
           int index = r.nextInt(fontNames.length);
           String fontName = fontNames[index];//生成隨機(jī)的字體名稱
           int style = r.nextInt(4);//生成隨機(jī)的樣式, 0(無樣式), 1(粗體), 2(斜體), 3(粗體+斜體)
           int size = r.nextInt(5) + 24; //生成隨機(jī)字號(hào), 24 ~ 28
           return new Font(fontName, style, size);
}
例1-4中,r.nextInt(fontNames.length)方法是獲得一個(gè)從0到成員變量fontNames數(shù)組的長(zhǎng)度之間的整數(shù)index,然后將這個(gè)整數(shù)當(dāng)作fontNames數(shù)組的下標(biāo),找到對(duì)應(yīng)的字體類型。局部變量style是隨機(jī)產(chǎn)生的樣式,詳情可參考例1-4中的代碼注釋,局部變量size是隨機(jī)生成的字體大小,即字號(hào),范圍是從24~28;最后將該字體返回。
(4)VerifyCode類的生成隨機(jī)的干擾線方法,主要代碼如例1-5所示:
例1-5 drawLine()方法
  // 畫干擾線
private void drawLine (BufferedImage image) {
       int num  = 3;//一共畫3條
       Graphics2D g2 = (Graphics2D)image.getGraphics();
       for(int i = 0; i < num; i++) {//生成兩個(gè)點(diǎn)的坐標(biāo),即4個(gè)值
           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); //干擾線是藍(lán)色
           g2.drawLine(x1, y1, x2, y2);//畫線
       }
}
例1-5中,局部變量num是記錄干擾線的條數(shù),然后創(chuàng)建當(dāng)前圖片的畫筆Graphics2D類的對(duì)象,再利用r對(duì)象生成四個(gè)值,其中x1和x2的大小范圍在0~70之間,y1和y2的大小在0~35之間,這四個(gè)值是用來作為確定一條直線的兩個(gè)點(diǎn)的坐標(biāo),由于有三條干擾線,所以這里使用for循環(huán),然后每循環(huán)一次就使用畫筆對(duì)象g2的drawLine()方法繪制一條線。
(5)VerifyCode類的生成隨機(jī)字符的方法,主要代碼如例1-6所示:
// 隨機(jī)生成一個(gè)字符
private char randomChar () {
       int index = r.nextInt(codes.length());
       return codes.charAt(index);
}
例1-6中,驗(yàn)證碼的所有可選字符都在字符串codes中,通過r對(duì)象的nextInt()方法獲得一個(gè)在0到codes.length范圍內(nèi)的整數(shù)index,然后調(diào)用charAt(index)方法獲得指定索引的字符,并返回。
(6)VerifyCode類的創(chuàng)建BufferedImage的方法,主要代碼如例1-7所示:
    // 創(chuàng)建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;
}
例1-7中,創(chuàng)建BufferedImage對(duì)象的步驟與例1-1相同,最后將創(chuàng)建的對(duì)象返回。
(7)VerifyCode類的獲得驗(yàn)證碼圖片上的文本方法,主要代碼如例1-8所示:
    // 返回驗(yàn)證碼圖片上的文本
public String getText () {
       return text;
}
例1-8中的text是成員變量,代表圖片上的驗(yàn)證碼。該方法要在另一個(gè)方法getImage()調(diào)用之后調(diào)用,getImage()方法后面會(huì)詳解。
(8)VerifyCode類的將圖片保存到指定的輸出流,主要代碼如例1-9所示:
    // 保存圖片到指定的輸出流
public static void output (BufferedImage image, OutputStream out)
              throws IOException {
       ImageIO.write(image, "JPEG", out);
}
例1-9中,output()方法有兩個(gè)參數(shù),第一個(gè)參數(shù)是繪制的圖片,第二個(gè)參數(shù)是圖片將要保存的輸出流;使用ImageIO類的write()方法將image對(duì)象以JPEG的格式保存在out輸出流中。
(9)VerifyCode類的得到驗(yàn)證碼圖片的方法,主要代碼如例1-10所示:
    // 調(diào)用這個(gè)方法得到驗(yàn)證碼
public BufferedImage getImage () {
       BufferedImage image = createImage();//創(chuàng)建圖片緩沖區(qū)
       Graphics2D g2 = (Graphics2D)image.getGraphics();//得到繪制環(huán)境
       StringBuilder sb = new StringBuilder();//用來裝載生成的驗(yàn)證碼文本
       // 向圖片中畫4個(gè)字符
       for(int i = 0; i < 4; i++)  {//循環(huán)四次,每次生成一個(gè)字符
           String s = randomChar() + "";//隨機(jī)生成一個(gè)字母
           sb.append(s); //把字母添加到sb
           float x = i * 1.0F * w / 4; //設(shè)置當(dāng)前字符的x軸坐標(biāo)
           g2.setFont(randomFont()); //設(shè)置隨機(jī)字體
           g2.setColor(randomColor()); //設(shè)置隨機(jī)顏色
           g2.drawString(s, x, h-5); //畫圖
       }
       this.text = sb.toString(); //把生成的字符串賦給了this.text
       drawLine(image); //添加干擾線
       return image;    
}
例1-10中,先調(diào)用createImage()方法創(chuàng)建圖片緩沖區(qū),然后得到繪制環(huán)境,即當(dāng)前圖片的畫筆;再創(chuàng)建一個(gè)用來保存驗(yàn)證碼文本的StringBuilder對(duì)象,利用for循環(huán)及以上提到的方法向圖片中畫4個(gè)字符,然后將sb對(duì)象的值賦給成員變量text,這時(shí)調(diào)用例1-8中的getText()方法就可以獲得驗(yàn)證碼文本。最后添加干擾線,再返回image對(duì)象。
(10)以上就是VerifyCode類的所有方法,現(xiàn)在我們?cè)贗mageTest類中定義一個(gè)單元測(cè)試方法fun2(),該方法的主要內(nèi)容如例1-11所示:
@Test
public void fun2() throws FileNotFoundException, IOException{
           VerifyCode vc = new VerifyCode();//創(chuàng)建VerifyCode類的對(duì)象
           BufferedImage bi = vc.getImage();//調(diào)用getImge()方法獲得一個(gè)BufferedImage對(duì)象
           VerifyCode.output(bi, new FileOutputStream("F:/驗(yàn)證碼.jpg"));//調(diào)用靜態(tài)方法output()方法將圖片保存在文件輸出流中
           System.out.println(vc.getText());//在控制臺(tái)上打印驗(yàn)證碼的文本值
}

(11)執(zhí)行fun2()方法,控制臺(tái)上打印結(jié)果如圖1-3所示:

圖1-3 驗(yàn)證碼信息
(12)由圖1-3可知,驗(yàn)證碼文本信息為“pxTy”,現(xiàn)在去F盤中找到驗(yàn)證碼.jpg,打開如圖1-4所示:

圖1-4 驗(yàn)證碼
在以后的開發(fā)中,想獲得驗(yàn)證碼就可以把VerifyCode類當(dāng)作一個(gè)幫助類,將它拷貝到自己的項(xiàng)目中然后調(diào)用相應(yīng)的方法就可以獲得驗(yàn)證碼圖片。

本文版權(quán)歸傳智播客Java培訓(xùn)學(xué)院所有,歡迎轉(zhuǎn)載,轉(zhuǎn)載請(qǐng)注明作者出處。謝謝!
作者:傳智播客Java培訓(xùn)學(xué)院
首發(fā):http://xamj520.com/javaee

0 分享到:
和我們?cè)诰€交談!