J2EE驗(yàn)證碼圖片如何生成和點(diǎn)擊刷新驗(yàn)證碼
驗(yàn)證碼圖片生成步驟
創(chuàng)建BufferedImage對(duì)象。
獲取BufferedImage的畫筆,即調(diào)用getGraphics()方法獲取Graphics對(duì)象。
調(diào)用Graphics對(duì)象的setColor()方法和fillRect()方法設(shè)置圖片背景顏色。
調(diào)用Graphics對(duì)象的setColor()方法和drawLine()方法設(shè)置圖片干擾線。
調(diào)用BufferedImaged對(duì)象的setRGB()方法設(shè)置圖片的噪點(diǎn)。
調(diào)用Graphics對(duì)象的setColor()方法、setFont()方法和drawString()方法設(shè)置圖片驗(yàn)證碼。
因?yàn)轵?yàn)證碼的圖片的寬度和高度要根據(jù)網(wǎng)站的風(fēng)格來(lái)確定的,所以字體的大小需要根據(jù)圖片的寬度和高度來(lái)確定,用到了小小的技巧。
package util;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Random;
import javax.imageio.ImageIO;
public class Verification {
private static final String ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890";
/**
* 生成一個(gè)寬為width, 高為height, 驗(yàn)證碼為code的圖片
* @param width 圖片的寬
* @param height 圖片的高
* @param code 驗(yàn)證碼字符串
* @return 返回圖片驗(yàn)證碼
*/
public static BufferedImage getImage(int width, int height, String code){
return getImage(width, height, code, 20);
}
/**
* 生成一個(gè)寬為width, 高為height, 驗(yàn)證碼為code的圖片,圖片中干擾線的條數(shù)為lineCnt
* @param width 圖片的寬
* @param height 圖片的高
* @param code 驗(yàn)證碼字符串
* @param lineCnt 干擾線的條數(shù),建議為10條左右,可根據(jù)結(jié)果適當(dāng)調(diào)整
* @return 返回圖片驗(yàn)證碼
*/
public static BufferedImage getImage(int width, int height, String code, int lineCnt){
return createImage(width, height, code, lineCnt, 0.01);
}
/**
* 生成一個(gè)寬為width, 高為height, 驗(yàn)證碼為code的圖片,圖片中干擾線的條數(shù)為lineCnt
* 噪聲比為noiseRate,即圖片中噪音像素點(diǎn)的百分比
* @param width 圖片的寬
* @param height 圖片的高
* @param code 驗(yàn)證碼字符串
* @param lineCnt 干擾線的條數(shù),建議為10條左右,可根據(jù)結(jié)果適當(dāng)調(diào)整
* @param noiseRate 圖片中噪音像素點(diǎn)占總像素的百分比
* @return 返回圖片驗(yàn)證碼
*/
public static BufferedImage getImage(int width, int height, String code, int lineCnt, double noiseRate){
return createImage(width, height, code, lineCnt, noiseRate);
}
/**
*
* 生成一個(gè)寬為width, 高為height, 驗(yàn)證碼為code的圖片,圖片中干擾線的條數(shù)為lineCnt
* 噪聲比為noiseRate,即圖片中噪音像素點(diǎn)的百分比
* @param width 圖片的寬
* @param height 圖片的高
* @param code 驗(yàn)證碼字符串
* @param lineCnt 干擾線的條數(shù),建議為10條左右,可根據(jù)結(jié)果適當(dāng)調(diào)整
* @param noiseRate 圖片中噪音像素點(diǎn)占總像素的百分比
* @return 返回圖片驗(yàn)證碼
*/
private static BufferedImage createImage(int width, int height, String code, int lineCnt, double noiseRate){
int fontWidth = ((int)(width * 0.8)) / code.length();
int fontHeight = (int)(height * 0.7);
//為了在任意的width和height下都能生成良好的驗(yàn)證碼,
//字體的大小為fontWdith何fontHeight中的小者,
int fontSize = Math.min(fontWidth, fontHeight);
//drawString時(shí)要用到
int paddingX = (int) (width * 0.1);
int paddingY = height - (height - fontSize) / 2;
//創(chuàng)建圖像
BufferedImage buffimg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
//獲得畫筆
Graphics g = buffimg.getGraphics();
//設(shè)置畫筆的顏色
g.setColor(getRandColor(200, 255));
//然后填充一個(gè)矩形,即設(shè)置背景色
g.fillRect(0, 0, width, height);
// 設(shè)置干擾線
for (int i = 0; i < lineCnt; i++) {
//隨機(jī)獲取干擾線的起點(diǎn)和終點(diǎn)
int xs = (int)(Math.random() * width);
int ys = (int)(Math.random() * height);
int xe = (int)(Math.random() * width);
int ye = (int)(Math.random() * height);
g.setColor(getRandColor(1, 255));
g.drawLine(xs, ys, xe, ye);
}
// 添加噪點(diǎn)
int area = (int) (noiseRate * width * height);
for(int i=0; i<area; ++i){
int x = (int)(Math.random() * width);
int y = (int)(Math.random() * height);
buffimg.setRGB(x, y, (int)(Math.random() * 255));
}
//設(shè)置字體
Font font = new Font("Ravie", Font.PLAIN, fontSize);
g.setFont(font);
for(int i=0; i<code.length(); ++i){
String ch = code.substring(i, i+1);
g.setColor(getRandColor(1, 199));
g.drawString(ch, paddingX + fontWidth * i, paddingY);
}
return buffimg;
}
/**
* 獲取隨機(jī)的顏色,r,g,b的取值在L到R之間
* @param L 左區(qū)間
* @param R 右區(qū)間
* @return 返回隨機(jī)顏色值
*/
private static Color getRandColor(int L, int R){
if(L > 255)
L = 255;
if(R > 255)
R = 255;
if(L < 0)
L = 0;
if(R < 0)
R = 0;
int interval = R - L;
int r = L + (int)(Math.random() * interval);
int g = L + (int)(Math.random() * interval);
int b = L + (int)(Math.random() * interval);
return new Color(r, g, b);
}
/**
* 隨機(jī)生成若干個(gè)由大小寫字母和數(shù)字組成的字符串
* @param len 隨機(jī)生成len個(gè)字符
* @return 返回隨機(jī)生成的若干個(gè)由大小寫字母和數(shù)字組成的字符串
*/
public static String getRandCode(int len){
String code = "";
for(int i=0; i<len; ++i){
int index = (int)(Math.random() * ALPHABET.length());
code = code + ALPHABET.charAt(index);
}
return code;
}
/**
* 將圖片轉(zhuǎn)為byte數(shù)組
* @param image 圖片
* @return 返回byte數(shù)組
* @throws IOException
*/
public static byte[] getByteArray(BufferedImage image) throws IOException{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(image, "png", baos);
return baos.toByteArray();
//ByteArrayOutputStream 不需要close
}
}
使用驗(yàn)證碼圖片
在verificationCode.java這個(gè)servlet中調(diào)用上面的類生成驗(yàn)證碼圖片,然后將圖片返回給客戶端。
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session = request.getSession();
//隨機(jī)生成字符串,并寫入session
String code = Verification.getRandCode(4);
session.setAttribute("verification", code);
BufferedImage image = util.Verification.getImage(100,30, code, 5);
response.setContentType("image/png");
OutputStream out = response.getOutputStream();
out.write(util.Verification.getByteArray(image));
out.flush();
out.close();
}
在index.jsp中設(shè)置驗(yàn)證碼,用戶點(diǎn)擊驗(yàn)證碼時(shí),調(diào)用js代碼請(qǐng)求服務(wù)器得到新的驗(yàn)證碼。因?yàn)樯厦娴哪莻€(gè)生成驗(yàn)證碼的servlet會(huì)被瀏覽器緩存,所以js代碼中需要給該servlet一個(gè)隨機(jī)的參數(shù),這樣瀏覽器就會(huì)向服務(wù)器發(fā)請(qǐng)求得到新的驗(yàn)證碼,而不是去緩存中讀取。
<%@page import="util.Verification"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<script type="text/javascript">
function refreshcode(){
document.getElementById("verification").src= "/verificationCode/verificationCode?hehe="+Math.random();
}
</script>
</head>
<body>
<form action="<%=request.getContextPath()+"/checkVerification" %>" method="post">
驗(yàn)證碼:<input type="text" name="submitVerification">
<img id="verification" alt="" title="看不清點(diǎn)擊刷新驗(yàn)證碼" src="<%=request.getContextPath()+"/verificationCode" %>"
onclick="refreshcode()"><br>
<input type="submit" name="submit" value="提交">
</form>
</body>
</html>
最后是在checkVerification.java這個(gè)servlet中判斷用戶輸入的驗(yàn)證碼是否正確,為了方便用戶,驗(yàn)證碼一般都設(shè)置成大小寫不敏感,所以要先轉(zhuǎn)化為小寫字母再比對(duì)。
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session = request.getSession();
String verification = (String)session.getAttribute("verification");
String submitVerification = request.getParameter("submitVerification");
PrintWriter out = response.getWriter();
if(verification!=null && submitVerification!=null){
if(verification.toLowerCase().equals(submitVerification.toLowerCase())){
out.println("yes!!!");
}
else{
out.println("no!!!");
}
}
else{
out.println("no!!!");
}
session.removeAttribute("verification");//防止用戶重復(fù)提交表單
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
最后運(yùn)行的效果圖如下

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助。
- 分享J2EE的13種核心技術(shù)
- JDK、J2EE、J2SE、J2ME四個(gè)易混淆概念區(qū)分
- 圖解Eclipse j2ee開發(fā)環(huán)境的搭建過程
- 經(jīng)常聽朋友說(shuō)什么J2EE,終于知道點(diǎn)什么是J2EE了,汗一個(gè)
- MyEclipse5.0M1注冊(cè)碼+eclipse3.2[J2EE]
- J2EE 開發(fā)購(gòu)物網(wǎng)站 經(jīng)驗(yàn)篇 - 建表
- 實(shí)戰(zhàn) J2EE 開發(fā)購(gòu)物網(wǎng)站 - 創(chuàng)建數(shù)據(jù)庫(kù)
- J2ee 高并發(fā)情況下監(jiān)聽器實(shí)例詳解
相關(guān)文章
MyBatis使用<foreach>標(biāo)簽報(bào)錯(cuò)問題及解決
這篇文章主要介紹了MyBatis使用<foreach>標(biāo)簽報(bào)錯(cuò)問題及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-03-03
基于SpringBoot+vue實(shí)現(xiàn)前后端數(shù)據(jù)加解密
這篇文章主要給大家介紹了基于SpringBoot+vue實(shí)現(xiàn)前后端數(shù)據(jù)加解密,文中有詳細(xì)的示例代碼,具有一定的參考價(jià)值,感興趣的小伙伴可以自己動(dòng)手試一試2023-08-08
Java實(shí)現(xiàn)的文件上傳下載工具類完整實(shí)例【上傳文件自動(dòng)命名】
這篇文章主要介紹了Java實(shí)現(xiàn)的文件上傳下載工具類,結(jié)合完整實(shí)例形式分析了java針對(duì)文件上傳下載操作的相關(guān)實(shí)現(xiàn)技巧,并且針對(duì)上傳文件提供了自動(dòng)命名功能以避免文件命名重復(fù),需要的朋友可以參考下2017-11-11
java使用Filter實(shí)現(xiàn)自動(dòng)登錄的方法
這篇文章主要為大家詳細(xì)介紹了java使用Filter實(shí)現(xiàn)自動(dòng)登錄的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-04-04
mybatis-puls中的resultMap數(shù)據(jù)映射
這篇文章主要介紹了mybatis-puls中的resultMap數(shù)據(jù)映射,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08
利用spring-data-redis實(shí)現(xiàn)incr自增的操作
這篇文章主要介紹了利用spring-data-redis實(shí)現(xiàn)incr自增的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來(lái)看看吧2020-11-11

