AJAX

1、概述
2、XMLHttpRequest 对象
3、AJAX 异步实现步骤
4、使用 Ajax 计算 BMI
5、AJAX 联合 json 使用
6、FormData 对象

概述

1、AJAX 是用来做局部刷新的。局部刷新使用的核心对象是异步对象(XMLHttpRequest)。这个异步对象是存在浏览器内存中的 ,使用 javascript 语法创建和使用 XMLHttpRequest 对象。AJAX 是一种在无需重新加载整个网页的情况下,能够更新部分页面内容的新方法。
2、ajax:Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)。
Asynchronous:异步。
JavaScript:javascript脚本,在浏览器中执行。
xml:一种数据格式
3、ajax 是一种做局部刷新的新方法,不是一种语言。ajax 包含的技术主要有 javascript、dom、css、xml等等。核心是 javascript 和 xml :
javascript:负责创建异步对象, 发送请求, 更新页面的 dom 对象。 ajax 请求需要服务器端的数据。
xml:网络中的传输的数据格式。

全局刷新和局部刷新
  • 全局刷新
    整个浏览器被新的数据覆盖。 在网络中传输大量的数据。 浏览器需要加载,渲染页面。
    1、必须由浏览器亲自向服务端发送请求协议包。
    2、这个行为导致服务端直接将【响应包】发送到浏览器内存中。
    3、这个行为导致浏览器内存中原有内容被覆盖掉。
    4、这个行为导致浏览器在展示数据时候,只有响应数据可以展示。
  • 局部刷新
    在浏览器器的内部,发起请求,获取数据,改变页面中的部分内容。其余的页面无需加载和渲染。 网络中数据传输量少, 给用户的感受好。(浏览器在展示数据时,此时在窗口既可以看到本次的响应数据,同时又可以看到浏览器内存中原有数据。)
    1、不能由浏览器发送请求给服务端。
    2、浏览器委托浏览器内存中一个脚本对象代替浏览器发送请求。
    3、这个行为导致导致服务端直接将【响应包】发送脚本对象内存中。
    4、这个行为导致脚本对象内容被覆盖掉,但是此时浏览器内存中绝大部分内容没有收 到任何影响。
    5、这个行为导致浏览器在展示数据时候,同时展示原有数据和响应数据。
异步请求对象
  • 概述
    1、在局部刷新,需要创建一个对象,代替浏览器发起请求的行为,这个对象存在内存中。 代替浏览器发起请求并接收响应数据。这个对象叫做异步请求对象。
    2、全局刷新是同步行为,局部刷新是异步行为(浏览器数据没有全部更新)。这个异步对象用于在后台与服务器交换数据,XMLHttpRequest 就是我们说的异步对象。
  • XMLHttpRequest 对象的作用
    1、在不重新加载页面的情况下更新网页。
    2、在页面已加载后向服务器请求数据。
    3、在页面已加载后从服务器接收数据。

所有现代浏览器 (IE7+、Firefox、Chrome、Safari 以及 Opera) 都内建了 XMLHttpRequest 对象。通过一行简单的 JavaScript 代码,我们就可以创建 XMLHttpRequest 对象。
var xmlhttp = new XMLHttpRequest();
AJAX 中的核心对象就是 XMLHttpRequest。

XMLHttpRequest 对象

常用属性
属性 说明
onprogress 分成上传和下载两种情况,下载的 progress 事件属于 XMLHttpRequest 对象;上传的 progress 事件属于 XMLHttpRequest.upload 对象。可以设置文件上传或者下载的进度处理事件
ontimeout HTTP请求超时事件触发器
onreadystatechange 状态改变事件触发器,每个状态改变都会触发这个事件触发器
readyState 数值,代表 XMLHttpRequest 的5个状态
responseText 服务器的响应,字符串
responseXML 服务器的响应,XML DOM 对象
status 服务器返回的 HTTP 状态码
timeout 设置 HTTP 请求的时限,单位为 ms,超过时限自动停止 HTTP 请求
abort() 停止当前请求
getResponseHeader(header) 返回指定响应头的字符串值
常用方法
方法 说明
abort() 停止当前请求
getAllResponseHeaders() 将 HTTP 请求的所有响应头作为键/值对返回
getResponseHeader(header) 返回指定响应头的字符串值
open(method, URL, asynFlag, userName, passWord) 建立对服务器的请求,method 参数是 HTTP 请求方法,URL参数可以是相对或绝对 URL。该方法还有3个可选参数。asynFlag:是否非同步标记,userName:用户名,passWord:密码
setResquestHeader(header, value) 把指定请求报头设置为所提供的值,此方法必须在 open() 方法和 send() 之间调用。如果多次对同一个请求头赋值,只会生成一个合并了多个值的请求头。
send(content) 向服务器发送请求(空字符串必须是 null)

AJAX 异步实现步骤

1、创建异步对象

var xmlHttp = new XMLHttpRequest();

2、给异步对象绑定事件(onreadystatechange)

(1)、当异步对象发起请求,获取了数据都会触发这个事件。这个事件需要指定一个函数, 在函数中处理状态的变化。
(2)、当请求被发送到服务器时,我们需要执行一些基于响应的任务。每当 readyState 改变时,就会触发 onreadystatechange 事件。此事件可以指定一个处理函数 function。
(3)、通过判断 XMLHttpReqeust 对象的状态,获取服务端返回的数据。 语法:

xmlHttp.onreadystatechange = function() {
	if( xmlHttp.readyState == 4 && xmlHttp.status == 200) {
		//处理服务器返回数据
	}
}
3、初始化异步请求对象

(1)、初始化请求参数,方法:open(method,url,async)
xmlHttp.open(请求方式get|post, "服务器端的访问地址", 同步|异步请求(默认是true,异步请求))
(2)、参数说明:
method:请求的类型(GET 或 POST)(使用 post 时必须加上这段,会自动附加请求报头
xmlHttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
url:服务器的 servlet 地址
async:true(异步)或 false(同步)(默认true)
异步:使用异步对象发起请求后,不用等待数据处理完毕,就可以执行其它的操作(send 之后的代码可以在数据处理前执行)。
同步:异步对象必须处理完成请求,从服务器端获取数据后,才能执行 send 之后的代码。任意时刻只能执行一个异步请求。(某一个时刻,浏览器只能委托一个异步请求对象发送请求,必须等待请求处理完成。浏览器委托异步请求对象工作期间,浏览器处于等待状态。不能执行其他命令。不推荐使用。)
(3)、例如:
xmlHttp.open(“get”,”http:192.168.1.20:8080/myweb/query?name=zs&pwd=123”,true);

4、使用异步对象发送请求

xmlHttp.send()

5、接收服务器响应的数据

(1)、如需获得来自服务器的响应,使用 XMLHttpRequest 对象的 responseText 或 responseXML 属性。
responseText:获得字符串形式的响应数据。
responseXML:获得 XML 形式的响应数据。
(2)、使用例子:xmlHttp.responseText
访问地址: 使用get方式传递参数
http://localhost:8080/course_myajax/bmiPrint?name=李四&w=82&h=1.8

  • 例子
xmlHttp.onreadystatechange= function(){
	处理请求的状态变化。
	if(xmlHttp.readyState == 4 && xmlHttp.status== 200 ) {
	//可以处理服务器端的数据,更新当前页面
	var data = xmlHttp.responseText;
	document.getElementById("name").innerText= data;
	}
}
XMLHttpRequest 三个重要属性

下面是 XMLHttpRequest 对象的三个重要的属性。

  • onreadystatechange 属性
    一个 js 函数名 或 直接定义函数,每当 readyState 属性改变时,就会调用该函数。
  • readyState 属性
    存有 XMLHttpRequest 的状态。从0到4发生变化。
    0:(请求未初始化)创建异步请求对象。var xmlHttp = new XMLHttpRequest();
    1:(服务器连接已建立)初始化异步请求对象。xmlHttp.open(请求方式,请求地址,true);
    2:(请求已接收)异步对象发送请求。xmlHttp.send();
    3:(请求处理中)异步对象接收应答数据,从服务端返回数据。XMLHttpRequest 内部处理(注意3是异步对象内部使用, 获取了原始的数据。)。
    4:(请求已完成,且响应已就绪)异步请求对象已经将数据解析完毕。此时开发人员才能处理数据(更新当前页面)。
  • status 属性:
    表示网络请求的状况的(200、404、500),这里需要的是当 status==200 时,表示网络请求是成功的。
回调

当请求的状态变化时,异步对象会自动调用 onreadystatechange 事件对应的函数。

使用 Ajax 计算 BMI

  • web.xml:
    <servlet>
        <servlet-name>BmiServlet</servlet-name>
        <servlet-class>com.aaa.ajax.BmiServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>BmiServlet</servlet-name>
        <url-pattern>/bmi</url-pattern>
    </servlet-mapping>
  • BmiServlet.java
package com.aaa.ajax;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

public class BmiServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String height = request.getParameter("height");
        String weight = request.getParameter("weight");

        float h = Float.parseFloat(height);
        float w = Float.parseFloat(weight);
        //计算bmi
        float bmi = w / (h * h);
        String msg;
        if (bmi < 18.5){
            msg = "您比较瘦";
        } else if (bmi > 18.5 && bmi <= 23.9){
            msg = "正常";
        } else if (bmi > 23.9 && bmi <= 27) {
            msg = "您偏于肥胖";
        } else {
            msg = "您属于肥胖";
        }
        msg = "您的BMI值是" + bmi + "," + msg;

        //响应 ajax 需要的数据,使用 HttpservletResponse 输出数据
        response.setContentType("text/html;charset=utf-8");
        PrintWriter pw = response.getWriter();
        pw.println(msg);
        pw.flush();
        pw.close();
    }
}
  • index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
         pageEncoding="UTF-8"%>
<html>
    <head>
        <title>局部刷新</title>
        <script type="text/javascript">
            function doAjax(){
                //1、创建异步对象
                var xmlHttp = new XMLHttpRequest();
                //2、给异步对象绑定事件
                xmlHttp.onreadystatechange = function(){
                    if(xmlHttp.readyState === 4 && xmlHttp.status === 200 ) {
                        //处理服务器端的数据,更新当前页面
                        var data = xmlHttp.responseText;
                        document.getElementById("mydata").innerText= data;
                    }
                }
                //3、初始化异步请求对象
                    //获取dom对象的value值
                    var height = document.getElementById("height").value;
                    var weight = document.getElementById("weight").value;
                    //拼接参数
                    var param = "height="+height+"&weight="+weight;
                xmlHttp.open("get", "bmi?" + param, true)
                //4、使用异步对象发送请求
                xmlHttp.send();
            }
        </script>
    </head>
    <body>
    <div>
        <p>局部刷新计算BMI</p>
        身高(m):<input type="text" id="height">
        <br>
        体重(kg):<input type="text" id="weight">
        <br>
        <input type="button" value="计算BMI" onclick="doAjax()">
        <br>
        <div id="mydata">等待加载BMI...</div>
    </div>
    </body>
</html>
  • 运行
    在这里插入图片描述
    输入数据点击按钮:
    在这里插入图片描述
    实现局部刷新。

AJAX 联合 json 使用

ajax 发起请求-------servlet(返回的一个 json 格式的字符串:{name:"河北", jiancheng:"冀","shenghui":"石家庄"}

  • json 分类:
    1、json 对象,JSONObject,这种对象的格式(名称:值), 也可以看做是(key:value)格式。
    2、json 数组, JSONArray,基本格式:
    [{ name:"河北", jiancheng:"冀","shenghui":"石家庄"} , { name:"山西", jiancheng:"晋","shenghui":"太原"} ]
  • 为什么要使用 json
    1、json格式好理解。
    2、json格式数据在多种语言中,比较容易处理。 使用java, javascript读写json格式的数据比较容易。
    3、json格式数据他占用的空间下,在网络中传输快, 用户的体验好。
  • 处理 json 的工具库
    gson(google);fastjson(阿里),jackson,json-lib。
    在 js 中的,可以把 json 格式的字符串,转为 json 对象,json 中的 key,就是 json 对象的属性名。

代码示例

(这里使用 jackson)

  • Province.java
public class Province {
    private int id;
    private String name;
    private String jiancheng;
    private String shenghui;
    
    无参构造...
    有参构造...
    get、set...
}
  • ProvinceDao.java
public class ProvinceDao {

    public Province searchById(Integer proid) {
        String url = "jdbc:mysql://localhost:3306/ajax?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=UTC&rewriteBatchedStatements=true";
        String username = "root";
        String password = "123";

        Connection con = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        String sql = "";
        Province province = null;

        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            con = DriverManager.getConnection(url, username, password);
            sql = "select name,jiancheng,shenghui from province where id = ?";
            pstmt = con.prepareStatement(sql);
            pstmt.setInt(1,proid);
            rs = pstmt.executeQuery();
            if(rs.next()){
                province = new Province();
                province.setName(rs.getString("name"));
                province.setJiancheng(rs.getString("jiancheng"));
                province.setShenghui(rs.getString("shenghui"));

            }
        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        }finally {
            try {
                if (con != null){
                    con.close();
                }
                if (pstmt != null){
                    pstmt.close();
                }
                if (rs != null){
                    rs.close();
                }
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }

        return province;
    }
}
  • SearchProServlet.java
public class SearchProServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String proid = request.getParameter("proid");
        ProvinceDao provinceDao = new ProvinceDao();
        String jsonData = "{}";

        if (proid != null && !"".equals(proid.trim())){
            Province province = provinceDao.searchById(Integer.parseInt(proid));
            //将实体类转换为 json
            ObjectMapper om =  new ObjectMapper();
            jsonData =  om.writeValueAsString(province);
        }

        //响应 ajax 需要的数据,使用 HttpservletResponse 输出数据
        response.setContentType("application/json;charset=utf-8");
        PrintWriter pw = response.getWriter();
        pw.println(jsonData);
        pw.flush();
        pw.close();
    }
}
  • index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
         pageEncoding="UTF-8"%>
<html>
    <head>
        <title>局部刷新</title>
        <script type="text/javascript">
            function search(){
                //获取dom对象的value值
                var proid = document.getElementById("proid").value;
                //1、创建异步对象
                var xmlHttp = new XMLHttpRequest();
                //2、给异步对象绑定事件
                xmlHttp.onreadystatechange = function(){
                    if(xmlHttp.readyState == 4 && xmlHttp.status == 200 ) {
                        //处理服务器端的数据,更新当前页面
                        var data = xmlHttp.responseText;
                        //eval是执行括号中的代码,把 json 字符串转化为 json 对象
                        var jsonObj = eval("("+data+")");
                        //var jsonObj = JSON.parse(data);
                        document.getElementById("proname").value = jsonObj.name;
                        document.getElementById("projc").value = jsonObj.jiancheng;
                        document.getElementById("prosh").value = jsonObj.shenghui;
                    }
                }
                //3、初始化异步请求对象
                xmlHttp.open("get", "search?proid=" + proid, true)
                //4、使用异步对象发送请求
                xmlHttp.send();
            }
        </script>
    </head>
    <body>
    <div>
        <table border="1">
            <tr>
                <td>省份编号:</td>
                <td>
                    <input type="text" id="proid">
                    <input type="button" value="搜索" onclick="search()">
                </td>
            </tr>
            <tr>
                <td>省份名称:</td>
                <td><input type="text" id="proname"></td>
            </tr>
            <tr>
                <td>省份简称:</td>
                <td><input type="text" id="projc"></td>
            </tr>
            <tr>
                <td>省会</td>
                <td><input type="text" id="prosh"></td>
            </tr>
        </table>
    </div>
    </body>
</html>

在这里插入图片描述
输入“1”点击搜索:
在这里插入图片描述

FormData 对象

1、使用 XMLHttpRequest 对象模拟 Form 表单提交数据给服务器时,无论是 "GET" 还是 "POST" 方法,都涉及了数据的拼接问题。
2、因为是字符串,如果数据项较多时,由于数据的键值必须和 Form 表单完全统一,否则服务器端无法处理,所以太容易出错了。
3、HTML5 新标准中提供了一个 FormData 对象,可以用来轻松模拟表单对象中的数据。
(总结:便于数据的拼接)

创建 FormData 对象

可以使用两种方法创建 FormData 对象。

  • 方法一
    一种是使用 new 关键字创建,页面上不需要 Form 表单,数据需要使用手工方式逐一附加,方法如下:
var formData = new FormData();
formData.append(key, value);
//key 是键,value 是对应的数据值
  • 方法二
    直接借助于页面上的 Form 表单,在使用 new 关键字实例化时,将 Form 表单对象直接作为参数,方法如下:
var oform = document.getElementById("myForm");
var formdata = new FormData(oform);
发送 FormData 数据

xmlHttp.send(FormData);

  • send 括号中的值可选
    在XHR请求中要发送的数据体,可以是以下几种:
    1、可以为 Document, 在这种情况下,它在发送之前被序列化。
    2、为 XMLHttpRequestBodyInit, 从 per the Fetch spec (规范中)可以是 Blob、BufferSource (en-US)、FormData、URLSearchParams 或者 USVString 对象。
    3、null
    4、如果没有指定值,则默认值为 null。
XMLHttpRequest.send();
XMLHttpRequest.send(ArrayBuffer data);
XMLHttpRequest.send(ArrayBufferView data);
XMLHttpRequest.send(Blob data);
XMLHttpRequest.send(Document data);
XMLHttpRequest.send(DOMString? data);
XMLHttpRequest.send(FormData data);

如果 send() 发送 DOM 对象,在发送之前,数据会先被串行化。如果发送二进制数据,最好是发送 ArrayBufferView 或 Blob 对象,这使得通过 Ajax 上传文件成为可能。

xhr.send("foo=bar&lorem=ipsum");
// xhr.send('string');
// xhr.send(new Blob());
// xhr.send(new Int8Array());
// xhr.send({ form: 'data' });
// xhr.send(document);
// xhr.send(null);
代码示例

将上面的 SearchProServlet 方法加上 post,这里使用 post 方式,将 index.jsp 中部分代码改成:

<script type="text/javascript">
	function search(){
	    //获取dom对象的value值
	    var proid = document.getElementById("proid").value;
	    //使用 FormData 对象进行进行字符串拼接
	    var formData = new FormData();
	    formData.append("proid", proid);
	    //1、创建异步对象
	    var xmlHttp = new XMLHttpRequest();
	    //2、初始化异步请求对象
	    xmlHttp.open("post", "search", true)
	    //3、给异步对象绑定事件
	    xmlHttp.onreadystatechange = function(){
	        if(xmlHttp.readyState === 4){
	            if(xmlHttp.status === 200) {
	                //处理服务器端的数据,更新当前页面
	                var data = xmlHttp.responseText;
	                //eval是执行括号中的代码,把 json 字符串转化为 json 对象
	                var jsonObj = eval("("+data+")");
	                //var jsonObj = JSON.parse(data);
	                document.getElementById("proname").value = jsonObj.name;
	                document.getElementById("projc").value = jsonObj.jiancheng;
	                document.getElementById("prosh").value = jsonObj.shenghui;
	            }
	        }
	    }
	    //这句必须有,使用 post 时会自动附加请求报头
	    xmlHttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
	    //4、使用异步对象发送请求(使用FormData)
	    xmlHttp.send(formData);
	}
</script>

效果同上

posted @ 2022-05-17 21:49  YU_UY  阅读(54)  评论(0编辑  收藏  举报