Ajax

Ajax基础

Ajax概述和实用需求

Ajax介绍
一、Ajax不是一项具体的技术,而是几门技术的综合应用。
Javascript、XHTML和CSS、DOM、XML和XMLHttpRequest。
二、Ajax核心只不过是要在javascript中调用一个叫XMLHttpRequest类,这个类可以与Web服务器使用HTTP协议进行交互,程序不通过浏览器发出请求,而是用这个特殊的JavaScript对象发送请求和接收响应。
三、XMLHttpRequest对象在网络上的俗称为Ajax对象。
四、一种不用刷新整个页面便可与服务器通讯的办法(更新网页部分数据).

Ajax的特点:

浏览器中显示一个页面后,这个页面以后一直不改变,所有的操作请求都由这个网页中的javascript代码发出,所有的结果都由javascript代码接受并增加到这个页面上,浏览器窗口中显示的网页始终都是初始的那个网页。

增强用户体验:可以在用户浏览网页的同时与服务器进行异步交互和实现网页内容的局部更新。

同步和异步交互:

  • 同步:提交请求->等待服务器处理->处理完毕返回 这个期间客户端浏览器不能干任何事
  • 异步:请求通过事件触发->服务器处理(这时浏览器仍然可以作其他事情)->处理完毕

同步是指:发送方发出数据后,等接收方发回响应以后才发下一个数据包的通讯方式。
异步是指:发送方发出数据后,不等接收方发回响应,接着发送下个数据包的通讯方式。

AJAX缺陷:

1,AJAX大量使用了Javascript和AJAX引擎,而这个取决于浏览器的支持。IE5.0及以上、Mozilla1.0、NetScape7及以上版本才支持,Mozilla虽然也支持AJAX,但是提供XMLHttpRequest的方式不一样。所以,使用AJAX的程序必须测试针对各个浏览器的兼容性。
2,AJAX更新页面内容的时候并没有刷新整个页面,因此,网页的后退功能是失效的;有的用户还经常搞不清楚现在的数据是旧的还是已经更新过的。这个就需要在明显位置提醒用户“数据已更新”。
3,对流媒体的支持没有FLASH、Java Applet好。

Ajax简单入门:获取服务器时间

开发步骤:
一、实例化Ajax对象
二、创建Http请求
三、注册readyState监听事件
四、发送http请求

//获取服务端时间
function getServerTime() {
    // 1.创建Ajax对象
    var ajax = new XMLHttpRequest();
    // 2.创建HTTP协议的请求
    ajax.open("GET", "/Ajax/01_getservertime/date2.jsp", true);
    // 3.注册reayState监听事件:onreadystatechange
    ajax.onreadystatechange = function() {
        if (ajax.readyState == 4 && ajax.status==200) {
            document.getElementById("showTime").innerHTML = ajax.responseText;
        }
    };
    // 4.发送HTTP请求
    ajax.send();
}

Ajax的浏览器兼容问题

创建XMLHttpRequest对象
Internet Explorer把XMLHttpRequest实现为一个ActiveX对象. IE7以上版本已经有有XMLHttpRequest对象.
其他浏览器(Firefox、Safari、Opera…)把它实现为一个本地的JavaScript对象。
XMLHttpRequest在不同浏览器上的实现是兼容的,所以可以用同样的方式访问XMLHttpRequest实例的属性和方法,而不论这个实例创建的方法是什么。

//创建Ajax对象
function createAjax(){
    var ajax = null;
    try {
        ajax = new XMLHttpRequest();
    } catch (e) {
        ajax = new ActiveXObject("Microsoft.XMLHTTP");
    }
    return ajax;
}

浏览器对Ajax的缓存问题

IE浏览器对Ajax请求的缓存问题,
解决方案:使用时间戳

ajax.open("get", "/Ajax/_01_hello/date.jsp?"+new Date().getTime(), true);

Ajax请求

GET请求:检查账号是否存在

JSP:

    <h3>注册邮箱</h3>
    <form action="" method="POST">
        账号:<input type="text" id="username" name="username" onblur="checkUsername();"/>
        <span id="msg"></span>
    </form>

JS:

function checkUsername() {
    //1.获取账号内容
    var usernameText = document.getElementById("username").value;
    //2.创建Ajax对象
    var ajax = createAjax();
    //3.创建HTTP协议请求
    ajax.open("GET","/checkUsername?username="+usernameText+"&"+new Date().getTime(),true);
    //4.监听readyState的监听事件
    ajax.onreadystatechange = function(){
        if(ajax.readyState==4 && ajax.status==200){
            document.getElementById("msg").innerHTML=ajax.responseText;
        }
    };
    //5.发送HTTP请求
    ajax.send();
}

Servlet:

    private List<String> names = Arrays.asList("will","lucy","lily");
    protected void service(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        System.out.println("请求过来了..............");
        resp.setContentType("text/html;charset=utf-8");
        PrintWriter out = resp.getWriter();
        
        String username = req.getParameter("username");
        if(names.contains(username)){
            out.print("亲,账号已存在!");
        }else{
            out.print("恭喜,该账号可用!");
        }
    }

POST请求:登录操作

JSP:

    <h3>登陆操作</h3>
    <form action="" method="POST">
        账号:<input type="text" id="username" name="username"/><br/>
        密码:<input type="password" id="password" name="password"/><br/>
        <button onclick="ajaxLogin();">Ajax登陆</button>
    </form>

JS:

//Ajax登陆操作
function ajaxLogin(){
    //1.获取表单数据
    var usernameText = document.getElementById("username").value;
    var passwordText = document.getElementById("password").value;
    
    //2.创建Ajax对象
    var ajax = createAjax();
    //3.创建HTTP协议请求
    ajax.open("POST","/login");
    
    //4.监听readyState的监听事件
    ajax.onreadystatechange = function(){
        if(ajax.readyState==4 && ajax.status==200){
            print("登陆成功!");
        }
    };
    /**
     * 如果用 POST 请求向服务器发送数据,需要将 "Content-Type" 的首部设置为 "application/x-www-form-urlencoded".
     * 它会告知服务器正在发送数据,并且数据已经符合URL编码了。因为后台它使用URL进行解码
     */
    ajax.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
    //5.发送HTTP请求
    var data = "username="+usernameText+"&password="+passwordText;
    ajax.send(data);
}

Servlet:

    protected void service(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        System.out.println(username+","+password);
    }

二级联动

就拿你在网上注册的时候要填个人地址,
我假设它有两个下拉列表(其实还可以有更多)
第一个下拉列表中让你选择的省,而另一个下拉列表让你
选择的是城市,当你在省的下拉列表中的选择发生改变的时候,
城市的下拉列表也应当跟着你所选择的省名称而发生改变.
这样就产生了一种联动的较果.
也就是简单的二级联动..

HTML:

    省份:
        <select id="province" onchange="proviceChange();">
            <option value='-1'>---请选择---</option>
        </select>
    城市:
        <select id="city">
            <option value='-1'>---请选择---</option>
        </select>

HTML数据格式

JS:

//加载省份数据
window.onload = function() {
    var ajax = createAjax();
    ajax.open("GET","/cascade/html?cmd=getAllProvinces");
    ajax.onreadystatechange = function(){
        if(ajax.readyState==4 && ajax.status==200){
            var provinceEl =document.getElementById("province");
            provinceEl.innerHTML+=ajax.responseText;
        }
    };
    ajax.send();
    
};
//选择的城市改变,城市也随之改变
function proviceChange(){
    //获取被选择省份的ID
    var pid = document.getElementById("province").value;
    var cityEl =document.getElementById("city");
    if(pid==-1){
        return;
    }
    var ajax = createAjax();
    ajax.open("GET","/cascade/html?cmd=getCitysByPid&pid="+pid);
    var result = "<option value='-1'>---请选择---</option>";
    ajax.onreadystatechange = function(){
        if(ajax.readyState==4 && ajax.status==200){
            cityEl.innerHTML=result+ajax.responseText;
        }
    };
    ajax.send(); 
}

Servlet:

//获取所有的省份
    protected void getAllProvinces(HttpServletRequest req,
            HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf-8");
        PrintWriter out = resp.getWriter();
        List<Province> provices = Province.getAllProvince();
        for (Province p : provices) {
            out.print("<option value='" + p.getId() + "'>" + p.getName()
                    + "</option>");
        }
    }

    //根据省份的ID获取对应省份的所有城市
    protected void getCitysByPid(HttpServletRequest req,
            HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf-8");
        PrintWriter out = resp.getWriter();
        String pid = req.getParameter("pid");
        List<City> citys = City.getCityByProvinceId(Long.valueOf(pid));
        for (City c : citys) {
            out.print("<option value='" + c.getId() + "'>" + c.getName()
                    + "</option>");
        }
    }

XML数据格式

JS:

//加载省份数据
window.onload = function() {
    var ajax = createAjax();
    ajax.open("GET", "/cascade/xml?cmd=getAllProvinces");
    ajax.onreadystatechange = function() {
        if (ajax.readyState == 4 && ajax.status == 200) {
            var provinceEl = document.getElementById("province");

            var xmlResult = ajax.responseXML;
            var datas = xmlResult.getElementsByTagName("data");
            for ( var i = 0; i < datas.length; i++) {
                var dataEl = datas[i];
                var id = dataEl.getAttribute("id");
                var text = dataEl.innerHTML;

                var optionEl = document.createElement("option");
                optionEl.value = id;
                optionEl.innerHTML = text;
                provinceEl.appendChild(optionEl);
            }

        }
    };
    ajax.send();
};
// 选择的城市改变,城市也随之改变
function proviceChange() {
    // 获取被选择省份的ID
    var pid = document.getElementById("province").value;
    var cityEl = document.getElementById("city");
    if (pid == -1) {
        return;
    }
    var ajax = createAjax();
    ajax.open("GET", "/cascade/xml?cmd=getCitysByPid&pid=" + pid);
    var result = "<option value='-1'>---请选择---</option>";
    ajax.onreadystatechange = function() {
        if (ajax.readyState == 4 && ajax.status == 200) {
            cityEl.innerHTML = result;

            var xmlResult = ajax.responseXML;
            var datas = xmlResult.getElementsByTagName("data");
            for ( var i = 0; i < datas.length; i++) {
                var dataEl = datas[i];
                var id = dataEl.getAttribute("id");
                var text = dataEl.innerHTML;
                
                var optionEl = document.createElement("option");
                optionEl.value = id;
                optionEl.innerHTML = text;
                cityEl.appendChild(optionEl);
            }
        }
    };
    ajax.send();
}

Servlet:

//获取所有的省份
    protected void getAllProvinces(HttpServletRequest req,
            HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/xml;charset=utf-8");
        PrintWriter out = resp.getWriter();
        out.print("<?xml version='1.0' encoding='utf-8' ?>");
        out.print("<datas>");
        List<Province> provices = Province.getAllProvince();
        for (Province p : provices) {
            out.print("<data id='" + p.getId() + "'>" + p.getName() + "</data>");
        }
        out.print("</datas>");
    }

    //根据省份的ID获取对应省份的所有城市
    protected void getCitysByPid(HttpServletRequest req,
            HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/xml;charset=utf-8");
        PrintWriter out = resp.getWriter();
        out.print("<?xml version='1.0' encoding='utf-8' ?>");
        out.print("<datas>");
        String pid = req.getParameter("pid");
        List<City> citys = City.getCityByProvinceId(Long.valueOf(pid));
        for (City c : citys) {
            out.print("<data id='" + c.getId() + "'>" + c.getName() + "</data>");
        }
        out.print("</datas>");
    }

发表评论

电子邮件地址不会被公开。 必填项已用 * 标注