Ajax(asynchronousjavascriptandxml)非同步的javascript和xml.
是為了解決傳統的web應用程式中"發送請求-等待回應"這種模式的弊端,(瀏覽器在發送完請求後,只能等待伺服器的回應,使用者不能做其他的操作,瀏覽器發送完請求,會拋棄整個頁面,等待伺服器返回新的頁面,也就是說,瀏覽器和伺服器之間交互的數據量很大,不能做到按需獲取數據)而創建的技術,該技術的本質是:透過一個瀏覽器內建的一個物件(XmlHttpRequest)異步地向伺服器發送請求.
所謂異步指的是瀏覽器並沒有拋棄整個頁面,也就是不是透過表單提交的方式向伺服器發送數據,伺服器在處理完請求之後,返回資料給XmlHttpRequest物件,透過javascript可以取得XmlHttpRequest中的資料.然後,使用此資料更新頁面,整個過程當中,使用者不用等待伺服器的回應.
說明:網頁的非同步傳輸技術.一種不用刷新整個頁面便可與伺服器通訊的辦法,在等待網頁的傳輸過程中,用戶依然可以和系統進行交互,頁面不用刷新就可以更新內容合理的運用可以讓用戶感覺更好更方便,但也不要濫用
同步與非同步
同步是指:發送方發出資料後,等接收方發迴響應以後才發下一個資料包的通訊方式。
Eg.同步:提交請求->等待伺服器處理->處理完畢返回這個期間客戶端瀏覽器不能幹任何事非同步是指:發送方發出資料後,不等接收方發迴回應,接著發送下個資料包的通訊方式
Eg.非同步:請求透過事件觸發->伺服器處理(這時瀏覽器仍可作其他事情)->處理完畢
Ajax的重要物件XMLHttpRequest
重要的Javascript對象,透過它提起對伺服器端的請求,可以透過Javascript提起請求,如果要提起多個請求,需要多個XHR對象,請求的結果被預先定義好的方法處理
如何建立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物件的重要屬性.
responseXml:取得伺服器回應的xml數據
status:取得伺服器回傳的狀態碼(例如200)
readyState: 取得xmlHttpRequest與伺服器通訊的狀態(0、1、2、3、4,分別描述不同的狀態).
(未初始化) : 物件已建立,但是尚未初始化(尚未呼叫open方法)
(初始化) : 物件已經建立,尚未呼叫send方法
(傳送資料) : send方法已呼叫,但是目前的狀態以及http頭未知
(資料傳送中) : 已接受部分資料。
(回應結束) : 此時,可以透過responseText/responseXml取得資料了。
個人使用Ajax實現的一個應用實例
系統截圖
系統說明:
系統結構圖
展示前台頁regist.jsp
<!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 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">
使用者名稱:
</td>
<td>
<input type="text" name="username" id="username" onblur="postValidate()"/>
<span style="color:orange" id="checkMsg" > * 使用者名稱由字母、數字、底線組成.</span>
</td>
</tr>
<tr>
<td align="right">
密碼:
</td>
<td>
<input type="password" name="password" id="password">
<span style="color:orange" id="pwdMsg" > * 密碼長度6-8位元,為了安全,應避免唯一格式.</span>
</td>
</tr>
<tr>
<td align="right">
確認密碼:
</td>
<td>
<input type="password" name="repassword" id="repassword">
<span style="color:orange" id="repwdMsg" > * 確認密碼,以確保您設定密碼時沒有手誤</span>
</td>
</tr>
<tr>
<td align="right">
信箱:
</td>
<td>
<input type="text" id="email" name="email">
<span style="color:orange" id="emailMsg" > * 輸入您常用的信箱,方便我們與您聯絡.</span>
</td>
</tr>
<tr>
<td align="right">
驗證碼:
</td>
<td>
<input type="text" id="checkcode">
<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">
服務條款:
</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="同意條款並註冊"/>
</td>
</tr>
</table>
<div align="center">
Copyright (c) 2013 蘇若年( <a href="mailto:[email protected]">聯絡我們:[email protected]</a> )
corporation All Rights Reserved.
</div>
</form>
</body>
</html>
/*
建立獲取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>";
}
}
} /* 定義表格的整體寬度以及邊框樣式,並定義表格內所有文字的樣式*/
.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;
}
<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>
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:[email protected]">寄郵件</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;
}
}
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());
}
}
}