Ajax(asynchronous javascript and xml)異步的javascript和xml.
是為了解決傳統的web應用中"發送請求-等待響應"這種模式的弊端,(瀏覽器在發送完請求后,只能等待服務器的響應,用戶不能做其他的操作,瀏覽器發送完請求,會拋棄整個頁面,等待服務器返回新的頁面,也就是說,瀏覽器和服務器之間交互的數據量很大,不能做到按需獲取數據)而創建的技術,該技術的本質是:通過一個瀏覽器內置的一個對象(XmlHttpRequest)異步地向服務器發送請求.
所謂異步指的是瀏覽器並沒有拋棄整個頁面,也就是不是通過表單提交的方式向服務器發送數據,服務器在處理完請求之后,返回數據給XmlHttpRequest對象,通過javascript可以獲取XmlHttpRequest中的數據.然后,使用該數據更新頁面,整個過程當中,用戶不用等待服務器的響應.
說明:網頁的異步傳輸技術.一種不用刷新整個頁面便可與服務器通訊的辦法,在等待網頁的傳輸過程中,用戶依然可以和系統進行交互,頁面不用刷新就可以更新內容合理的運用可以讓用戶感覺更好更方便,但也不要濫用
同步與異步
同步是指:發送方發出數據后,等接收方發回響應以后才發下一個數據包的通訊方式。
Eg.同步:提交請求->等待服務器處理->處理完畢返回 這個期間客戶端瀏覽器不能干任何事異步是指:發送方發出數據后,不等接收方發回響應,接着發送下個數據包的通訊方式
Eg.異步:請求通過事件觸發->服務器處理(這時瀏覽器仍然可以作其他事情)->處理完畢
Ajax的重要對象XMLHttpRequest
重要的Javascript對象,通過它提起對服務器端的請求,可以通過Javascript提起請求,如果要提起多個請求,需要多個XHR對象,請求的結果被預先定義好的方法處理
如何創建XmlHttpRequest對象
//獲取xmlHttpRequest對象,該對象由瀏覽器實現(該實現並沒有標准化),在創建該對象時,要區分瀏覽器.
function getXmlHttpRequest(){ var xmlHttpRequest = null; if ((typeof XMLHttpRequest) != 'undefined') { //非ie瀏覽器
xmlHttpRequest = new XMLHttpRequest(); }else { //ie瀏覽器
xmlHttpRequest = new ActiveXObject('Microsoft.XMLHttp'); } return xmlHttpRequest; } 或者 function createXmlHttpRequest(){ var xmlHttpRequest = null; if(window.ActiveXObject){ xmlHttpRequest = new AvtiveXObject("Microsoft.XMLHTTP"); }else if(window.XMLHttpRequest){ xmlHttpRequest = new XMLHttpRequest(); } }
xmlHttpRequest對象的重要屬性.
responseText: 獲取服務器響應的文本數據 responseXml:獲取服務器響應的xml數據 status:獲取服務器返回的狀態碼(比如200) readyState: 獲取xmlHttpRequest與服務器通訊的狀態(0、1、2、3、4,分別描述不同的狀態). 0(未初始化) : 對象已建立,但是尚未初始化(尚未調用open方法) 1(初始化) : 對象已經建立,尚未調用send方法 2(發送數據) : send方法已調用,但是當前的狀態以及http頭未知 3(數據傳送中) : 已接受部分數據。 4 (響應結束) : 此時,可以通過responseText/responseXml獲取數據了。
xmlHttpRequest的返回數據獲取方式
從服務器端接收數據的時候,那些數據必須以瀏覽器能夠理解的格式來發送。服務器端的編程語言一般以如下 3 種格式返回數據: 1.Text(又稱Html格式) 2.XML 3.JSON
個人使用Ajax實現的一個應用實例
系統截圖
系統說明:
系統結構圖
展示前台頁regist.jsp
<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>用戶注冊</title>
<link href="css/regist.css" rel="stylesheet" type="text/css" />
<script src="js/regist_ajax.js" type="text/javascript"></script>
</head>
<body onload="getRegistRuleTxt(),getCheckcode()">
<form action="regist.do" onsubmit="return check(this);">
<table border="1" bordercolor="gray" cellpadding="6" align="center">
<tr>
<td colspan="2">
>> <font color="red">用戶注冊</font>
<font color="gray">[模塊說明:用戶名檢查、服務條款使用Ajax異步處理,驗證碼服務端生成]</font>
</td>
</tr>
<tr>
<td align="right" class="left"> 用戶名: </td>
<td width="580">
<input type="text" name="username" id="username" onblur="postValidate()" class="inpt"/> <span style="color:orange" id="checkMsg" > * 用戶名由字母、數字、下划線組成.</span>
</td>
</tr>
<tr>
<td align="right" class="left"> 密碼: </td>
<td>
<input type="password" name="password" id="password" class="inpt"> <span style="color:orange" id="pwdMsg" > * 密碼長度6-8位,為了安全,應避免唯一格式.</span>
</td>
</tr>
<tr>
<td align="right" class="left" class="inpt"> 確認密碼: </td>
<td>
<input type="password" name="repassword" id="repassword" class="inpt"> <span style="color:orange" id="repwdMsg" > * 確認密碼,以保證您設置密碼時沒有手誤</span>
</td>
</tr>
<tr>
<td align="right" class="left" class="inpt"> 郵箱: </td>
<td>
<input type="text" id="email" name="email" class="inpt"> <span style="color:orange" id="emailMsg" > * 輸入您的常用郵箱,方便我們與您取得聯系.</span>
</td>
</tr>
<tr>
<td align="right" class="left" class="inpt"> 驗證碼: </td>
<td>
<input type="text" id="checkcode" class="inpt"> <img id="ckcodeimage" src="imgsrc" style="border:solid #92CEDB 1px "> <!-- 驗證碼 -->
<a href="javascript:;" onclick="getCheckcode()">看不清,換一張</a>
<span style="color:orange" id="ckcodeMsg" > </span>
</td>
</tr>
<tr>
<td align="right" class="left"> 服務條款: </td>
<td>
<textarea rows="5" cols="48" style="margin-bottom:6px;margin-left:5px; color:gray" readonly="readonly" id="item" >
</textarea>
</td>
</tr>
<tr>
<td align="right">
</td>
<td>
<input type="submit" value="同意條款並注冊" style="width: 140px; height: 30px;"/>
</td>
</tr>
</table>
<div class="rghts" align="center"> Copyright (c) 2013 蘇若年( <a href="mailto:dennisit@163.com">聯系我們:dennisIT@163.com</a> ) corporation All Rights Reserved. </div>
</form>
</body>
</html>
異步Ajax處理js
var xmlHttpRequest = getXmlHttpRequest(); /* 創建獲取xmlHttpRequest對象的方法 */
function getXmlHttpRequest(){ var xmlHttpRequest = null; if((typeof XMLHttpRequest) != 'undefined'){ /*非IE瀏覽器創建XMLHttpRequest對象*/ xmlHttpRequest = new XMLHttpRequest(); }else{ /*IE瀏覽器創建XMLHttpRequest對象*/ xmlHttpRequest = new ActiveXObject('Microsoft.XMLHttp'); } return xmlHttpRequest; } /* 驗證碼響應事件 */
function getCheckcode(){ var codeimage = document.getElementById("ckcodeimage"); var url = "checkcode.do"; codeimage.src=addTimestamp(url); } /* 使用Ajax獲取服務條款 */
function getRegistRuleTxt(){ var item = document.getElementById("item"); var url = "rulesText.do"; //解決get方式提交時的中文編碼問題,使用encodeURI(url).true表示采用異步方式發送請求,addTimestamp(url)防止瀏覽器緩存
xmlHttpRequest.open("post",encodeURI(url),true); xmlHttpRequest.setRequestHeader("Content-Type","application/x-www-form-urlencoded"); xmlHttpRequest.onreadystatechange=function(){ if(xmlHttpRequest.readyState == 4){ if(xmlHttpRequest.status == 200){ var respText = xmlHttpRequest.responseText; item.value=respText; }else{ //系統錯誤.
item.value="system error"; } }else{ //顯示檢查中...
item.value="loading..."; } }; xmlHttpRequest.send(null); } /* 采用get方式驗證 */
function getValidate(){ var username = document.getElementById("username"); var url = "validatename.do?username=" + username.value; //解決get方式提交時的中文編碼問題,使用encodeURI(url).true表示采用異步方式發送請求,addTimestamp(url)防止瀏覽器緩存
xmlHttpRequest.open("get",encodeURI(addTimestamp(url)),true); //調用檢查返回狀態的方法
xmlHttpRequest.onreadystatechange=callback; xmlHttpRequest.send(null); } /* 采用post方式驗證 */
function postValidate(){ var username = document.getElementById("username"); var url = "validatename.do"; //true表示采用異步的方法發送請求.默認就為true,請求方式可以為get、post、put、delete
xmlHttpRequest.open('post',url,true); xmlHttpRequest.setRequestHeader("Content-Type","application/x-www-form-urlencoded"); xmlHttpRequest.onreadystatechange=callback; //如果有多個參數,采用&符號鏈接鍵值對,escape用於解決中文問題
xmlHttpRequest.send('username=' + escape(username.value)); } /* 監控狀態返回的方法 */
function callback(){ if(xmlHttpRequest.readyState == 4){ if(xmlHttpRequest.status == 200){ var respText = xmlHttpRequest.responseText; innerHtmlMsg(respText); }else{ //系統錯誤.
innerHtmlMsg("error"); } }else{ //顯示檢查中...
innerHtmlMsg("checking"); } } /* 增加時間戳,防止瀏覽器緩存,瀏覽器緩存只對get方法緩存 */
function addTimestamp(url){ if(url.indexOf("?")!=-1){ //如果有參數
return url+"×tamp=" + new Date().valueOf(); }else{ //沒有參數
return url+"?timestamp=" + new Date().valueOf(); } } function innerHtmlMsg(message){ var checkMsg = document.getElementById("checkMsg"); if(message=='exists'){ //用戶名存在
checkMsg.innerHTML= "<font color='red'>* 對不起,該用戶名已經存在.</font>"; } if(message=='noexists'){ //用戶名可以用
checkMsg.innerHTML= "<font color='green'>* 恭喜您,該用戶名可用.</font>"; } if(message=='checking'){ //系統檢查中
checkMsg.innerHTML= "<font color='#0099aa'>* 系統正在進行數據檢查...</font>"; } if(message=='error'){ //系統出錯
checkMsg.innerHTML= "<font color='red'>系統故障,請檢查網絡,或者<a href='#'>聯系我們</a></font>"; } }
頁面樣式regist.css
table { margin-top:70px; width:780px; border-collapse:collapse; /* 合並單元格之間的邊 */ font-size:14px; border:1px solid gray; /*#92CEDB*/ font:normal 12px/1.5em "宋體", Verdana, Lucida, Arial, Helvetica, sans-serif;
} /* 定義表格的整體寬度以及邊框樣式,並且定義表格內所有文字的樣式 */ .left{ font-weight:500; color:#708899; padding-right:20px; background-color: #D6ECF5;
} .inpt { border:solid #92CEDB 1px; width: 210px; height: 22px; margin-left: 10px;
} .rghts{ margin-top:20px; color:#708899; font-size:12px;
}
Web.xml中的內容
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<servlet>
<servlet-name>UserServlet</servlet-name>
<servlet-class>com.webapp.servlet.UserServlet</servlet-class>
<init-param>
<param-name>rulesfilepath</param-name>
<param-value>/txt/item.txt</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>UserServlet</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>regist.jsp</welcome-file>
</welcome-file-list>
</web-app>
驗證碼輸出工具類
package com.webapp.util; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.image.BufferedImage; import java.util.HashMap; import java.util.Map; import java.util.Random; /** * * @version : 1.1 * * @author : 蘇若年 <a href="mailto:DennisIT@163.com">發送郵件</a> * * @since : 1.0 創建時間: 2013-1-20 下午04:26:52 * * @function: TODO * */
public class CheckCodeImageUtil { private static final String[] chars = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I" }; private static final int SIZE = 4; //驗證碼上的字符個數
private static final int LINES = 4; //干擾線條數
private static final int WIDTH = 110; //驗證碼圖片寬
private static final int HEIGHT = 40; //驗證碼圖片高
private static final int FONT_SIZE = 21;//驗證碼上字體大小
/** * 產生驗證碼 * * @return Map<驗證碼的值,驗證碼的圖片> * */
public static Map<String,BufferedImage> creatCheckImage(){ //保存產生驗證碼真實值的串
StringBuffer buffer = new StringBuffer(); //自定義圖片對象
BufferedImage image = new BufferedImage(WIDTH,HEIGHT,BufferedImage.TYPE_INT_RGB); Map<String,BufferedImage> map = new HashMap<String,BufferedImage>(); Graphics graphics = image.getGraphics(); graphics.setColor(Color.WHITE); graphics.fillRect(0, 0, WIDTH, HEIGHT); Random random = new Random(); //畫隨機字符
for(int i=0; i<SIZE; i++){ //隨即獲取定義字符集中的一個元素
int rand = random.nextInt(chars.length); graphics.setColor(randomColor()); graphics.setFont(new Font(null,Font.BOLD+Font.ITALIC,FONT_SIZE)); graphics.drawString(chars[rand],(i)*WIDTH/SIZE+8 , HEIGHT/2+10); buffer.append(chars[rand]); //將生成的字符串存入到buffer中,將來獲取時用於跟用戶輸入的值比較
} //畫干擾線
for(int i=1;i<=LINES;i++){ graphics.setColor(randomColor()); graphics.drawLine(random.nextInt(WIDTH), random.nextInt(HEIGHT), random.nextInt(WIDTH),random.nextInt(HEIGHT)); if(i==LINES){ graphics.setFont(new Font(null,Font.ITALIC,13)); graphics.setColor(Color.GRAY); graphics.drawString("蘇若年工作室", 5,15); } } map.put(buffer.toString(), image); return map; } /** * 隨即產生顏色 * @return
*/
public static Color randomColor(){ Random random = new Random(); Color color = new Color(random.nextInt(256),random.nextInt(256),random.nextInt(256)); return color; } }
Servlet處理類
package com.webapp.servlet; import java.awt.image.BufferedImage; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.util.List; import java.util.Map; import java.util.Vector; import javax.imageio.ImageIO; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.sun.image.codec.jpeg.JPEGCodec; import com.sun.image.codec.jpeg.JPEGImageEncoder; import com.sun.imageio.plugins.common.ImageUtil; import com.webapp.util.CheckCodeImageUtil; public class UserServlet extends HttpServlet { private List<String> userList; private String txtFilePath = null; public void init() throws ServletException { txtFilePath = this.getInitParameter("rulesfilepath"); //模擬數據庫
userList = new Vector<String>(); userList.add("zhangsan"); userList.add("lisi"); userList.add("wangwu"); userList.add("zhaoliu"); } public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String uri = request.getRequestURI(); String path = uri.substring(uri.lastIndexOf("/"),uri.lastIndexOf(".")); if(path.equals("/validatename")){ request.setCharacterEncoding("utf-8"); response.setContentType("text/html;charset=utf-8"); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } //模擬系統產生異常測試
/*if(1==2){ throw new ServletException("some error"); }*/ String username = request.getParameter("username"); System.out.println("username:" + username); //模擬用戶數據查詢
boolean exist = userList.contains(username); if(exist){ response.getWriter().print("exists"); }else{ response.getWriter().print("noexists"); } } if(path.equals("/rulesText")){ request.setCharacterEncoding("utf-8"); response.setContentType("text/html;charset=utf-8"); String filePath = this.getServletContext().getRealPath(txtFilePath); File file = new File(filePath); StringBuffer buffer = new StringBuffer(); try { BufferedReader reader = new BufferedReader(new FileReader(file)); String tmp = ""; while((tmp = reader.readLine())!=null){ buffer.append(new String(tmp.getBytes("gbk"),"utf8")).append("\n"); } reader.close(); } catch (Exception e) { e.printStackTrace(); } if(buffer.toString().trim()!=null){ response.getWriter().print(buffer.toString()); } } if(path.equals("/checkcode")){ response.setContentType("image/jpeg"); Map<String, BufferedImage> map = CheckCodeImageUtil.creatCheckImage(); String key = (String)map.keySet().iterator().next(); request.getSession().setAttribute("code",key); System.out.println("checkcode = " + request.getSession().getAttribute("code")); BufferedImage image = map.get(key); ImageIO.write(image, "jpeg", response.getOutputStream()); } } }
轉載請注明出處:[http://www.cnblogs.com/dennisit/archive/2013/01/28/2880463.html]