js-day04--Ajax应用--二级联动


Ajax概述和实用需求

Ajax介绍/阿贾克斯:
一、Ajax不是一项具体的技术,而是几门技术的综合应用。
  Javascript、XHTML和CSS、DOM、XML和XMLHttpRequest。
二、Ajax核心只不过是要在javascript中调用一个叫XMLHttpRequest类,这个类可以与Web服务器使用HTTP协议进行交互,程序不通过浏览器发出请求,而是用这个特殊的JavaScript对象发送请求和接收响应。
三、XMLHttpRequest对象在网络上的俗称为Ajax对象。
四、一种不用刷新整个页面便可与服务器通讯的办法(更新网页部分数据).
-------------------------------------------------------------------------
AJAX 指异步 JavaScript 及 XML(Asynchronous JavaScript And XML)。
AJAX 是一种在 2005 年由 Google 推广开来的编程模式。
AJAX 不是一种新的编程语言,而是一种使用现有标准的新方法。
通过 AJAX,你可以创建更好、更快以及更友好的 WEB 应用程序。

Ajax的特点(看图):
浏览器中显示一个页面后,这个页面以后一直不改变,所有的操作请求都由这个网页中的javascript代码发出,所有的结果都由javascript代码接收并增加到这个页面上,浏览器窗口中显示的网页始终都是初始的那个网页。
增强用户体验:可以在用户浏览网页的同时与服务器进行异步交互和实现网页内容的局部更新
同步和异步交互:
* 同步:提交请求->等待服务器处理->处理完毕返回 这个期间客户端浏览器不能干任何事(单线程).
* 异步:请求通过事件触发->服务器处理(这时浏览器仍然可以作其他事情)->处理完毕(多线程).
同步是指:发送方发出数据后,等接收方发回响应以后才发下一个数据包的通讯方式。
异步是指:发送方发出数据后,不等接收方发回响应,接着发送下个数据包的通讯方式。
具体应用: NBA文字直播平台.

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

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

AJAX不支持跨域访问

示例代码:

//获取服务端时间,Struts2框架
public class HelloAction extends ActionSupport {

    private static final long serialVersionUID = 1L;

    public String execute() throws Exception {
        //获取服务器时间
        String time = new Date().toLocaleString();
        
        //服务端响应,对客户端输出的内容
        //Thread.sleep(2000);
        ServletActionContext.getResponse().getWriter().print(time);
        
        return NONE;
    }
}
<!-- 前端HTML代码 -->
<body>
    北京时间:<span id="time">暂无数据</span>
    <hr/>
    <input type="button" onclick="getServerTime();" value="获取服务端时间" style="background-color: orange;">
</body>
//简单的Ajax,获取服务端时间
function getServerTime(){
    //1:创建Ajax对象
    var ajax = createAjax();
    //2:创建一个新的HTTP请求(请求方式,请求URL地址,异步/同步(true/false))
    //该处加new Date().getTime()时间戳,是为了解决IE缓存问题
    ajax.open("get", "/ajax/hello/date.jsp?"+new Date().getTime(), true);
    
    //4:监听readyState改变事件,因为异步的时候,一发送Ajax请求会直接收到响应,
    //但是服务端可能还没有来得及处理信息,所以需要监听readyState事件的状态来接收服务端的响应
    //并且监听readyState事件只能放在发送Ajax请求之前
    ajax.onreadystatechange = function(){
        //当ajax.readyState == 4的时候,说明服务端已经处理好了该次的Ajax请求
        //当ajax.status == 200的时候,说明请求地址OK,即HTTP响应OK
        if(ajax.readyState == 4 && ajax.status == 200){
            //5:接收服务端响应
            var result = ajax.responseText;
            //把服务端响应写出到页面
            document.getElementById("time").innerHTML = result;
        }
    };
    //3:发送Ajax请求
    ajax.send();
    //console.debug("--------------");
}

//创建Ajax对象,处理W3C和IE6以下版本浏览器的兼容性
function createAjax(){
    var ajax = null;
    
    try {
        ajax = new XMLHttpRequest();
    } catch (e) {
        ajax = new ActiveXObject("Microsoft.XMLHTTP");
    }
    return ajax;
}

浏览器兼容和缓存问题

Ajax的问题:
  1):只接受和处理响应成功.
  2):XMLHttpRequest针对于W3C和IE7以上版本的浏览器有效.
    针对于IE6和IE6以下的版本不支持.

//创建Ajax对象,处理W3C和IE6以下版本浏览器的兼容性
function createAjax(){
    var ajax = null;
    
    try {
        ajax = new XMLHttpRequest();
    } catch (e) {
        ajax = new ActiveXObject("Microsoft.XMLHTTP");
    }
    return ajax;
}

  3):IE浏览器默认会对Ajax请求缓存.
    把请求的URL当做Map中的key,把该请求的响应作为Map的value.
    如果请求地址不变,就直接把上一次该地址的响应给客户端(不会发生新的请求).
    解决方案:使用时间戳作为资源的参数.

    //该处加new Date().getTime()时间戳,是为了解决IE缓存问题
    ajax.open("get", "/ajax/hello/date.jsp?"+new Date().getTime(), true);

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

使用Ajax发生GET请求,并传递参数.
案例:检查注册账号是否已经存在.

 

示例代码:

//判断用户名是否已经存在,Struts2框架
public class GetUsernameAction extends ActionSupport{

    private static final long serialVersionUID = 1L;

    private String username;

    public void setUsername(String username) {
        this.username = username;
    }

    //创建数组模拟数据库里面的用户名
    List<String> names = Arrays.asList("will","server","ajax");
    
    public String execute() throws Exception {
        String msg = "账号名可用";
        //判断传入的值是否存在数组中
        if(names.contains(username)){
            msg = "账号已经存在!!!";
        }
        //设置响应编码
        ServletActionContext.getResponse().setCharacterEncoding("utf-8");
        //设置响应信息
        ServletActionContext.getResponse().getWriter().print(msg);
        return NONE;
    }
}
<body>
    <h3>Ajax判断用户名是否存在</h3><br/>
    用户名:<input type="text" onblur="checkUsername();" id="username">
    <span id="msg" style="color: red"></span>
</body>
//简单的Ajax,判断输入的用户名是否可用
function checkUsername(){
    var username = document.getElementById("username").value;
    //alert(username);
    //1:创建Ajax对象
    var ajax = createAjax();
    //2:创建一个新的HTTP请求(请求方式,请求URL地址,异步/同步(true/false)(默认true))
    ajax.open("get","/ajax/getUsername.action?username="+username);
    //4:监听readystatechange的状态
    ajax.onreadystatechange = function(){
        if(ajax.readyState == 4 && ajax.status == 200){
            //5:接收服务端响应
            var result = ajax.responseText;
            document.getElementById("msg").innerHTML = result;
        }
    };
    //3:发送Ajax请求
    ajax.send();
}

//创建Ajax对象,处理W3C和IE6以下版本浏览器的兼容性
function createAjax(){
    var ajax = null;
    
    try {
        ajax = new XMLHttpRequest();
    } catch (e) {
        ajax = new ActiveXObject("Microsoft.XMLHTTP");
    }
    return ajax;
}

POST请求:登录操作

使用Ajax发生POST请求,并传递参数.
案例:使用Ajax完成登陆操作.

 示例代码:

//Ajax判断登录,Struts2框架
public class LoginAction extends ActionSupport {

    private static final long serialVersionUID = 1L;

    private String username;
    private String password;
    public void setUsername(String username) {
        this.username = username;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    
    public String execute() throws Exception {
        System.out.println(username+", "+password);
        return NONE;
    }
}
<body>
    <h3>Ajax登录操作</h3><br/>
    <form action="#" method="post" enctype="application/x-www-form-urlencoded">
        账号:<input type="text" id="username"><br/>
        密码:<input type="password" id="password"><br/>
        <input type="button" onclick="checkLogin();" value="登录">
    </form>
</body>
//简单的Ajax,登判断录
function checkLogin(){
    var username = document.getElementById("username").value;
    var password = document.getElementById("password").value
    
    //1:创建Ajax对象
    var ajax = createAjax();
    //2:创建一个新的HTTP请求(请求方式,请求URL地址,异步/同步(true/false)(默认true))
    ajax.open("post","/ajax/login.action");
    //4:监听readystate事件变化
    ajax.onreadystatechange = function(){
        if(ajax.readyState == 4 && ajax.status == 200){
            console.debug("登录成功");
        }
    };
    /*
     * 如果使用POST请求向服务端发送数据,需要将"Content-Type"的首部设置为"application/x-www-form-urlencoded"
     * 它会告知服务器正在发送数据,并且数据已经符合URL编码。因为后台它使用URL进行解码
     */
    ajax.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
    //3:发送Ajax请求(因为是POST请求,所以需要在后面添加参数)
    var data = "username="+username+"&password="+password;
    ajax.send(data);
}

//创建Ajax对象,处理W3C和IE6以下版本浏览器的兼容性
function createAjax(){
    var ajax = null;
    
    try {
        ajax = new XMLHttpRequest();
    } catch (e) {
        ajax = new ActiveXObject("Microsoft.XMLHTTP");
    }
    return ajax;
}

二级联动

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

 

使用html作为后台和前台的数据交互格式.

 示例代码:

//Ajax二级联动之HTML格式,Struts2框架
public class LinkageByHtmlAction extends ActionSupport {

    private static final long serialVersionUID = 1L;

    private Long pid;
    
    public void setPid(Long pid) {
        this.pid = pid;
    }

    //获取所有省份
    /*
     * <option value="1">四川</option>
     * <option value="2">广东</option>
     * <option value="3">陕西</option>
     */
    public String getProvinces() throws Exception{
        StringBuilder sb = new StringBuilder(200);
        //获取所有省份
        List<Province> provinces = Province.getAllProvince();
        
        for(Province p : provinces){
            sb.append("<option value='").append(p.getId()).append("'>").append(p.getName()).append("</option>");
        }
        
        //设置编码,并且打印HTML格式的信息
        ServletActionContext.getResponse().setCharacterEncoding("utf-8");
        ServletActionContext.getResponse().getWriter().print(sb);
        //System.out.println(sb);
        return NONE;
    }
    
    //获取对应id省份的城市    
    /*
     * <option value="1">广州</option>
     * <option value="2">深圳</option>
     * <option value="3">东莞</option>
     */
    public String getCitys() throws Exception{
        StringBuilder sb = new StringBuilder(200);
        //获取对应id省份的城市    
        List<City> citys = City.getCityByProvinceId(pid);
        
        for(City c : citys){
            sb.append("<option value='").append(c.getId()).append("'>").append(c.getName()).append("</option>");
        }
        //设置编码,并且打印HTML格式的信息
        ServletActionContext.getResponse().setCharacterEncoding("utf-8");
        //System.out.println(sb);
        ServletActionContext.getResponse().getWriter().print(sb);
        return NONE;
    }
}
<body>
    <h3>Ajax二级联动,HTML格式</h3><br/>
    省份:<select id="province" onchange="getCitys();"><option>请选择</option></select>
    市级:<select id="city"><option>请选择</option></select>
</body>
//简单的Ajax,二级联动,HTML格式
//获取省份
window.onload = function(){
    //页面加载完毕之后,把所有省份查询出来并显示到页面
    var ajax = createAjax();
    ajax.open("get","/linkage/html_getProvinces.action",true);
    ajax.onreadystatechange = function(){
        if(ajax.readyState == 4 && ajax.status == 200){
            var result = ajax.responseText;
            document.getElementById("province").innerHTML += result;
        }
    };
    ajax.send();
};
//获取市级,根据不同省份
function getCitys(){
    //获取省份id
    var pid = document.getElementById("province").value;
    document.getElementById("city").innerHTML = "<option>请选择</option>";
    //alert(pid);
    if(!parseInt(pid)){
        return;
    }
    var ajax = createAjax();
    ajax.open("get","/linkage/html_getCitys.action?pid="+pid,true);
    ajax.onreadystatechange = function(){
        if(ajax.readyState ==4 && ajax.status == 200){
            var result = ajax.responseText;
            document.getElementById("city").innerHTML = result;
        }
    };
    ajax.send();
}

//创建Ajax对象,处理W3C和IE6以下版本浏览器的兼容性
function createAjax(){
    var ajax = null;
    
    try {
        ajax = new XMLHttpRequest();
    } catch (e) {
        ajax = new ActiveXObject("Microsoft.XMLHTTP");
    }
    return ajax;
}

使用xml作为后台和前台的数据交互格式.
--------------------------------------------------------------------
在服务端中:把所有的数据以XML文档的结构封装起来,再响应给客户端.
在Ajax处理响应的时候: 解析响应过来的XML文档,获取其中的数据,再拼接在<option>元素中,最后把<option>元素作为<select>的儿子节点.

示例代码:

//Ajax二级联动之HTML格式,Struts2框架
public class LinkageByXMLAction extends ActionSupport{

    private static final long serialVersionUID = 1L;

    private Long pid;
    
    public void setPid(Long pid) {
        this.pid = pid;
    }

    //获取所有省份
    /*
     * <option value="1">四川</option>
     * <option value="2">广东</option>
     * <option value="3">陕西</option>
     */
    public String getProvinces() throws Exception{
        //获取所有省份
        List<Province> provinces = Province.getAllProvince();
        //把所有省份储存在内存中的Document文档中
        Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
        doc.setXmlVersion("1.0");
        Element root = doc.createElement("datas");
        doc.appendChild(root);
        
        //把省份信息写入到文档中
        for(Province p : provinces){
            Element dataEl = doc.createElement("data");
            dataEl.setAttribute("id", p.getId()+"");
            dataEl.setTextContent(p.getName());
            root.appendChild(dataEl);
        }
        
        //设置编码,并且打印HTML格式的信息
        ServletActionContext.getResponse().setCharacterEncoding("utf-8");
        //同步:把内存中的Document文档数据同步到客户端
        TransformerFactory.newInstance().newTransformer()
        .transform(new DOMSource(doc), new StreamResult(ServletActionContext.getResponse().getWriter()));

        return NONE;
    }
    
    //获取对应id省份的城市    
    /*
     * <option value="1">广州</option>
     * <option value="2">深圳</option>
     * <option value="3">东莞</option>
     */
    public String getCitys() throws Exception{
        //获取对应id省份的城市    
        List<City> citys = City.getCityByProvinceId(pid);
        //把所有市级储存在内存中的Document文档中
        Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
        doc.setXmlVersion("1.0");
        Element root = doc.createElement("datas");
        doc.appendChild(root);
        
        //把市级信息写入到文档中
        for(City c : citys){
            Element dataEl = doc.createElement("data");
            dataEl.setAttribute("id", c.getId()+"");
            dataEl.setTextContent(c.getName());
            root.appendChild(dataEl);
        }
        
        //设置编码,并且打印HTML格式的信息
        ServletActionContext.getResponse().setCharacterEncoding("utf-8");
        //同步:把内存中的Document文档数据同步到客户端
        TransformerFactory.newInstance().newTransformer()
        .transform(new DOMSource(doc), new StreamResult(ServletActionContext.getResponse().getWriter()));
        
        return NONE;
    }
}
<body>
    <h3>Ajax二级联动,XML格式</h3><br/>
    省份:<select id="province" onchange="getCitys();"><option>请选择</option></select>
    市级:<select id="city"><option>请选择</option></select>
</body>
//简单的Ajax,二级联动,XML格式
//获取省份
window.onload = function(){
    //页面加载完毕之后,把所有省份查询出来并显示到页面
    var ajax = createAjax();
    ajax.open("get","/linkage/html_getProvinces.action",true);
    ajax.onreadystatechange = function(){
        if(ajax.readyState == 4 && ajax.status == 200){
            /*
             <datas>
                 <data id ="1">四川</data>
                 <data id ="2">广东</data>
                 <data id ="3">陕西</data>
             </datas>
             */
            //服务端返回的Document对象
            var doc = ajax.responseXML;
            var datas = doc.getElementsByTagName("data");
            for (var index = 0; index < datas.length; index++) {
                var data = datas[index];
                //每一个data元素都封装到<option1>标签中
                var optionEl = document.createElement("option");
                optionEl.value = data.id
                optionEl.innerHTML = data.innerHTML;
                document.getElementById("province").appendChild(optionEl);
            }
        }
    };
    ajax.send();
};
//获取市级,根据不同省份
function getCitys(){
    //获取省份id
    var pid = document.getElementById("province").value;
    document.getElementById("city").innerHTML = "<option>请选择</option>";
    //alert(pid);
    if(!parseInt(pid)){
        return;
    }
    var ajax = createAjax();
    ajax.open("get","/linkage/html_getCitys.action?pid="+pid,true);
    ajax.onreadystatechange = function(){
        if(ajax.readyState ==4 && ajax.status == 200){
            //服务端返回的Document对象
            var doc = ajax.responseXML;
            var datas = doc.getElementsByTagName("data");
            for (var index = 0; index < datas.length; index++) {
                var data = datas[index];
                //每一个data元素都封装到<option1>标签中
                var optionEl = document.createElement("option");
                optionEl.value = data.id
                optionEl.innerHTML = data.innerHTML;
                document.getElementById("province").appendChild(optionEl);
            }
        }
    };
    ajax.send();
}

//创建Ajax对象,处理W3C和IE6以下版本浏览器的兼容性
function createAjax(){
    var ajax = null;
    
    try {
        ajax = new XMLHttpRequest();
    } catch (e) {
        ajax = new ActiveXObject("Microsoft.XMLHTTP");
    }
    return ajax;
}

今日小结

 

原文地址:https://www.cnblogs.com/Java0120/p/10285344.html