作者:傳智播客java培訓學院首發:http://www.itcast.cn/javaee
生成驗證碼圖片驗證碼是Completely Automated Public Turing test to tell Computers and Humans Apart(全自動區分計算機和人類的圖靈測試)的縮寫,是一種區分用戶是計算機還是人的公共全自動程序,可以防止:惡意破解密碼、刷票、論壇灌水、有效防止某個黑客對某一特定注冊用戶,用特定程序暴力破解方式進行不斷的登錄嘗試。實際上驗證碼是現在很多網站通行的方式,我們利用比較簡易的方式實現了這個功能。下面我們就來學習如何自動生成一個驗證碼圖片,案例的源代碼點擊此處進行下載,具體如下:
大家想必在登錄某個網站的時候都輸入過驗證碼,如圖1-1所示:
圖1-1驗證碼
下面通過一個案例來學習如何自動生成一個驗證碼圖片:(1)創建一個web應用,名稱為Example1,在該應用下的src目錄下新建一個Class類,名稱為ImageTest,主要代碼如例1-1所示:例1-1 ImageTest.java
public class ImageTest { @Testpublic void fun1() throws FileNotFoundException, IOException{ /* * 1. 創建圖片緩沖區 * 2. 設置其寬高 * 3. 得到這個圖片的繪制環境(得到畫筆) * 4. 保存起來 */ BufferedImage bi = new BufferedImage(70, 35, BufferedImage.TYPE_INT_RGB); Graphics2D g = (Graphics2D)bi.getGraphics();//得到繪制環境 g.setColor(Color.WHITE);//把環境設置為白色 g.fillRect(0, 0, 70, 35);//填充矩形!填充矩形,從0,0點開始,寬70,高35,即整個圖片,即為圖片設置背景色 g.setColor(Color.RED);//把環境設置為紅色 g.drawString("Hello", 2, 35-2);//向圖片上寫入字符串,其中2,2表示x,y軸的坐標 ImageIO.write(bi, "JPEG", new FileOutputStream("F:/xxx.jpg"));}} |
在例1-1中,首先要獲得圖片緩沖區,即BufferedImage類的一個對象,BufferedImage類的構造方法中,第一個參數和第二個參數表示圖片的長和寬,第三個參數是圖片的類型;然后獲取繪制環境,也可以理解為獲取當前圖片的畫筆,使用該對象可以設置一系列的屬性,例如圖片的背景顏色、填充形狀等。最后使用ImageIO類的write()方法將當前畫好的圖片寫到指定的輸出流中。(2)測試fun1()方法,去F盤查看生成的圖片效果如何,如圖1-2所示:
圖1-2 繪制的圖片如圖1-2所示,繪制的圖片背景色是白色,字符串“Hello”的顏色是紅色,該字符串的位置也是由我們自己設置的,可以調整。
通過以上對自動繪制圖片的了解,下面我們來完成另外一個繪制圖片的類,這個類相較于上面的ImageTest類要復雜很多,如下所示:(1)在ImageTest同包下新建一個Class類,名稱為VerifyCode,下面我們對類中的方法進行一一介紹。首先來看該類的成員變量,如例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); // 驗證碼上的文本 private String text ; |
例1-2中,成員變量w、h分別表示圖片的長和寬;成員變量r是Random類型的對象,用來生成隨機數;成員變量fontNames是列舉驗證圖片中驗證碼的字體類型;成員變量codes是列舉驗證碼的所有的可選字符;成員變量bgColor是驗證圖片的背景色;成員變量text是圖片上的驗證碼。(2)VerifyCode類的生成隨機顏色的方法,主要代碼如例1-3所示:例1-3 randomColor()方法
// 生成隨機的顏色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類型的對象,r.nextInt(int n)方法返回一個偽隨機數,它是取自此隨機數生成器序列的、在 0(包括)和指定值n(不包括)之間均勻分布的 int值。其中局部變量red、green、blue分別代表顏色的RGB的紅、綠、藍三個通道的顏色值。該方法返回的是隨機產生的顏色。(3)VerifyCode類的生成隨機字體的方法,主要代碼如例1-4所示:例1-4 randomFont()方法
// 生成隨機的字體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; //生成隨機字號, 24 ~ 28 return new Font(fontName, style, size);} |
例1-4中,r.nextInt(fontNames.length)方法是獲得一個從0到成員變量fontNames數組的長度之間的整數index,然后將這個整數當作fontNames數組的下標,找到對應的字體類型。局部變量style是隨機產生的樣式,詳情可參考例1-4中的代碼注釋,局部變量size是隨機生成的字體大小,即字號,范圍是從24~28;最后將該字體返回。(4)VerifyCode類的生成隨機的干擾線方法,主要代碼如例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++) {//生成兩個點的坐標,即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);//畫線 }} |
例1-5中,局部變量num是記錄干擾線的條數,然后創建當前圖片的畫筆Graphics2D類的對象,再利用r對象生成四個值,其中x1和x2的大小范圍在0~70之間,y1和y2的大小在0~35之間,這四個值是用來作為確定一條直線的兩個點的坐標,由于有三條干擾線,所以這里使用for循環,然后每循環一次就使用畫筆對象g2的drawLine()方法繪制一條線。(5)VerifyCode類的生成隨機字符的方法,主要代碼如例1-6所示:
// 隨機生成一個字符private char randomChar () { int index = r.nextInt(codes.length()); return codes.charAt(index);} |
例1-6中,驗證碼的所有可選字符都在字符串codes中,通過r對象的nextInt()方法獲得一個在0到codes.length范圍內的整數index,然后調用charAt(index)方法獲得指定索引的字符,并返回。(6)VerifyCode類的創建BufferedImage的方法,主要代碼如例1-7所示:
// 創建BufferedImageprivate 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中,創建BufferedImage對象的步驟與例1-1相同,最后將創建的對象返回。(7)VerifyCode類的獲得驗證碼圖片上的文本方法,主要代碼如例1-8所示:
// 返回驗證碼圖片上的文本public String getText () { return text;} |
例1-8中的text是成員變量,代表圖片上的驗證碼。該方法要在另一個方法getImage()調用之后調用,getImage()方法后面會詳解。(8)VerifyCode類的將圖片保存到指定的輸出流,主要代碼如例1-9所示:
// 保存圖片到指定的輸出流public static void output (BufferedImage image, OutputStream out) throws IOException { ImageIO.write(image, "JPEG", out);} |
例1-9中,output()方法有兩個參數,第一個參數是繪制的圖片,第二個參數是圖片將要保存的輸出流;使用ImageIO類的write()方法將image對象以JPEG的格式保存在out輸出流中。(9)VerifyCode類的得到驗證碼圖片的方法,主要代碼如例1-10所示:
// 調用這個方法得到驗證碼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); //把字母添加到sb中 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; } |
例1-10中,先調用createImage()方法創建圖片緩沖區,然后得到繪制環境,即當前圖片的畫筆;再創建一個用來保存驗證碼文本的StringBuilder對象,利用for循環及以上提到的方法向圖片中畫4個字符,然后將sb對象的值賦給成員變量text,這時調用例1-8中的getText()方法就可以獲得驗證碼文本。最后添加干擾線,再返回image對象。(10)以上就是VerifyCode類的所有方法,現在我們在ImageTest類中定義一個單元測試方法fun2(),該方法的主要內容如例1-11所示:
@Testpublic void fun2() throws FileNotFoundException, IOException{ VerifyCode vc = new VerifyCode();//創建VerifyCode類的對象 BufferedImage bi = vc.getImage();//調用getImge()方法獲得一個BufferedImage對象 VerifyCode.output(bi, new FileOutputStream("F:/驗證碼.jpg"));//調用靜態方法output()方法將圖片保存在文件輸出流中 System.out.println(vc.getText());//在控制臺上打印驗證碼的文本值} |
(11)執行fun2()方法,控制臺上打印結果如圖1-3所示:圖1-3驗證碼信息(12)由圖1-3可知,驗證碼文本信息為“pxTy”,現在去F盤中找到驗證碼.jpg,打開如圖1-4所示:圖1-4驗證碼在以后的開發中,想獲得驗證碼就可以把VerifyCode類當作一個幫助類,將它拷貝到自己的項目中然后調用相應的方法就可以獲得驗證碼圖片。
新聞熱點
疑難解答