[導(dǎo)讀]本文通過(guò)實(shí)例,介紹在做驗(yàn)證碼的時(shí)候?yàn)榱私o用戶很好的體驗(yàn),需要在原有驗(yàn)證方式基礎(chǔ)之上增加一段js,通過(guò)xmlhttp來(lái)獲取返回值,以此來(lái)驗(yàn)證是否有效。同時(shí),本例還特別適合檢驗(yàn)用戶名是否有效。  

1、我們?cè)谧鲵?yàn)證碼的時(shí)候往往由于要反作弊,驗(yàn)證有時(shí)故意加入多的干擾因素,這時(shí)驗(yàn)證碼顯示不很清楚,用戶經(jīng)常輸入錯(cuò)誤。這樣不但要重新刷新頁(yè)面,導(dǎo)致用戶沒有看清楚驗(yàn)證碼而重填而不是修改,而且如果沒有用session保存下用戶輸入的其它數(shù)據(jù)的話(如姓名),用戶剛剛輸入的內(nèi)容也不存在了,這樣給用戶造成不好的體驗(yàn)。  

2、本例在原有驗(yàn)證方式基礎(chǔ)之上增加一段js,通過(guò)xmlhttp來(lái)獲取返回值,以此來(lái)驗(yàn)證是否有效,這樣即使用戶瀏覽器不支持js,也不會(huì)影響他的正常使用了。  

3、為了防止作弊,當(dāng)用戶連接3次輸入錯(cuò)誤時(shí)則重載一下圖片,這樣也利于用戶因?yàn)閳D片上的驗(yàn)證碼辨認(rèn)不清而使其終無(wú)法輸入正確。  

4、本例還特別適合檢驗(yàn)用戶名是否有效,只要從后臺(tái)做個(gè)sql查詢,返回一個(gè)值或是xml即可。(這種例子太多  ,就在此不贅述了)。  

5、本例的優(yōu)點(diǎn)在于非常方便用戶輸入,而且減少對(duì)服務(wù)器端的請(qǐng)求,可以說(shuō)既改善用戶體驗(yàn)而且略會(huì)節(jié)省帶寬成本,但相應(yīng)地要在頁(yè)面上增加一段JavaScript代碼,在目前網(wǎng)速越來(lái)越快人們要求便捷舒適的今天,似乎我們更應(yīng)注意提供給用戶良好的使用感受。  

代碼如下:  

1、img.jsp,輸入主頁(yè)面  
<%@ page contentType="text/html; charset=GBK" language="java" import="java.sql.*" errorPage="" pageEncoding="GBK"%> 

<%
//set Chinese Char
//Cody by JarryLi@gmail.com ;
//homepage:jiarry.126.com 
request.setCharacterEncoding(
"GBK"); 
response.setCharacterEncoding(
"GBK");
response.setContentType(
"text/html; charset=GBK"); 
%> 

<html>
<head>
<title>圖片驗(yàn)證</title>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312"> 

<script src="net.js"></script>
</head>
<body> 
AJAX(無(wú)刷新及時(shí)提示)驗(yàn)證碼實(shí)例!cody by jarry 
<hr>

<%
String num=request.getParameter("num"); 

String random=(String)session.getAttribute("random"); 

String name=request.getParameter("name"); 

if(num!=null&&random!=null&&name!=null



if(num.equals(random)) 



out.println(
"<font style=\"color:green;font-weight:bold\"

恭喜您,驗(yàn)證碼輸入成功,這里是提交結(jié)果頁(yè)面,可以寫入數(shù)據(jù)庫(kù)了!
</font> 

<a href=\"img.jsp\">返回再測(cè)試</a><br>"); 

out.println(
"您的名字是:"+name); 

out.println(
"<br>"); 

out.println(
"您輸入的是:"+num); 

out.println(
"驗(yàn)證碼是:"+random); 

out.println(
"</body>"); 

return;
//javascript:history.go(-1


%> 

<script type="text/javascript">
var times=0;
function subform(){
var gtext=this.req.responseText;
var info=document.getElementById("info");
if(gtext.indexOf("validate_successful")!=-1){ 

//info.innerHTML="<font color=green>驗(yàn)證碼通過(guò)</font>"; 

document.forms[
"myform"].submit(); 

//當(dāng)?shù)玫降闹当硎竞戏ǎ瑒t驗(yàn)證碼通過(guò)。 

}
else

times
++

if(times>=3){//如果連接3次輸入錯(cuò)誤,則重載圖片,可以防止作弊和用戶看不清圖片; 

info.innerHTML
="接連3次輸入錯(cuò)誤。更新驗(yàn)證碼,請(qǐng)重新輸入"

document.forms[
"myform"].num.value=""

show(document.getElementById('random')); 

times
=0

}
else

info.innerHTML
=""+times+"次驗(yàn)證碼錯(cuò)誤,請(qǐng)注意區(qū)分大小寫 "



document.forms[
"myform"].num.select(); 





function validata(obj){ 

var enter=true

var info=document.getElementById("info"); 

var msg=""

if(obj.name.value.match(/^\s*$/g)){//如果未輸入名字,提示 

msg
+="請(qǐng)輸入您的姓名<br>";enter=false 



if(obj.num.value.match(/^\s*$/g)){//如果未輸入驗(yàn)證碼,提示 

msg
+="請(qǐng)輸入驗(yàn)證碼<br>";enter=false 



if(enter==false){ 

info.innerHTML
=msg; 

return false



var url="num.jsp?num="+obj.num.value; 

var newxmlhttp=new net.ContentLoader(url,subform,"","get",null,null); 

return false



function show(o){ 

//重載驗(yàn)證碼 

var timenow = new Date().getTime(); 

o.src
="random.jsp?d="+timenow; 

/* 

//超時(shí)執(zhí)行; 

setTimeout(function(){ 

o.src="random.jsp?d="+timenow; 



,20); 

*/ 



</script> 

<form action="img.jsp" name="myform" method="post" 

onsubmit
="return validata(this);"> 

您的姓名:
<input type="text" name="name" size=10> (為了更好地說(shuō)明此例,特加姓名一項(xiàng))<br> 

驗(yàn) 證 碼:
<input type="text" name="num" size=10 maxlength="4"> 

<img src="random.jsp" id="random" align="" valign="absmiddle" hspace="5"> 

<href="javascript:show(document.getElementById('random'))">驗(yàn)證碼看不清</a><br> 

<br> <input type="submit" value=" 提交 "><br> 

<div id=info style="color:red;padding:10px;font-size:12px;"></div> 

</form> 

</body> 

</html>

2、num.jsp,反饋xmlhttp請(qǐng)求的頁(yè)面
<%@ page contentType="text/html; charset=GBK" language="java" 

import
="java.sql.*" errorPage="" pageEncoding="GBK"%> 

<% 

//set Chinese Char 

//Cody by JarryLi@gmail.com ; 

//homepage:jiarry.126.com 

request.setCharacterEncoding(
"GBK"); 

response.setCharacterEncoding(
"GBK"); 

response.setContentType(
"text/html; charset=GBK"); 

%> 

<% 

String num=request.getParameter("num"); 

String random=(String)session.getAttribute("random"); 

if(num!=null&&random!=null



if(!num.equals(random)) 



/* 

out.println(
"<script>alert('驗(yàn)證碼錯(cuò)誤!請(qǐng)重試。')</script>"); 

out.println(
"<script>history.go(-1)</script>"); 

//response.sendRedirect("img.jsp"); 

*/ 

out.print(
"validate_failed:"+random); 



else 



//out.println("<center>驗(yàn)證成功!</center>"); 

out.print(
"validate_successful:"+random); 





%> 

3、random.jsp,生成驗(yàn)證碼圖片的頁(yè)面
<%@ page autoFlush="false" import="java.util.*,java.awt.*, 

java.awt.image.
*,com.sun.image.codec.jpeg.*,java.util.*" %> 

<

//set Chinese Char 

//Cody by JarryLi@gmail.com ; 

//homepage:jiarry.126.com 

request.setCharacterEncoding(
"GBK"); 

response.setCharacterEncoding(
"GBK"); 

response.setContentType(
"text/html; charset=GBK"); 

%> 

<% 

String chose="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"

char display[]
={'0',' ','0',' ','0',' ','0'},ran[]={'0','0','0','0'},temp; 

Random rand
=new Random(); 

for(int i=0;i<4;i++



temp
=chose.charAt(rand.nextInt(chose.length())); 

display[i
*2]=temp; 

ran[i]
=temp; 





String random=String.valueOf(display); 

session.setAttribute(
"random",String.valueOf(ran)); 

%> 

<% 

out.clear(); 

response.setContentType(
"image/jpeg"); 

response.addHeader(
"pragma","NO-cache"); 

response.addHeader(
"Cache-Control","no-cache"); 

response.addDateHeader(
"Expries",0); 

int width=80, height=30

BufferedImage image 
= new BufferedImage(width, height, 

BufferedImage.TYPE_INT_RGB); 

Graphics g 
= image.getGraphics(); 

//以下填充背景顏色 

g.setColor(Color.GREEN); 

g.fillRect(
00, width, height); 

//設(shè)置字體顏色 

g.setColor(Color.RED); 

Font font
=new Font("Arial",Font.PLAIN,20); 

g.setFont(font); 

//g.drawString(random,5,14); 

g.drawString(random,
5,20); 

g.dispose(); 

ServletOutputStream outStream 
= response.getOutputStream(); 

JPEGImageEncoder encoder 
=JPEGCodec.createJPEGEncoder(outStream); 

encoder.encode(image); 

outStream.close(); 

%> 

4、net.js,封裝好的xmlhttp對(duì)象,可以很方便的調(diào)用
/* namespacing object */ 

var net=new Object(); 



net.READY_STATE_UNINITIALIZED
=0

net.READY_STATE_LOADING
=1

net.READY_STATE_LOADED
=2

net.READY_STATE_INTERACTIVE
=3

net.READY_STATE_COMPLETE
=4

/*--- content loader object for cross-browser requests ---*/ 

net.ContentLoader
=function(url,on_load,on_error,method,params,contentType){ 

this.req=null

this.on_load=on_load; 

this.on_error=(on_error) ? on_error : this.defaultError; 

this.loadXMLDoc(url,method,params,contentType); 



net.ContentLoader.prototype.loadXMLDoc
=function(url,method,params,contentType){ 

if (!method) 



method
="GET"



if (!contentType && method=="POST"



contentType
='application/x-www-form-urlencoded'; 



if (window.XMLHttpRequest) 



this.req=new XMLHttpRequest(); 



else if (window.ActiveXObject) 



//add try catch; 

try { 

this.req = new ActiveXObject("Msxml2.XMLHTTP"); 

}
catch (e1){ 

try { 

this.req = new ActiveXObject("Microsoft.XMLHTTP"); 

catch (e2){ 





// 

//this.req=new ActiveXObject("Microsoft.XMLHTTP"); 



if (this.req) 



try 



var loader=this

this.req.onreadystatechange=function() 



net.ContentLoader.onReadyState.call(loader); 



this.req.open(method,url,true); 

if (contentType) 



this.req.setRequestHeader('Content-Type', contentType); 



this.req.send(params); 



catch (err) 



this.on_error.call(this); 







net.ContentLoader.onReadyState
=function(){ 

var req=this.req; 

var ready=req.readyState; 

if (ready==net.READY_STATE_COMPLETE){ 

var httpStatus=req.status; 

if (httpStatus==200 || httpStatus==0){ 

this.on_load.call(this); 

}
else

this.on_error.call(this); 







net.ContentLoader.prototype.defaultError
=function(){ 

alert(
"error fetching data!" 

+"\n\nreadyState:"+this.req.readyState 

+"\nstatus: "+this.req.status 

+"\nheaders: "+this.req.getAllResponseHeaders());