今天讲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
培训是高花费,学生对培训机构要求高、对老师语言表达能力要求高是正常的不能再正常的事
情,这没什么不对的。一个拙嘴笨腮的培训讲师,但非有点良心,也会觉着干培训这钱拿着问
心有愧吧,当然这是从理论上讲,现在这社会,恐怕有这良心的人不多。