昨天开始学习Ajax技术,对着书上的代码,走了不少弯路,还好也从中总结了一些经验,首先我们来看看这个程序。
建立一个jsp文件“index.jsp”,body部分我们先把表格表单画出来
<body style="margin: 0px;">
<form action="" method="post" name="form1">
<table width="509" height="352" border="0" align="center"
cellpadding="0" cellspacing="0" background="images/bg.gif">
<tr>
<td height="54"></td>
</tr>
<tr>
<td height="253" valign="top">
<div style="position: absolute;">
<table width="100%" height="250" border="0" cellspacing="0"
cellpadding="0">
<tr>
<td width="30%" height="54" align="right" style="color: #8e6723"><b>用户名:</b></td>
<td width="45%"><input type="text" name="username"
id="username" size="32"></td>
<td width="25%"><img src="images/checkBt.jpg" width="104"
height="23" style="cursor: pointer;"
onclick="checkUser(form1.username);"></td>
</tr>
<tr>
<td height="51" align="right" style="color: #8e6723"><b>密码:</b></td>
<td><input name="pwd1" type="password" id="pwd1" size="35"></td>
<td rowspan="2"><div id="toolTip"></div></td>
</tr>
<tr>
<td height="56" align="right" style="color: #8e6723"><b> 确认密码:</b></td>
<td><input name="pwd2" type="password" id="pwd2" size="35"></td>
</tr>
<tr>
<td height="55" align="right" style="color: #8e6723"><b>E-mail:</b></td>
<td colspan="2"><input name="email" type="text" id="email"
size="45"></td>
</tr>
<tr>
<td colspan="2" align="center"><input type="image"
name="imageField" src="images/registerBt.jpg"></td>
</tr>
</table>
</div>
</td>
</tr>
</table>
</form>
</body>
图片部分是自己在源码拷贝来的文件,这部分没什么问题无非是表格表单的基础,有一点需要注意,那个鼠标放到“检查用户名”那个按钮(实际是个image图片)的时候变成手的那个代码,在IE7之前style=”cursor: hand;”,在IE7之后用的事style=”cursor: pointer;”而这个pointer好像是现在的传统,不知道兼不兼容IE7之前的,因为没有装IE7以下的版本索性也懒得测试了,以后自行百度。表格表单构建完成后我们开始写其他的,我们顺着思路写,我们在点击那个“检查用户名”的时候,会触发一个js函数,这里我们直接先写头部去
function checkUser(username) {
if (username.value == "") {
alert("请输入用户名!");
username.focus();
return;
} else {
createRequest("checkUser.jsp?user=" + username.value);
}
}
这里我要说一下,写JS和CSS最好用其他编译器写,因为eclipse你直接写是没有自动的代码补全的,像我这种喜欢写错单词的,真的伤,最后还是靠单步调试找到错误的。推荐用HBuilder写,写完以后复制过来,有强大的编译器就要用上,上文的表格表单布局应该也可以用Dreamweaver代替,手写那些宽度还有高度真的有点伤,还不容易对齐,高效的开发才是我们所需要的。好像Dreamweaver是可以拖拽来布局的,具体我还没试,这次就这样写了,下次再有表格表单我再尝试可视化的操作方式。
这里检测输入的用户名是否为空,js里面没有equal方法用”==”来判断,如果为空就弹出窗口提示(弹窗我总喜欢写成alter,估计是上学期写sql修改语句留下的毛病,所以我才说一定要用其他带补全和提示的编辑器来写js和css),如果不为空那么我们就要判断这个用户名有没有被注册了。
跟着代码走,然后跳转到createRequest这个function了,所以我们头部继续加这个js函数
function createRequest(url) {
http_request = false;
if (window.XMLHttpRequest) { // 非ie浏览器
http_request = new XMLHttpRequest(); //创建XMLHttpRequest对象
} else if (window.ActiveXObject) { //IE浏览器不同版本的实例化
try {
http_request = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
// TODO: handle exception
try {
http_request = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {
// TODO: handle exception
}
}
}
if (!http_request) {
alert("不能创建XMLRequst对象实例!");
return false;
}
http_request.onreadystatechange = getResult; //为XMLHttpRequst对象指定一个返回结果处理函数
http_request.open("GET", url, true); //创建和服务器的连接
http_request.send(null); //向服务器发送请求
}
js里面单引号和双引号是一样的,根据个人习惯来,我就最外面用双引号,通过XMLHttpRequest对象,Ajax可以像桌面应用程序一样只同服务器进行数据层面的交换,不用每次都刷新页面,也不用每次都把数据交给服务器来处理,比如我们在百度输入一个关键字,然后搜索框下面产生了很多联想,那个就是Ajax,这样减轻了服务器的负担也加快了响应速度。
我们把函数这样写的好处是不用考虑浏览器的兼容性,都能new一个XMLHttpRequest对象。
我们实例化对象以后,继续写,以上是套路,既然我们调用了返回结果处理函数,我们就来写这个函数,要注意getResult是不能添加小括号以及指定参数的,不过可以使用匿名类,例如http_request.onreadystatechange = function(){
getResult(“添加的函数”);
}`
其实js是可以不用再语句最后加分号的,只是习惯这样写,看起来也舒服,加不加都正确,养成良好的书写习惯。
开始写返回结果处理函数
function getResult() {
if (http_request.readyState == 4) { //判断请求是否完成
if (http_request.status == 200) { //判断返回服务器的HTTP码是否表示成功
document.getElementById("toolTip").innerHTML = http_request.responseText; //把提示内容赋值到定义好的div中
document.getElementById("toolTip").style.display = "block" //显示提示框
} else {
alert("您所请求的页面有误");
}
}
}
我们一开始在checkUser这个js函数的最后一句是跳转到createRequest函数处理的,并且参数是在checkUser这个jsp页面处理以后返回来的一个参数,我们这个demo没有连接数据库来验证用户名是否存在,而是直接在另一个jsp页面里面放一些用户名,然后对比有没有存在。
我们来写这个jsp页面,新建一个jsp页面“checkUser.jsp”
<%@page import="java.util.Arrays"%>
<%@ page language="java" contentType="text/html; charset=GB18030"
pageEncoding="GB18030"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=GB18030">
<title>Insert title here</title>
</head>
<body>
<%
String[] userList={"明日科技","mr","mrsoft","wgh"};//存放已有的用户名
String user = new String(request.getParameter("user").getBytes("ISO-8859-1"),"GB18030"); //request转码
Arrays.sort(userList); //升序排序
int result = Arrays.binarySearch(userList,user);//二分法查找
if(result > -1){
out.println("很抱歉,该用户已被注册");
}else{
out.println("恭喜,可以注册");
}
%>
</body>
</html>
因为request传递的数据是以ISO-8859-1编码过来的,我们这里直接用String来转码转成本jsp页面的GB18030,不然会乱码。
然后我们print出来的字符串是回应道了getRequest函数里面,在判断请求状态以后Result方法里把回应过来的字符串设置到一个叫toolTip的div,然后把这个div设置成可见,就提示出了
那我们就要开始写这个div的样式表了,这是个ID选择器(ID选择器只能使用一次)
<style type="text/css">
<!--
#toolTip {
position: absolute; /*设置为绝对定位 */
left: 331px; /*设置左边距*/
top: 39px; /*设置顶边距 */
width: 98px; /*设置宽度 */
height: 48px; /*设置高度 */
padding-top: 45px; /*设置文字与顶边的距离*/
padding-left: 25px; /*设置文字与左边的距离 */
padding-right: 25px; /*设置文字与右边的距离*/
z-index: 1;
display: none; /*设置默认不显示 */
color: red; /*设置文字的颜色*/
background-image: url(images/tooltip.jpg);
}
-->
</style>
这里要注意,我犯了一个很低级的错误css的注释我用了//,但是要记住//是给java和js用的,css用的是/* */。所以我才说一定要换个编译器写js和css高效而且不容易出错,就算出错也有提示。另外你百度到的方法说改eclipse里面的Preferences的editor的content assist 的auto activation triggers效果也是最多提示一些java代码到了css里面那些标签他也没有提示了,而且百度那个方法相当无语,还导入导出弄几遍,其实直接替换成.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ就好了。这个方法没什么作用,eclipse应该是有插件的,我也懒得装了,myeclipse听说这方面支持都装好了,但是目前还不想换编译器,就多学几个编译器吧。
到这里我们这个Ajax实例是写完了,下面开始学调试,一开始百度“eclipse调试JSP页面”结果出来的答案都不理想,后来索性用chrome来调试了,很多浏览器都能调试,火狐的调试好像很好,不过目前只装chrome,chrome的开发者工具是英文的调成夜间界面相当nice。首先我们在eclipse把刚才的程序跑一遍,目的是把程序run在tomcat里面,然后我们复制eclipse帮我们部署到服务器上的url到chrome打开
f12进开发者模式,选source。因为我确定是js函数出错,我直接在调用的第一个function打了个断点(双击第九行,高亮显示断点打上去了),在用户名输入”mr”点击检查,然后开始执行程序了,run到这一行的时候就开始暂停了,如图
然后就是跟eclipse调试java程序一样了,f10下一个函数,f11是进入函数体内部,看到右边的scope了么,所有的参数以及对象变化在那里都看得到,但是数据太多头疼,我们在watch里面点加号然后像我一样输入你要看的具体数据我就想看看toolTip.style.dispaly的状态还有toolTip.innerHTML有没有给我赋值(检测用户名的div显示与否和显示的字符串)还有http_Request对象有没有赋值成功,每次输入一个你要看的数据你再点一下外面然后再点下添加输入下一个,还有联想功能特别好用,这个和eclipse的调试模式一样,你鼠标移到你要看的对象上,就会悬浮出来该对象的数据,只是watch更加有目的性。
查了半天果然,是我js写错了,readyState这个状态属性少写了一个字母,倒腾半天,不过还是有收获,起码用熟了debug还有知道了以后写css还有js用其他编译器。