今天講Ajax,還是那天試講的年輕人,他叫王興魁。
回顧一下上次說過的內容:
A New Approach to Web Pllication XML
Asynchronized javascript and xml
對錶單數據的校驗不需要打開新的頁面或是提交整個頁面數據
不刷新頁面動態修改頁面內容,減少用戶的等待時間。
只是從服務器端獲取需要的數據,而不是一次獲取所有的數據。
一個校驗用戶名的實例:
一個文本框,一個按鈕(檢驗用戶名是否存在)
<body>
<form action="Classic" method="POST">
<input type="text" id="name">
<input type="submit" value="校驗" >
</form>
</body>
public class Classic extends HttpServlet
{
protected void doPost
{
response.setContentType("text/html;charset=gbk");
response.setHeader("Cache-Control","no-cache");
PrintWriter out = response.getWriter() ;
String name = request.getParameter("name");
if("wangxingkui".equals(name))
{
out.println("存在");
}
else
{
out.println("不存在");
}
out.println("<a href='Classic.html'>返回Classic.html</a>");
}
};
如果是採用ajax的話,html頁面應該這麼寫:
<body>
<input type="text" id="name">
<input type="button" id="submit" οnclick="check()">
<script type="text/javascript">
var xmlhttp;
function check()
{
if(window.XMLHttpRequest)//這個if分支是用來處理非IE瀏覽器的。
{
xmlhttp = new XMLHttpRequest();
if(xmlhttp.overrideMimeType)//需要覆蓋MimeType
{
xmlhttp.overrideMimeType("text/xml");
}
}
if(window.ActiveXObject)//這個if邏輯分支是用來處理IE瀏覽器的。
{
var microsoft = ['Microsoft.XMLHTTP','MSXML2.XMLHTTP',
'MSXML2.XMLHTTP.5.0','MSXML2.XMLHTTP.4.0',
'MSXML2.XMLHTTP.3.0'];
for(var i=0 ; i<microsoft.length; i++)
{
try
{
//嘗試建立xmlhttp對象
xmlhttp=new ActiveXObject(microsoft[i]);
break ;
}
catch(e)
{
}
}
}
if(xmlhttp)
{
var username = document.getElementById("name").value;
//得到文本框中的用戶名的value!
xmlhttp.onreadystatechange = callback ;
//給xmlhttp對象設置回調方法
xmlhttp.open("GET","AJAX?name=" + username,true); //爲了和服務器建立一個連接
//其實open方法共有5個參數:第一個參數,指定和服務器之間數據交互的方式
//第二個參數是url,第三個是設置xmlhttp是否用異步方式實現,如果是false的話,
//就是同步方式,不會再去調用callback方法,
//xmlhttp.open("POST","AJAX",true);採用post方式的open方法
//xmlhttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
//如果是是post方式提交的話,還必須設置xmlhttp對象的請求頭!
xmlhttp.send(null); //發送數據
//xmlhttp.send("name=" + username);如果是post提交的話,在send中不能再寫null了,
//而是要拼接好你要傳送過去的信息,然後再send過去。
}
else
{
alert("建立xmlhttprequest失敗!");
}
}
function callback()
{
//服務器端數據都發過來的時候,readyState值爲4
if(xmlhttp.readyState == 4)
{
if(xmlhttp.status == 200)
{
//服務器以純文本的方式返回數據,數據賦給text變量。
var text = xmlhttp.responseText ;
alert(text) ;
}
}
}
</script>
</body>
Servlet則做少許改動即可:
public class Classic extends HttpServlet
{
protected void doPost
{
response.setContentType("text/html;charset=gbk");
response.setHeader("Cache-Control","no-cache");
PrintWriter out = response.getWriter() ;
String name = request.getParameter("name");
if("wangxingkui".equals(name))
{
out.println("存在");
}
else
{
out.println("不存在");
}
}
};
AJAX應用的5個步驟:
1、建立XMLHttpRequest對象
2、設置回調函數(服務器端消息回來後用這個函數做相應處理)
3、使用open方法建立連接
4、send方法發送數據
5、在回調函數中針對不同響應狀態進行相應的處理。
還有不同瀏覽器創建XMLHttpRequest對象的方式不同
設置onreadystatechange需要注意
GET和POST方式提交時候send和open方法需要注意的區別
如何得知服務器的處理結束返回(在callback中處理)
返回的數據類型可以是純文本也可以是xml類型(responseText和responseXML)
================================================================
XMLHttpRequest的一個特殊性的安全問題:不能夠跨域訪問。
IE:訪問跨域頁面時會給出提示,用戶確認後可以訪問
FireFox或其他:不允許訪問跨域頁面。
解決方法實例:通過一種代理方式(讓服務器端代理去訪問url信息,然後返回給客戶端)
//判斷這個url地址是否是同域上的
function convertURL(url)
{
//如果是http://開頭的話,我們認爲是跨域訪問
if(url.substring(0,7) == "http://")
{
return "Proxy?url" + url ;//然後將url轉爲代理
}
return url ;
}
然後在服務器端
public class Proxy extends HttpServlet
{
protected void doPost()
{
String url = request.getParameter("url");
URL connect = new URL(url) ;
BufferedReader reader =
new BufferedReader(new InputStreamReader(connect.openStream()));
String line ;
PrintWriter out = response.getWriter() ;
while((line = reader.readLine())!=null)
{
out.println(line) ;
}
}
}
================================================================================
使用GET和POST兩種方式完成一個校驗電子郵件地址的小程序
符合條件的電子郵件應滿足一下規則
包含@
以.com .net .cn .org .edu結尾
以xml的格式send數據
服務器端解析的主要方式:
BufferedReader r = request.getReader();
上述問題的答案:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title></title>
</head>
<body>
<input type="text" id="email"/>
<input type="button" value="校驗" οnclick="check()"/>
<script type="text/javascript">
function check(){
var myxmlhttp = new MyXMLHttpRequest();
var email = document.getElementById("email").value;
myxmlhttp.send("POST","AJAX","<email>" + email + "</email>",mycallback);
}
function mycallback(responsetext){
alert(responsetext);
}
var MyXMLHttpRequest = function(){
if(window.XMLHttpRequest){
this.xmlhttp = new XMLHttpRequest();
if(this.xmlhttp.overrideMimeType){
this.xmlhttp.overrideMimeType("tex/xml");
}
} else if(window.ActiveXObject){
var microsoft = ['Micosoft.XMLHTTP','MSXML2.XMLHTTP'
,'MSXML2.XMLHTTP.5.0','MSXML2.XMLHTTP.4.0'
,'MSXML2.XMLHTTP.3.0'];
for(var i=0; i<microsoft.length; i++){
try{
this.xmlhttp = new ActiveXObject(microsoft[i]);
break;
} catch(e){
}
}
} else{
this.xmlhttp = null;
}
}
MyXMLHttpRequest.prototype.send = function(method,url,data,usercallback){
var xmlhttp = this.xmlhttp;
this.xmlhttp.onreadystatechange = function(){
if(xmlhttp.readyState == 4){
if(xmlhttp.status == 200){
usercallback(xmlhttp.responseText);
}
}
};
this.xmlhttp.open(method,url,true);
if(method == "POST"){
this.xmlhttp
.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
}
this.xmlhttp.send(data);
}
</script>
</body>
</html>
/**
* Created by IntelliJ IDEA.
* User: Administrator
* Date: 2007-3-10
* Time: 10:46:30
* To change this template use File | Settings | File Templates.
*/
import java.io.PrintWriter;
import java.io.BufferedReader;
public class AJAX extends javax.servlet.http.HttpServlet {
protected void doPost(javax.servlet.http.HttpServletRequest request,
javax.servlet.http.HttpServletResponse response)
throws javax.servlet.ServletException, java.io.IOException
{
response.setContentType("text/html;charset=GB2312");
response.setHeader("Cache-Control","no-cache");
BufferedReader reader = request.getReader();
PrintWriter out = response.getWriter();
String line = reader.readLine();
String email = line.substring(6,line.indexOf("</"));
//String email = request.getParameter("email");
if(email != null){
if(email.indexOf("@") > 0 &&
(email.endsWith(".com") || email.endsWith(".net")
|| email.endsWith(".cn") || email.endsWith(".edu")
|| email.endsWith(".org"))){
out.println("email符合要求");
} else{
out.println("email不符合要求");
}
} else{
out.println("email不符合要求");
}
}
protected void doGet(javax.servlet.http.HttpServletRequest request,
javax.servlet.http.HttpServletResponse response)
throws javax.servlet.ServletException, java.io.IOException {
doPost(request,response);
}
}
=============================================================================
DOM(文檔對象模型)是表示和處理HTML或XML文檔各元素的應用程序接口(API)。
HTML的DOM和XML的DOM在API接口上基本一致,使用差別不大,但本質上有區別。
HTML的DOM是一個內存對象樹,在瀏覽器中只保存一份,HTML的DOM修改HTML的內容會直接反應
到瀏覽器中;而XML的DOM則可以創建多個,每個可以對應一個XML文件。
<html>
<head><title>yuan</title></head>
<body οnlοad="show()">
<input type="text" />
<div>Hello</div>
<script type="text/javascript">
function show()
{
//返回html的根節點這一層的所有子節點
//var htmlnodes = document.childNodes[1];
var nodes = document.body.childNodes ; //遍歷body標籤體中的所有節點。
for(var i=0 ; i< nodes.length ; i ++)
{
var node = nodes[i];
alert("NodeName:"+node.nodeName+"NodeValue:"+node.nodeType);
}
}
</script>
</body>
</html>
==================================================
如果不想讓提示信息用提示框的形式出現,而是直接出現在頁面裏面的話,可以在頁面中設置一個
div層,然後在相應的callback方法 中寫四行代碼如下:
<div id="message"></div>
var text = xmlhttp.responseText ;
var div = document.getElementById("message")
var textnode=document.createTextNode(text);
div.appendChild(textnode);
還可以這麼來:
var text = xmlhttp.responseText ;
var div = document.getElementById("message")
div.innerHTML = text ;
//這也是可以的!
======================================================
聯動菜單:
服務器端的Servlet:
String year = request.getParameter("year");
String city = request.getParameter("city");
String number = (String)yearCityNumberMap.get(year+"&"+city);
//init方法中將hashMap中設置好數值
yearCityNumberMap.put("2007&beijing","150");
……………………………………………………………………………………………………
客戶端的html:
<select id="year" οnchange="updateList()">
<option value="">Select One</option>
<option value="2006">2006</option>
<option value="2007">2007</option>
</select>
<select id="city" οnchange="updateList()">
<option value="">Select One</option>
<option value="beijing">beijing</option>
<option value="shanghai">shanghai</option>
</select>
<select id="number"></select> //這個下拉框的內容是根據前兩個動態生成的。
腳本中的關鍵代碼:
<script type="text/javascript">
function show()
{
document.getElementById("year").value
}
function callback(responseText)
{
clear();
var optionnode = document.createElement("option");
var text = document.createTextNode(responseText);
optionnode.appendChild(text);
var selectnode = document.getElementById("number");
selectnode.appendChild(optionnode);
}
function clear()
{
var selectnode = document.getElementById("number");
var nodes = document.getElementById("number").childNodes ;
while(nodes.length)
{
//每次移除掉一個select子節點
selectnode.recoveChild(nodes[0]);
}
}
</script>
==============================
聯動菜單的真實源代碼:
服務器端:
/**
* Created by IntelliJ IDEA.
* User: xingxing
* Date: 2007-3-9
* Time: 23:10:03
* To change this template use File | Settings | File Templates.
*/
import java.io.PrintWriter;
import java.util.HashMap;
public class List extends javax.servlet.http.HttpServlet {
HashMap yearCityNumberMap = new HashMap();
protected void doPost(javax.servlet.http.HttpServletRequest request,
javax.servlet.http.HttpServletResponse response)
throws javax.servlet.ServletException, java.io.IOException
{
response.setContentType("text/html;charset=GB2312");
response.setHeader("Cache-Contorl","no-cache");
PrintWriter out = response.getWriter();
String year = request.getParameter("year");
String city = request.getParameter("city");
System.out.println(year+"&"+city);
String number = (String) yearCityNumberMap.get(year+"&"+city);
out.println(number);
}
protected void doGet(javax.servlet.http.HttpServletRequest request,
javax.servlet.http.HttpServletResponse response)
throws javax.servlet.ServletException, java.io.IOException
{
doPost(request,response);
}
public void init(javax.servlet.ServletConfig servletConfig)
throws javax.servlet.ServletException
{
System.out.println("init");
yearCityNumberMap.put("2007&beijing","150");
yearCityNumberMap.put("2006&beijing","145");
yearCityNumberMap.put("2007&shanghai","140");
yearCityNumberMap.put("2006&shanghai","135");
//初始化數據
//數據庫應用
}
}
客戶端:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title></title>
</head>
<body>
年份
<select id="year" οnchange="updateList()">
<option value="">Select One</option>
<option value="2007">2007</option>
<option value="2006">2006</option>
</select>
城市
<select id="city" οnchange="updateList()">
<option value="">Select One</option>
<option value="beijing">beijing</option>
<option value="shanghai">shanghai</option>
</select>
人口
<select id="number"></select>
萬
<script type="text/javascript">
var xmlhttp;
function updateList(){
if(window.XMLHttpRequest){
xmlhttp = new XMLHttpRequest();
if(window.overrideMimeType){
xmlhttp.overrideMimeType('text/xml');
}
} else{
var microsoft = ['Microsoft.XMLHTTP','MSXML2.XMLHTTP',
'MSXML2.XMLHTTP.5.0','MSXML2.XMLHTTP.4.0','MSXML2.XMLHTTP.3.0'];
for(var i=0; i<microsoft.length; i++){
try{
xmlhttp = new ActiveXObject(microsoft[i]);
break;
}catch(e){
}
}
}
if(xmlhttp == null ){
alert("建立XMLHttpRequest對象失敗");
} else{
xmlhttp.open("POST","List",true);
xmlhttp.onreadystatechange = callback;
xmlhttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
var year = document.getElementById("year").value;
var city = document.getElementById("city").value;
if(year != "" && city != ""){
xmlhttp.send("year=" + year + "&city=" + city);
} else{
clear();
}
}
}
function callback(){
if(xmlhttp.readyState == 4){
if(xmlhttp.status == 200){
var number = xmlhttp.responseText;
clear();
var optionNode = document.createElement("option");
optionNode.appendChild(document.createTextNode(number));
document.getElementById("number").appendChild(optionNode);
}
}
}
function clear(){
var number = document.getElementById("number");
while(number.childNodes.length > 0) {
number.removeChild(number.childNodes[0]);
}
}
</script>
</body>
</html>
====================================================================
如果返回的響應內容不是文本形式而是XML形式的話,需要客戶端裏面使用DOM來解析。
比如:
function mycallback(responseXML)
{
var docum = responseXML ;
var message = docum.getElementsByTagName("message");
var text = message[0].firstChildnodeValue;
}
DOM與XML
在處理XML文檔中兩個節點之間的空格時,IE和以Firefox爲代表的其他瀏覽器在實現上並不相同。
其中IE會忽略掉兩個節點中的空格內容,而FireFox則會將這些空格也當作是一個一個的節點。
//針對FireFox類的瀏覽器去除XML文檔中兩個節點間的空格
function removeWhitespace(xml)
{
var loopIndex;
for (loopIndex = 0; loopIndex < xml.childNodes.length;loopIndex++) {
var currentNode = xml.childNodes[loopIndex];
//當節點是Element類型時,則遞歸調用這個方法,移除該節點的子節點間的空格
if (currentNode.nodeType == 1) {
removeWhitespace(currentNode);
}
//當節點是Text類型且節點內容是一個或多個空格時,則將此節點移除。
if (((/^/s+$/.test(currentNode.nodeValue))) &&(currentNode.nodeType == 3)) {
xml.removeChild(xml.childNodes[loopIndex--]);
}
}
}
----------------------------------------------------------
舉個例子說明一下:
<books>
<book>
<user>wang</user>
</book>
</books>
如果是IE處理的話books的childnodes就只有book,book的childnodes就只有user
如果是火狐的話,根節點是book,下面有很多的節點(其中包括book和許多空格和回車組成的節點)
所以如果是火狐瀏覽器處理的話,必須得考慮這個空格和回車符的處理問題,必須將它們忽略掉。
===========================================================================
DOM與XML
使用過DOM4j的人可能都知道可以利用其中的XPATH方式直接獲取任意深度的一個節點。
在IE6.0及其以後版本中我們可以使用同樣的方式來訪問任意深度的XML數據,這給XML數據的
解析操作帶來了便利。
但是在FireFox等瀏覽器中,則是使用了DOM標準的XPATH處理方式,沒有IE這麼簡單的方式。
//獲得第一個book節點中的第一個author節點
var anode = xmlDoc.selectSingleNode("book/author")
//獲得第一個book節點中的第一個author節點的文本內容
var author = xmlDoc.selectSingleNode("book/author/text()").nodeValue
//獲得第一個book節點中的第一個包含age屬性的author節點
var author = xmlDoc.selectSingleNode("book/author[@age]")
//獲得所有book節點下的author節點
var author = xmlDoc.selectNodes(“book/author")
===============================================================
封裝XPATH方法,解決IE與其他瀏覽器之間的不同
/**
* 封裝selectSingleNode方法,返回滿足XPATH表達式的第一個節點
* @paran xmldoc 表示要查找的XML文檔
* @param sXPath XPATH表達式
*/
function selectSingleNode(xmldoc,sXPath){
//如果瀏覽器是IE
if(window.ActiveXObject){
//使用IE的XPATH方式獲得節點
return xmldoc.selectSingleNode(sXPath);
} else{
//FireFox類瀏覽器的處理方式
var oEvaluator = new XPathEvaluator();
if(oEvaluator != null){
var oResult = oEvaluator.evaluate(sXPath,xmldoc,null,
XPathResult.FIRST_ORDERED_NODE_TYPE, null);
return oResult.singleNodeValue;
} else{
return null;
}
}
}
/**
* 封裝selectNodes方法,以數組方式返回滿足XPATH表達式的所有節點
* @paran xmldoc 表示要查找的XML文檔
* @param sXPath XPATH表達式
*/
function selectNodes(xmldoc,sXPath){
//如果瀏覽器是IE
if(window.ActiveXObject){
//使用IE的XPATH方式獲得節點
return xmldoc.selectNodes(sXPath);
} else{
//FireFox類瀏覽器的處理方式
var oEvaluator = new XPathEvaluator();
if(oEvaluator != null){
var oResult = oEvaluator.evaluate(sXPath,xmldoc,null,
XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);
var nodes = new Array;
var node;
while(node=oResult.iterateNext()){
nodes.push(node);
}
return nodes;
} else{
return null;
}
}
}
===============================================================
IE與其他瀏覽器還可以新建xml文檔對象或裝載xml文檔對象。
封裝方法如下:
/**
* 封裝裝載XML的方法,並返回XML文檔的根節點。
* @param flag true時參數xml表示xml文檔的名稱;false時參數xml是一個字符串,其內容是一個xml文檔
* @param xml 根據flag參數的不同表示xml文檔的名稱或一個xml文檔的字符串表示
* @param fload 表示xml文檔裝載完成時調用的方法,可以爲null
*/
function loadXML(flag,xml,fload){
var xmlDoc;
//針對IE瀏覽器
if(window.ActiveXObject){
var aVersions = ["Microsoft.XmlDom",
"MSXML2.DOMDocument.5.0","MSXML2.DOMDocument.4.0",
"MSXML2.DOMDocument.3.0","MSXML2.DOMDocument"];
for (var i = 0; i < aVersions.length; i++) {
try {
//建立xml對象
var xmlDoc = new ActiveXObject(aVersions[i]);
break;
} catch (oError) {
}
}
if(xmlDoc != null){
xmlDoc.onreadystatechange = function(){
//文檔裝載完成時
if(xmlDoc.readyState == 4){
//文檔裝載完成後做相關處理
if(fload != null){
fload(xmlDoc);
}
}
}
//根據XML文檔名稱裝載
if(flag == true){
xmlDoc.load(xml);
} else{
//根據表示XML文檔的字符串裝載
xmlDoc.loadXML(xml);
}
//返回XML文檔的根節點。
return xmlDoc.documentElement;
}
} else{
//針對非IE瀏覽器
if(document.implementation && document.implementation.createDocument){
/*
第一個參數表示XML文檔使用的namespace的URL地址
第二個參數表示要被建立的XML文檔的根節點名稱
第三個參數表示要建立的文檔類型
這裏我們要裝載一個已有的XML文檔,所以首先建立一個空文檔,因此使用下面的方式
*/
xmlDoc = document.implementation.createDocument("","",null);
if(xmlDoc != null){
xmlDoc.onload = function(){
//文檔裝載完成後做相關處理
if(fload != null){
fload(xmlDoc);
}
}
//根據XML文檔名稱裝載
if(flag == true){
xmlDoc.load(xml);
} else{
//根據表示XML文檔的字符串裝載
var oParser = new DOMParser();
xmlDoc = oParser.parseFromString(xml,"text/xml");
}
//返回XML文檔的根節點。
return xmlDoc.documentElement;
}
}
}
return null;
}
===================================================================
firefox中處理XPath是如何去做的:
//xmldoc是通過XMLHttpRequest獲取的響應XML數據,內容如上面所示
var xmldoc = xhr.responseXML
//FireFox中需要使用XPathEvaluator對象來獲取指定path的XML數據
var oEvaluator = new XPathEvaluator();
//定義XPATH的表達式,這裏還是獲取book節點下的author節點
var sXPath = "book/author";
/*
evaluate方法用於獲取指定path的XML,共有五個輸入參數:
(1)XPATH的表達式
(2)XML文檔對象
(3)用於解析那namespace的方法
(4)evaluate方法返回類型,共十種,這裏給出常用的幾種,其餘可參考《JavaScript權威指南》
(JavaScript The Definitive Guide)
1) XPathResult.ORDERED_NODE_ITERATOR_TYPE返回的XPathResult對象中包含的是Node節點集合,
節點順序和文檔中的順序相同。可以在while循環中通過XPathResult對象的iterateNext方法依次
獲得所有節點。此種方式不允許在遞歸獲取所有節點的過程中修改文檔內容。
2) XPathResult.ORDERED_NODE_SNAPSHOT_TYPE返回的XPathResult對象中包含的是Node節點集合,
節點順序和文檔中的順序相同。此時XPathResult對象中的snapshotLength屬性表示返回的節點個數,
可以在for循環中通過XPathResult對象的snapshotItem(index)方法依次獲得所有節點。此種方式由
於得到的是一個snapshot(鏡像),因此文檔內容的變化不會影響到循環獲取節點。
3) XPathResult.FIRST_ORDERED_NODE_TYPE 類似於IE中的selectSingleNode方法的效果,返回符合
XPATH路徑的第一個節點,可通過XPathResult對象的singleNodeValue屬性獲得這個節點。
4) XPathResult.STRING_TYPE返回符合XPATH路徑的第一個節點,並在XPathResult對象的stringValue
屬性中保存這個節點的文本信息,對於上面的示例XML,則會返回”wang”。
5) 存儲根據指定path獲取到的XML節點,應爲XPathResult類型對象,如果null,則通過evaluate返回一個
新的XPathResult類型對象。
*/
//這裏使用XPathResult.ORDERED_NODE_ITERATOR_TYPE的方式獲得相應節點
var oResult = oEvaluator.evaluate(sXPath, xmldoc,null,
XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);
if (oResult != null) {
var oElement;
//使用while循環,通過iterateNext方法獲得所有匹配的節點
while (oElement = oResult.iterateNext()) {
//顯示當前節點的文本內容
alert(oElement.firstChild.nodeValue);
}
}
==========================================================================================
一個ajax實現的簡單學生管理系統:
服務器端:
import java.io.*;
import java.util.Random;
import javax.servlet.*;
import javax.servlet.http.*;
public class StudentListServlet extends HttpServlet {
protected void addStudent(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//Store the object in the database
String uniqueID = storeStudent();
//Create the response XML
StringBuffer xml = new StringBuffer("<result><uniqueID>");
xml.append(uniqueID);
xml.append("</uniqueID>");
xml.append("<status>1</status>");
xml.append("</result>");
//數據庫操作
//Send the response back to the browser
sendResponse(response, xml.toString());
}
protected void deleteStudent(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String id = request.getParameter("id");
/* Assume that a call is made to delete the employee from the database */
//Create the response XML
StringBuffer xml = new StringBuffer("<result>");
xml.append("<status>1</status>");
xml.append("</result>");
//數據庫操作
//Send the response back to the browser
sendResponse(response, xml.toString());
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String action = request.getParameter("action");
if(action.equals("add")) {
addStudent(request, response);
}
else if(action.equals("delete")) {
deleteStudent(request, response);
}
}
private String storeStudent() {
/* Assume that the employee is saved to a database and the
* database creates a unique ID. Return the unique ID to the
* calling method. In this case, make up a unique ID.
*/
String uniqueID = "";
Random randomizer = new Random(System.currentTimeMillis());
for(int i = 0; i < 8; i++) {
uniqueID += randomizer.nextInt(9);
}
return uniqueID;
}
private void sendResponse(HttpServletResponse response, String responseText)
throws IOException {
response.setContentType("text/xml");
response.getWriter().write(responseText);
}
}
客戶端:
基本工作流程:add按鈕點擊後,創建xm1httpRequest,然後從輸入框裏面將信息取出來,用xmlhttpRequest
將信息發給服務器,然後服務器操作數據庫,返回響應;如果成功的話,動態生成列表,列表中的每一行信息還要
附加好一個刪除按鈕,每個刪除按鈕還要附帶一個onclick事件!這些都是要用dom創建節點的方式來做。
如果失敗的話,就好辦了,只需要返回個錯誤信息到客戶端就可以了。
如果刪除一個用戶的話,前面創建列表的時候每個刪除按鈕都對應着delete方法,方法裏面還是先創建
xmlhttprequest,然後發送信息(只需要傳送id給服務器端就可以了),服務器根據id信息去刪除,要麼
成功,要麼失敗;成功的話,用html的dom將child節點remove掉(不需要像上面設置button那些麻煩事情了),
失敗的話,比成功的時候簡單多了,還是一樣,返回個信息給客戶端就ok了
代碼:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Employee List</title>
<script type="text/javascript">
var xmlHttp;
var name;
var number;
var classname;
var action;
var deleteID;
var EMP_PREFIX = "emp-";
function createXMLHttpRequest() {
if(window.XMLHttpRequest){
xmlHttp = new XMLHttpRequest();
if(window.overrideMimeType){
xmlHttp.overrideMimeType('text/xml');
}
} else{
var microsoft = ['Microsoft.XMLHTTP','MSXML2.XMLHTTP',
'MSXML2.XMLHTTP.5.0','MSXML2.XMLHTTP.4.0','MSXML2.XMLHTTP.3.0'];
for(var i=0; i<microsoft.length; i++){
try{
xmlHttp = new ActiveXObject(microsoft[i]);
break;
}catch(e){
}
}
}
}
function addStudent() {
name = document.getElementById("name").value;
number = document.getElementById("number").value;
classname = document.getElementById("classname").value;
action = "add";
if(name == "" || number == "" || classname == "") {
return;
}
var url = "StudentListServlet?"
+ createAddQueryString(name, number, classname, "add")
+ "&ts=" + new Date().getTime();
createXMLHttpRequest();
xmlHttp.onreadystatechange = handleAddStateChange;
xmlHttp.open("GET", url, true);
xmlHttp.send(null);
}
function createAddQueryString(name, title, department, action) {
var queryString = "name=" + name
+ "&number=" + number
+ "&classname=" + classname
+ "&action=" + action;
return queryString;
}
//接收響應的時候
function handleAddStateChange() {
if(xmlHttp.readyState == 4) {
if(xmlHttp.status == 200) {
updateStudentList();//添加數據
clearInputBoxes();//清除輸入框!
}
else {
alert("Error while adding employee.");
}
}
}
function clearInputBoxes() {
document.getElementById("name").value = "";
document.getElementById("number").value = "";
document.getElementById("classname").value = "";
}
function deleteStudent(id) {
deleteID = id;
var url = "StudentListServlet?"
+ "action=delete"
+ "&id=" + id
+ "&ts=" + new Date().getTime();
createXMLHttpRequest();
xmlHttp.onreadystatechange = handleDeleteStateChange;
xmlHttp.open("GET", url, true);
xmlHttp.send(null);
}
function updateStudentList() {
var responseXML = xmlHttp.responseXML;
//看status是否滿足條件
var status = responseXML.getElementsByTagName("status").item(0).firstChild.nodeValue;
status = parseInt(status);
if(status != 1) {
return;
}
//下面開始建表了
var row = document.createElement("tr");
var uniqueID = responseXML.getElementsByTagName("uniqueID")[0].firstChild.nodeValue;
row.setAttribute("id", EMP_PREFIX + uniqueID);
//每次都新建一個td,然後將內容放進去。
row.appendChild(createCellWithText(name));
row.appendChild(createCellWithText(number));
row.appendChild(createCellWithText(classname));
//這部分是創建button!
var deleteButton = document.createElement("input");
deleteButton.setAttribute("type", "button");
deleteButton.setAttribute("value", "刪除");
deleteButton.onclick = function () { deleteStudent(uniqueID); };
//這個onclick屬性在IE中無法通過setAttribute的方式設置屬性!!!
var cell = document.createElement("td");
cell.appendChild(deleteButton);
row.appendChild(cell);
document.getElementById("studentList").appendChild(row);
updateEmployeeListVisibility();
}
function createCellWithText(text) {
var cell = document.createElement("td");
cell.appendChild(document.createTextNode(text));
return cell;
}
function handleDeleteStateChange() {
if(xmlHttp.readyState == 4) {
if(xmlHttp.status == 200) {
deleteEmployeeFromList();
}
else {
alert("Error while deleting employee.");
}
}
}
function deleteEmployeeFromList() {
var status = xmlHttp.responseXML.getElementsByTagName("status")
.item(0).firstChild.nodeValue;
status = parseInt(status);
if(status != 1) {
return;
}//判斷服務器端是否真的已經將數據處理完了。
//根據ID找到節點,然後刪除!
var rowToDelete = document.getElementById(EMP_PREFIX + deleteID);
var employeeList = document.getElementById("studentList");
employeeList.removeChild(rowToDelete);
updateEmployeeListVisibility();
}
function updateEmployeeListVisibility() {
var employeeList = document.getElementById("studentList");
if(employeeList.childNodes.length > 0) {
document.getElementById("studentListSpan").style.display = "";
}
else {
document.getElementById("studentListSpan").style.display = "none";
}
}
</script>
</head>
<body>
<h1>學生管理系統</h1>
<table width="80%" border="0">
<tr>
<td>姓名: <input type="text" id="name"/></td>
<td>學號: <input type="text" id="number"/></td>
<td>班級: <input type="text" id="classname"/></td>
</tr>
</table>
<input type="button" value="增加" οnclick="addStudent()"/>
<span id="studentListSpan" style="display:none;">
<h2>學生:</h2>
<table border="1" width="80%">
<tbody id="studentList"></tbody>
</table>
</span>
</body>
</html>
================================================================
ajax還可以實現那種服務器和客戶端自動定時交互的功能。比如隔多長時間自動從服務器端
獲取某可能頻繁改變的數據,然後通過不刷新頁面的方式來實現改變客戶端數據的效果。
下面的代碼涉及了ajax中的樣式設置的細節,比如setTimeout方法就是一個典型例子
timeoutid = setTimeout(show,1000); 每隔1000ms運行一次show方法,返回的
timeoutid傳給clearTimeout就可以停止
這種定時的功能!
代碼如下:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title></title>
</head>
<body οnlοad="show()">
當前股票指數:<span id="level"></span>
<input type="button" value="stop refresh" id="stop" οnclick="stop()"/>
<script type="text/javascript">
var timeoutid;
function show(){
var myxmlhttp = new MyXMLHttpRequest();
myxmlhttp.send("POST","Refresh","",mycallback);
timeoutid = setTimeout(show,1000);
}
function mycallback(responsetext){
var divnode = document.getElementById("level");
if(responsetext - 0 > 2500){
divnode.style.backgroundColor = "red";
}else{
divnode.style.backgroundColor = "yellow";
}
divnode.innerHTML = responsetext;
}
var MyXMLHttpRequest = function(){
if(window.XMLHttpRequest){
this.xmlhttp = new XMLHttpRequest();
if(this.xmlhttp.overrideMimeType){
this.xmlhttp.overrideMimeType("tex/xml");
}
} else if(window.ActiveXObject){
var microsoft = ['Micosoft.XMLHTTP','MSXML2.XMLHTTP'
,'MSXML2.XMLHTTP.5.0','MSXML2.XMLHTTP.4.0'
,'MSXML2.XMLHTTP.3.0'];
for(var i=0; i<microsoft.length; i++){
try{
this.xmlhttp = new ActiveXObject(microsoft[i]);
break;
} catch(e){
}
}
} else{
this.xmlhttp = null;
}
}
MyXMLHttpRequest.prototype.send =
function(method,url,data,usercallback)
{
var xmlhttp = this.xmlhttp;
this.xmlhttp.onreadystatechange = function(){
if(xmlhttp.readyState == 4){
if(xmlhttp.status == 200){
usercallback(xmlhttp.responseText);
}
}
};
this.xmlhttp.open(method,url,true);
if(method == "POST"){
this.xmlhttp.setRequestHeader("Content-Type",
"application/x-www-form-urlencoded");
}
this.xmlhttp.send(data);
}
function stop(){
clearTimeout(timeoutid);
}
</script>
</body>
</html>
=============================================================
由於自己DOM和javascript等並不是很明白,所以今天挺糊塗的,不過王興魁這小夥子,
真的挺猛的,培訓的老師就該像這個樣子纔對。老師不僅僅是要技術或是項目非常非常的
牛,最重要的一點是如果想兼職當培訓講師的話,語言表達能力是非常非常重要的,若是光
依仗着技術和經驗,但是嘴皮子不靈光的話,這樣的兼職講師,不可能會受學生的歡迎,IT
培訓是高花費,學生對培訓機構要求高、對老師語言表達能力要求高是正常的不能再正常的事
情,這沒什麼不對的。一個拙嘴笨腮的培訓講師,但非有點良心,也會覺着幹培訓這錢拿着問
心有愧吧,當然這是從理論上講,現在這社會,恐怕有這良心的人不多。