Ajax的新特性
- 对于传统的JSP页面,访问后台Servlet或者数据库常需要经过通过Form表单或者其他get/post方式,等待后台/数据库相应后再跳转到新的页面。这种传输模式是典型的同步传输,即用户需要等待应用在查询后台数据时的空窗期。另外,原本的页面会被刷新,在不经过特殊处理的情况下用户原本输入的内容会丢失。用户体验感严重下降。
- Ajax可以利用异步传输的特性实现页面的局部刷新。一个典型的应用是在用户提交注册申请之前检测用户名的可用性:
Ajax的基本使用方式
本文以上述经典应用为切入点,详解Ajax的基本使用方法
HTML/JSP页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<base href="<%=request.getContextPath()+"/"%>">
<title>注册页面</title>
<script type="text/javascript">
var xhr;
function checkNC() {
var nc = document.getElementById("nc").value;
if(nc==null||nc==''){
document.getElementById("nc_span").innerText="用户名不能为空";
}else {
//发送ajax请求
//[1]创建XMLHttpRequest对象
xhr=new XMLHttpRequest();
//[2]和服务器建立连接
//xhr.open(method,url,acy,username,passward);
xhr.open("get","RegisterServlet?nc="+nc,true);
//[3]执行回调函数
xhr.onreadystatechange=process;
//[4]发送请求数据
xhr.send(null);
}
}
function process() {
//接受ajax 的响应内容
var text= xhr.responseText;
//把响应回的内容放到span中
document.getElementById("nc_span").innerText=text;
}
</script>
</head>
<body>
<h3>用户注册</h3>
<form>
<p>
用户名:<input type="text" name="nc" id="nc" onblur="checkNC()"/>
<span id="nc_span"></span>
</p>
<p>
真实姓名:<input type="text" name="uname"/>
</p>
<p>
密码:<input type="text" name="pwd"/>
</p>
<p>
描述:<input type="text" name="desc"/>
</p>
<p>
<input type="submit" value="注册"/>
</p>
</form>
</body>
</html>
关键步骤解释:
- 在Form表单中我们对用户名这一字段做两个判断。首先是非空校验,在容器失去焦点的时候调用JS代码检查空值情况。若不为空则进入Ajax传输代码段。
- 第一步,创建小黄人对象:
XMLHttpRequest对象
- 第二步,和服务器建立连接,
xhr.open(method,url,acy,username,passward);
,其中method表示使用get还是post方法传输数据,url指明访问路径,acy指明是否异步,username和password是服务器指定的用户名和密码。 - 第三步,设置回调函数。回调函数是用来处理Ajax在异步请求中返回的数据,本例中的回调函数如下:
function process() {
//接受ajax 的响应内容
var text= xhr.responseText;
//把响应回的内容放到span中
document.getElementById("nc_span").innerText=text;
}
事实上由于回调函数被指明在了Ajax的xhr.onreadystatechange
属性中,所以在Ajax返回数据的各个阶段都会被调用,Ajax返回数据的阶段分为:
[A] 请求没有发出(在调用 open() 之前)
[B] 请求已经建立但还没有发出(调用 send() 之前)
[C] 请求已经发出正在处理之中(这里通常可以从响应得到内容头部)
[D] 请求已经处理,响应中有部分数据可用,但是服务器还没有完成响应
[E] 响应已完成,可以访问服务器响应并使用它
以上五种状态分别对应xhr.readyState
参数中的[0,1,2,3,4]
所以,为了让本页面再接受到了全部的数据之后再调用方法,可以设置如下条件:
function process(){
if(xhr.readyState == 4){//200 404 500
if(xhr.status == 200){ /*响应状态码200, 404, 500...*/
//得到返回的结果
var result = xhr.responseText;
//写到指定位置
document.getElementById("namemsg").innerHTML=result;
}else{
alert("Ajax请求错误");
}}}
第四步:发送请求
由于本例中设定使用get方法发送数据,参数信息被绑定在URL中,于是,此处send方法不用再发送额外数据xhr.send(null)
Servlet页面处理与访问数据库
@WebServlet("/RegisterServlet")
public class RegisterServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=utf-8");
//[1]接受页面的数据
String nc = req.getParameter("nc");
//[2]数据的处理-->返回结果
boolean flag=false;
String exitingName="";//此处代表从数据库中查询到的相同用户名
if(exitingName.equals(nc)){
flag=true;
}
//[3]根据返回结果做出响应
PrintWriter out = resp.getWriter();
if(flag){
//证明用户名在数据库存在-->用户不可使用
out.print("用户名占用");
}else{
//证明用户名子啊数据库不存在-->用户名可用
out.print("用户名可用");
}
}
}
在servlet页面中,直接使用request对象获得相关参数,使用PrintWriter对象直接输出内容,该内容会自动返回至Ajax调用页面。