java驗(yàn)證碼生成的基本流程
1.驗(yàn)證碼的生成,我們能夠看到是用Graphics對(duì)象畫(huà)出來(lái)的。對(duì)象我們必須要獲得Graphics對(duì)象
1-1、Graphics對(duì)象的獲取,要通過(guò)BufferedImage獲得
<span style="font-size:18px;">int width=100;//確定框框的大小 int height=40; BufferedImage bfi =new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); Graphics g=bfi.getGraphics();//獲得Graphics對(duì)象就可以畫(huà)圖</span>
1-2、一般的驗(yàn)證碼背景框都是白色的
<span style="font-size:18px;"> //1,設(shè)置背景(白框框) g.setColor(Color.WHITE);//白色的畫(huà)筆 g.fillRect(0, 0, width, height);//畫(huà)矩形矩形框框</span>
1-3、保存數(shù)據(jù)(后臺(tái)驗(yàn)證使用)和設(shè)置字體樣式(美觀)
String str="";//保存數(shù)據(jù) Random rom=new Random(); //設(shè)置字體的大寫(xiě)與粗 g.setFont(new Font("a", Font.BOLD,20));
1-4、生成具體的數(shù)值,以及隨機(jī)生成的顏色
for(int i=0;i<4;i++){ int num=rom.nextInt(10);//生成的隨機(jī)數(shù) g.setColor(new Color(rom.nextInt(256),rom.nextInt(256), rom.nextInt(256)));//設(shè)置畫(huà)筆的顏色(隨機(jī)) g.drawString(""+num, 20*i, 20+rom.nextInt(10));//畫(huà)出線,x的位置每一之間增加20,y的坐標(biāo)以20一條線,在線上或者是線下 //PS:位置需要明確些, }
1-5、一般的數(shù)字容易被其他軟件直接識(shí)別出來(lái),為了防黑。稍微加一點(diǎn)干擾線
//畫(huà)出一些干擾線 for (int i = 0; i < 10; i++) { g.setColor(new Color(rom.nextInt(256),rom.nextInt(256), rom.nextInt(256)));//設(shè)置畫(huà)筆的顏色(隨機(jī)) g.drawLine(rom.nextInt(100),rom.nextInt(40), rom.nextInt(100), rom.nextInt(40));//位置也是隨機(jī),x,y的值不要超過(guò)矩形框框 }
1-6、銷毀Graphics對(duì)象和存儲(chǔ)圖片
<span style="white-space:pre"> </span>g.dispose();//銷毀對(duì)象 ImageIO.write(bfi, "JPEG", res.getOutputStream());//圖片用字節(jié)流 直接得到 PS::: res是Servlet里面的。
這樣驗(yàn)證碼就生成了,那我們?nèi)绾螌?dǎo)入到前臺(tái)去呢
2、具體實(shí)現(xiàn)
前臺(tái)代碼呈現(xiàn)():
<body> <h1>用戶登錄</h1><br/> 用戶名:<input type="text" name="nametext"/><br/> 密 碼:<input type="text" name="psd"/><br/> 請(qǐng)輸入驗(yàn)證碼:<input type="text"/> <img <span style="color:#ff0000;">src="/IMG/immg" </span>id="aid"/><a href="javascript:flush()" >看不清</a> </body>
src的地址來(lái)源就是從后臺(tái)發(fā)過(guò)來(lái)的。路徑是很有意思的。
2-1步驟
項(xiàng)目里面
myeclipse --> src -->new Servlet 出現(xiàn)如下:
點(diǎn)擊----》next 出現(xiàn)如下頁(yè)面:
這個(gè)配置會(huì)自動(dòng)到項(xiàng)目里面的web-INF文件夾里面web.xml。這個(gè)框框里面的值就是前臺(tái) src里面寫(xiě)的需要訪問(wèn)的路徑,----> 點(diǎn)擊完成就行了。
自動(dòng)了。生成如下界面:
在這里就可寫(xiě)之前的代碼。但是需要注意,我們必須通過(guò)覆蓋這個(gè)方法才能有效:
protected void service(HttpServletRequest req, HttpServletResponse resp)//自動(dòng)生成 輸入 <span style="font-family: Arial, Helvetica, sans-serif;">service 補(bǔ)全,自動(dòng)生成</span> throws ServletException, IOException { // TODO Auto-generated method stub super.service(req, resp); }
具體的代碼如下:
package cn.hncu.com.servlet; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.image.BufferedImage; import java.io.FileOutputStream; import java.io.IOException; import java.util.Random; import javax.imageio.ImageIO; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class Imgdemo extends HttpServlet { @Override public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { int width=100;//確定框框的大小 int height=40; BufferedImage bfi =new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); Graphics g=bfi.getGraphics();//獲得Graphics對(duì)象就可以畫(huà)圖 //1,設(shè)置背景(白框框) g.setColor(Color.WHITE);//白色的畫(huà)筆 g.fillRect(0, 0, width, height);//畫(huà)矩形矩形框框 //2,具體生成隨機(jī)數(shù) String str="";//保存數(shù)據(jù) Random rom=new Random(); //設(shè)置字體的大寫(xiě)與粗 g.setFont(new Font("a", Font.BOLD,20)); //畫(huà)出具體的圖片 for(int i=0;i<4;i++){ int num=rom.nextInt(10);//生成的隨機(jī)數(shù) g.setColor(new Color(rom.nextInt(256),rom.nextInt(256), rom.nextInt(256)));//設(shè)置畫(huà)筆的顏色(隨機(jī)) g.drawString(""+num, 20*i, 20+rom.nextInt(10));//畫(huà)出線,x的位置每一之間增加20,y的坐標(biāo)以20一條線,在線上或者是線下 //PS:位置需要明確些, } //畫(huà)出一些干擾線 for (int i = 0; i < 10; i++) { g.setColor(new Color(rom.nextInt(256),rom.nextInt(256), rom.nextInt(256)));//設(shè)置畫(huà)筆的顏色(隨機(jī)) g.drawLine(rom.nextInt(100),rom.nextInt(40), rom.nextInt(100), rom.nextInt(40));//位置也是隨機(jī),x,y的值不要超過(guò)矩形框框 } g.dispose(); ImageIO.write(bfi, "JPEG", res.getOutputStream());//圖片用字節(jié)流 直接得到 } }<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"> </span>
前臺(tái)代碼:
<%@ 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 'img.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"> --> <script type="text/javascript"> function flush(){ var text=document.getElementById("aid"); var date =new Date(); var tt=date.getTime(); text.src="/IMG/immg?"+tt; } </script> </head> <body> <h1>用戶登錄</h1><br/> 用戶名:<input type="text" name="nametext"/><br/> 密 碼:<input type="text" name="psd"/><br/> 請(qǐng)輸入驗(yàn)證碼:<input type="text"/> <img src="/IMG/immg" id="aid"/><a href="javascript:flush()" >看不清</a> </body> </html>
對(duì)于前臺(tái)代碼需要解釋一下:
當(dāng)我們的的驗(yàn)證碼傳過(guò)來(lái)看不清的時(shí)候需要刷新,而瀏覽器有自動(dòng)記憶的功能,當(dāng)沒(méi)有新的參數(shù)傳進(jìn)來(lái)的時(shí)候,瀏覽器是不會(huì)刷新的,所以我們需要手動(dòng)的去寫(xiě)一個(gè)js控制參數(shù)傳,我們知道,只有時(shí)間是不會(huì)變化的,所有我們采用時(shí)間來(lái)作為參數(shù)傳遞。
PS:自己坑了一段時(shí)間的問(wèn)題:驗(yàn)證碼的路徑問(wèn)題。前端的“/”表示 tomcat目錄,在項(xiàng)目?jī)?nèi)部,如web.xml中“/”表示該項(xiàng)目下。也就是說(shuō),他們兩個(gè)的目錄差了一層。
最后附上自己在測(cè)試的時(shí)候的代碼以及修改數(shù)字形狀的問(wèn)題,如改成2D的效果更不錯(cuò)。都有很明顯的記錄。
package cn.hncu.com; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.geom.AffineTransform; import java.awt.image.BufferedImage; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.util.Random; import javax.imageio.ImageIO; import org.junit.Test; public class Demoimg { @Test public void Test() throws Exception{ String str="9988"; int width=60; int height=30; //通過(guò)bufferedImage對(duì)象獲得Graphics對(duì)象 BufferedImage bfi=new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR); Graphics g=bfi.getGraphics(); g.drawString(str, 10,10); g.dispose();//類似于IO中的關(guān)流 ImageIO.write(bfi , "JPEG", new FileOutputStream("F:\\ex\\a.jpg")); //bfi為畫(huà)布,將畫(huà)布寫(xiě)到文件中JPEG為指定文件格式 } @Test public void Test2() throws Exception{ int width=100; int height=40; BufferedImage bfi =new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); Graphics g=bfi.getGraphics();//獲得Graphics對(duì)象就可以畫(huà)圖 //1,設(shè)置背景(白框框) g.setColor(Color.WHITE);//白色的畫(huà)筆 g.fillRect(0, 0, width, height); //2,具體生成隨機(jī)數(shù) String str="";//保存數(shù)據(jù) Random rom=new Random(); //設(shè)置字體的大寫(xiě)與粗 g.setFont(new Font("a", Font.BOLD,20)); //畫(huà)出具體的圖片 for(int i=0;i<4;i++){ int num=rom.nextInt(10);//生成的隨機(jī)數(shù) g.setColor(new Color(rom.nextInt(256),rom.nextInt(256), rom.nextInt(256)));//設(shè)置畫(huà)筆的顏色(隨機(jī)) g.drawString(""+num, 20*i, 20+rom.nextInt(10));//畫(huà)出線,x的位置每一之間增加20,y的坐標(biāo)以20一條線,在線上或者是線下 //PS:位置需要明確些, } //畫(huà)出一些干擾線 for (int i = 0; i < 10; i++) { g.setColor(new Color(rom.nextInt(256),rom.nextInt(256), rom.nextInt(256)));//設(shè)置畫(huà)筆的顏色(隨機(jī)) g.drawLine(rom.nextInt(100),rom.nextInt(40), rom.nextInt(100), rom.nextInt(40));//位置也是隨機(jī),x,y的值不要超過(guò)矩形框框 } g.dispose(); ImageIO.write(bfi, "JPEG", new FileOutputStream("F:\\ex\\b.jpg")); } //畫(huà)出可以變化的情況 //字體能夠旋轉(zhuǎn)的驗(yàn)證碼 @Test public void Test3() throws IOException{ int width=100; int height=40; BufferedImage bfi =new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); Graphics g=bfi.getGraphics(); Graphics2D g2d=(Graphics2D) g; Random rom =new Random(); g2d.setColor(Color.WHITE);//設(shè)置畫(huà)筆的顏色 g2d.fillRect(0, 0, width, height);//畫(huà)出一個(gè)白色的矩形 g2d.setFont(new Font("a", Font.BOLD, 20)); for(int i=0;i<4;i++){ int num=rom.nextInt(10); //旋轉(zhuǎn),放縮 AffineTransform aff=new AffineTransform(); //aff.rotate(Math.random(), i*18, height-20);//旋轉(zhuǎn) aff.scale(0.6+Math.random(), 0.6+Math.random());//縮放 g2d.setColor(new Color(rom.nextInt(256),rom.nextInt(256),rom.nextInt(256))); g2d.setTransform(aff); g2d.drawString(""+num, i*18, height-25); } g2d.dispose(); ImageIO.write(bfi, "JPEG", new FileOutputStream("F:\\ex\\c.jpg")); } }
以上就是關(guān)于java生成驗(yàn)證碼的基本流程,還附帶了自己親自的測(cè)試的代碼,希望這些都能幫到大家。
相關(guān)文章
基于Springboot疫苗接種行程管理系統(tǒng)的設(shè)計(jì)與實(shí)現(xiàn)
本文主要介紹了基于Springboot實(shí)現(xiàn)的疫苗接種行程管理系統(tǒng)的示例代碼,系統(tǒng)主要實(shí)現(xiàn)個(gè)人疫苗接種管理、行程管理、病史管理、風(fēng)險(xiǎn)地區(qū)管理、核酸檢測(cè)報(bào)告結(jié)果上報(bào)、疫情新聞管理等功能,需要的可以參考一下2022-03-03idea 打包的jar運(yùn)行報(bào) "XXX中沒(méi)有主清單屬性"
這篇文章主要介紹了idea 打包的jar運(yùn)行報(bào) "XXX中沒(méi)有主清單屬性",文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-03-03java ConcurrentHashMap鎖分段技術(shù)及原理詳解
這篇文章主要介紹了java ConcurrentHashMap鎖分段技術(shù)詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-07-07Java輸入輸出流復(fù)制文件所用時(shí)間對(duì)比
這篇文章主要介紹了Java輸入輸出流復(fù)制文件所用時(shí)間對(duì)比的相關(guān)資料,非常不錯(cuò),具有參考解決價(jià)值,需要的朋友可以參考下2016-08-08Java運(yùn)用設(shè)計(jì)模式中的建造者模式構(gòu)建項(xiàng)目的實(shí)例解析
這篇文章主要介紹了Java運(yùn)用設(shè)計(jì)模式中的建造者模式構(gòu)建項(xiàng)目的實(shí)例解析,建造者模式對(duì)外隱藏創(chuàng)建過(guò)程的產(chǎn)品,使用組合的方式,由指揮者來(lái)決定建造的流程,需要的朋友可以參考下2016-04-04Java面試題沖刺第十三天--數(shù)據(jù)庫(kù)(3)
這篇文章主要為大家分享了最有價(jià)值的三道數(shù)據(jù)庫(kù)面試題,涵蓋內(nèi)容全面,包括數(shù)據(jù)結(jié)構(gòu)和算法相關(guān)的題目、經(jīng)典面試編程題等,感興趣的小伙伴們可以參考一下2021-07-07詳解Java如何實(shí)現(xiàn)FP-Growth算法
學(xué)校里的實(shí)驗(yàn),要求實(shí)現(xiàn)FP-Growth算法.FP-Growth算法比Apriori算法快很多(但是卻比不上時(shí)間)在網(wǎng)上搜索后發(fā)現(xiàn)Java實(shí)現(xiàn)的FP-Growth算法很少,且大多數(shù)不太能理解):太菜.所以就自己實(shí)現(xiàn)了一下.這篇文章重點(diǎn)介紹一下我的Java實(shí)現(xiàn) ,需要的朋友可以參考下2021-06-06SpringCloud通過(guò)Nacos實(shí)現(xiàn)注冊(cè)中心與遠(yuǎn)程服務(wù)調(diào)用詳解流程
如果不滿足eureka注冊(cè)中心,那么本文記錄的Nacos是不二之選。本文主要記錄Springboot基于Nacos實(shí)現(xiàn)注冊(cè)中心以及遠(yuǎn)程服務(wù)調(diào)用2022-07-07windows下vscode+vs2019開(kāi)發(fā)JNI的示例
本文給大家普及windows下vscode+vs2019開(kāi)發(fā)JNI的示例以及各個(gè)環(huán)節(jié)的注意事項(xiàng),文章通過(guò)示例代碼圖文相結(jié)合給大家介紹的非常詳細(xì),需要的朋友可以參考下2021-06-06