玩命加载中 . . .

Ajax学习笔记


学习视频链接:B站 动力节点

一、概述

ajax是用来做局部刷新的。局部刷新使用的核心对象是 异步对象(XMLHttpRequest)
这个异步对象是存在浏览器内存中的 ,使用javascript语法创建和使用XMLHttpRequest对象。

全局刷新:整个浏览器被新的数据覆盖。在网络中传输大量的数据。 浏览器需要加载,渲染页面。
局部刷新:在浏览器器的内部,发起请求,获取数据,改变页面中的部分内容。其余的页面无需加载和渲染 网络中数据传输量少, 给用户的感受好。

AJAX:Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)。

AJAX 是一种在无需重新加载整个网页的情况下,能够更新部分页面内容的新方法

Asynchronous: 异步的意思
JavaScript:javascript脚本,在浏览器中执行
and : 和
xml : 是一种数据格式

ajax是一种做局部刷新的新方法,不是一种语言。 ajax包含的技术主要有javascript,dom,css, xml等等。 核心是javascript 和 xml 。
javascript:负责创建异步对象, 发送请求, 更新页面的dom对象。 ajax请求需要服务器端的数据。
xml: 网络中的传输的数据格式。 使用json替换了xml 。

AJAX 不单需要前端的技术,同时需要后端(服务器)的配合。服务器需要提供数据,数据是 AJAX 请求的响应结果。

二、AJAX异步实现步骤

ajax中使用XMLHttpRequest对象。

1、创建异步对象

var xmlHttp = new XMLHttpRequest();

2、给异步对象绑定事件

当请求被发送到服务器时,我们需要执行一些基于响应的任务。每当 readyState 改变时,就会触发 onreadystatechange 事件。此事件可以指定一个处理函数 function。

onreadystatechange :当异步对象发起请求,获取了数据都会触发这个事件。这个事件需要指定一个函数, 在函数中处理状态的变化。

通过判断 XMLHttpReqeust 对象的状态,获取服务端返回的数据。

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

异步对象的属性 readyState 表示异步对象请求的状态变化
0:创建异步对象时, new XMLHttpRequest();
1:初始异步请求对象, xmlHttp.open()
2:发送请求, xmlHttp.send()
3:从服务器端获取了数据,此时3, 注意3是异步对象内部使用, 获取了原始的数据。
4:异步对象把接收的数据处理完成后。 此时开发人员在4的时候处理数据。
在4的时候,开发人员做什么 ? 更新当前页面。

异步对象的status属性,表示网络请求的状况的, 200, 404, 500, 需要是当status==200
时,表示网络请求是成功的。

3、初始化异步请求

异步的方法open()

xmlHttp.open(请求方式get|post, "服务器端的访问地址", 同步|异步请求(默认是true,异步请求))

open(method,url,async)
参数说明:
• method:请求的类型;GET 或 POST
• url:服务器的 servlet 地址
• asynctrue(异步)或 false(同步)

例如:

xmlHttp.open("get", "login?name=admin&pwd=admin",true);

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

xmlHttp.send()

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

需获得来自服务器的响应,使用 XMLHttpRequest 对象的 responseText 或responseXML 属性。

responseText:获得字符串形式的响应数据
responseXML:获得 XML 形式的响应数据

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

三、JSON

JSON(JavaScript Object Notation, JS 对象简谱) 是一种轻量级的数据交换格式。

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(阿里,速度快,不是最符合json处理规范的)

jackson(性能好,规范好

json-lib(性能差,依赖多)

在js中的,可以把json格式的字符串,转为json对象, json中的key,就是json对象的属性名。

四、AJAX示例

根据省份id查询省份信息

1、环境准备

数据库 db_test

省份信息表:

SET FOREIGN_KEY_CHECKS=0;


DROP TABLE IF EXISTS `province`;
CREATE TABLE `province` (
  `id` INT(11) NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(255) DEFAULT NULL COMMENT '省份名称',
  `jiancheng` VARCHAR(255) DEFAULT NULL COMMENT '简称',
  `shenghui` VARCHAR(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8;

INSERT INTO `province` VALUES ('1', '河北', '冀', '石家庄');
INSERT INTO `province` VALUES ('2', '山西', '晋', '太原市');
INSERT INTO `province` VALUES ('3', '内蒙古', '蒙', '呼和浩特市    ');
INSERT INTO `province` VALUES ('4', '辽宁', '辽', '沈阳');
INSERT INTO `province` VALUES ('5', '江苏', '苏', '南京');
INSERT INTO `province` VALUES ('6', '浙江', '浙', '杭州');
INSERT INTO `province` VALUES ('7', '安徽', '皖', '合肥');
INSERT INTO `province` VALUES ('8', '福建', '闽', '福州');
INSERT INTO `province` VALUES ('9', '江西', '赣', '南昌');

城市信息表:

SET FOREIGN_KEY_CHECKS=0;

DROP TABLE IF EXISTS `city`;
CREATE TABLE `city` (
  `id` INT(11) NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(255) DEFAULT NULL,
  `provinceid` INT(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8;


INSERT INTO `city` VALUES ('1', '石家庄市', '1');
INSERT INTO `city` VALUES ('2', '秦皇岛', '1');
INSERT INTO `city` VALUES ('3', '保定市', '1');
INSERT INTO `city` VALUES ('4', '张家口', '1');
INSERT INTO `city` VALUES ('5', '南昌市', '9');
INSERT INTO `city` VALUES ('6', '九江市', '9');
INSERT INTO `city` VALUES ('7', '宜春市', '9');
INSERT INTO `city` VALUES ('8', '福州市', '8');
INSERT INTO `city` VALUES ('9', '厦门市', '8');
INSERT INTO `city` VALUES ('10', '泉州市', '8');
INSERT INTO `city` VALUES ('11', '龙岩市', '8');
INSERT INTO `city` VALUES ('12', '太原', '2');
INSERT INTO `city` VALUES ('13', '大同', '2');
INSERT INTO `city` VALUES ('14', '呼和浩特', '3');
INSERT INTO `city` VALUES ('15', '包头', '3');
INSERT INTO `city` VALUES ('16', '呼伦贝尔', '3');

2、搭建环境

  1. 新建web application:ajaxweb

  2. 配置tomact服务器

  3. Module添加Tomact支持

  4. 创建X表单和MLHttpRequest对象

    <div align="center">
        <table>
            <tr>
                <td>省份编号:</td>
                <td><input type="text" id="proid">
                    <input type="button" value="搜索" onclick="doSearch()">
                </td>
            </tr>
            <tr>
                <td>省份名称:</td>
                <td><input type="text" id="proname"></td>
            </tr>
            <tr>
                <td>省份简称:</td>
                <td><input type="text" id="projiancheng"></td>
            </tr>
        </table>
    </div>

    创建XMLHttpRequest对象:

    <script type="text/javascript">
        function doSearch() {
        var proid = document.getElementById("proid").value;
        //创建异步请求对象
        var xmlHttp = new XMLHttpRequest();
        //绑定事件
        xmlHttp.onreadystatechange = function () {
            if (xmlHttp.readyState == 4 && xmlHttp.status == 200){
                var data = xmlHttp.responseText;
                alert(data);
            }
        }
        //初始化请求参数
        xmlHttp.open("get","s?proid="+proid,true);
        //发送请求
        xmlHttp.send();
    }
    </script>
  5. 创建Servlet处理Ajax请求

    package com.lskj.controller;
    
    

import javax.servlet.ServletException;
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 SearchServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String provinceName = “无数据”;
//获取参数proid
String param = req.getParameter(“proid”);
if(“1”.equals(param)){
provinceName = “河北”;
}
resp.setContentType(“text/html;charset=utf-8”);
PrintWriter pw = resp.getWriter();
pw.println(provinceName);
pw.flush();
pw.close();
}

   @Override
   protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       super.doGet(req, resp);
   }

}


6. web.xml文件中注册servlet

   ```xml
   <servlet>
       <servlet-name>SearchServlet</servlet-name>
       <servlet-class>com.lskj.controller.SearchServlet</servlet-class>
   </servlet>
   <servlet-mapping>
       <servlet-name>SearchServlet</servlet-name>
       <url-pattern>/s</url-pattern>
   </servlet-mapping>
  1. 运行Tomact进行测试

  2. 添加mysql驱动

    • 在WEB-INF目录下创建lib文件,用来存放jar文件,把准备好的mysql驱动拷贝到lib目录下。
    • 在项目结构中modules->Dependencies->JARs or directories->项目WEB-INF\lib目录,并选中刚添加的依赖
    • 确认修改,也是在项目结构下的Problems->点击Fix->Add “lib” to the artifact->OK
  3. 创建ProvinceDao访问数据库

    //根据id获取名称
    public String queryProviceNameById(Integer proviceId){
        String url = "jdbc:mysql://localhost:3306/db_test";
        String user = "root";
        String pwd = "root";
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        //方法返回值
        String retName = "";
        try{
            //注册驱动
            Class.forName("com.mysql.jdbc.Driver");
            //获取连接
            conn = DriverManager.getConnection(url, user, pwd);
            //获取数据库操作对象
            String sql = "select name from province where id = ?";
            ps = conn.prepareStatement(sql);
            ps.setInt(1,proviceId);
            //执行SQL
            rs = ps.executeQuery(sql);
            //处理结果集
            if (rs.next()) {
                retName = rs.getString("name");
            }
        } catch(ClassNotFoundException e){
            e.printStackTrace();
        } catch(SQLException e){
            e.printStackTrace();
        }finally {
            //释放资源
            try {
                if (rs != null) {
                    rs.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
            try {
                if (ps != null) {
                    ps.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
            try {
                if (conn != null) {
                    conn.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return retName;
    }
  4. 修改之前创建的Servlet

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String provinceName = "无数据";
        //获取参数proid
        String param = req.getParameter("proid");
        /*if("1".equals(param)){
                provinceName = "河北";
            }*/
        if(param != null){
            ProvinceDao dao = new ProvinceDao();
            provinceName = dao.queryProviceNameById(Integer.parseInt(param));
        }
        resp.setContentType("text/html;charset=utf-8");
        PrintWriter pw = resp.getWriter();
        pw.println(provinceName);
        pw.flush();
        pw.close();
    }
  5. 修改index.jsp中的js代码

    //绑定事件
    xmlHttp.onreadystatechange = function () {
        if (xmlHttp.readyState == 4 && xmlHttp.status == 200){
            var data = xmlHttp.responseText;
            //alert(data);
            document.getElementById("proname").value = data;
        }
    }
  6. 部署项目,访问测试

3、使用json作为数据交换格式

根据省份id,查询省份的所有数据(数据格式为json)

实现步骤:

  1. 添加处理json的工具库

    jackson:是非常有名的处理 json 的工具库。使用 jackson 可以实现 java 对象到 json 格式字符串的转换,也可以实现 json 字符串转为 json 对象。

    • 把json的三个工具库jar文件复制到/WEB-INF/lib目录下
    • 确认修改,在项目结构下的Problems->点击Fix->Add “lib” to the artifact->OK
  2. 创建实体类Province

    package com.lskj.pojo;
    
    public class Province {
        private Integer id;
        private String name;
        private String jiancheng;
        private String shenghui;
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getJiancheng() {
            return jiancheng;
        }
    
        public void setJiancheng(String jiancheng) {
            this.jiancheng = jiancheng;
        }
    
        public String getShenghui() {
            return shenghui;
        }
    
        public void setShenghui(String shenghui) {
            this.shenghui = shenghui;
        }
    }
  3. 在ProvinceDao中增加方法,返回对象

    //根据id获取一个完整的Province对象
    public Province queryProviceById(Integer proviceId){
        String url = "jdbc:mysql://localhost:3306/db_test";
        String user = "root";
        String pwd = "root";
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        //方法返回值
        Province province = null;
        try{
            //注册驱动
            Class.forName("com.mysql.jdbc.Driver");
            //获取连接
            conn = DriverManager.getConnection(url, user, pwd);
            //获取数据库操作对象
            String sql = "select id,name,jiancheng,shenghui from province where id = ?";
            ps = conn.prepareStatement(sql);
            ps.setInt(1,proviceId);
            //执行SQL
            rs = ps.executeQuery();
            //处理结果集
            if (rs.next()) {
                province = new Province();
                province.setId(rs.getInt("id"));
                province.setName(rs.getString("name"));
                province.setJiancheng(rs.getString("jiancheng"));
                province.setShenghui(rs.getString("shenghui"));
            }
        } catch(ClassNotFoundException e){
            e.printStackTrace();
        } catch(SQLException e){
            e.printStackTrace();
        }finally {
            //释放资源
            try {
                if (rs != null) {
                    rs.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
            try {
                if (ps != null) {
                    ps.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
            try {
                if (conn != null) {
                    conn.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return province;
    }
  4. 创建新的Servlet对象

    public class SearchServletJson extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            //默认值,{}:表示json格式的数据
            String json = "{}";
    
            //获取请求参数,省份id
            String strProid = req.getParameter("proid");
    
            //判断proid有值时,调用dao查询数据
            if( strProid != null && strProid.trim().length() > 0 ){
                ProvinceDao dao  = new ProvinceDao();
                Province p  = dao.queryProviceById(Integer.valueOf(strProid));
                //需要使用jackson 把  Provice对象转为  json
                ObjectMapper om  = new ObjectMapper();
                json =  om.writeValueAsString(p);
            }
    
            //把获取的数据,通过网络传给ajax中的异步对象,响应结果数据
            //指定服务器端(servlet)返回给浏览器的是json格式的数据,json数据使用utf-8编码的
            //response.setContentType("text/json;charset=utf-8");
            resp.setContentType("application/json;charset=utf-8");
            PrintWriter pw  = resp.getWriter();
            pw.println(json); //输出数据---会赋给ajax中 responseText属性
            pw.flush();
            pw.close();
        }
    }
  5. 创建searchJson.jsp,获取json数据

    页面:

    省份编号:
    省份名称:
    省份简称:
    省会名称:

    ajax请求处理:

    <script type="text/javascript">
        function  doSearch() {
            //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 + ")");
                    //更新dom对象
                    callback(jsonobj);
                }
            }
    
            //3.初始异步对象的请求参数
            var proid = document.getElementById("proid").value;
    
            // true :异步处理请求。 使用异步对象发起请求后,不用等待数据处理完毕,就可以执行其它的操作。
            // false:同步,异步对象必须处理完成请求,从服务器端获取数据后,才能执行send之后的代码。 任意时刻只能执行一个异步请求。
    
            xmlHttp.open("get","json?proid="+proid,true);
    
            //4.发送请求
            xmlHttp.send();
        }
    
        //定义函数,处理服务器端返回的数据
        function callback(json){
            document.getElementById("proname").value = json.name;
            document.getElementById("projiancheng").value=json.jiancheng;
            document.getElementById("proshenghui").value= json.shenghui;
        }
    </script>
  6. web.xml中注册Servlet

    <servlet>
        <servlet-name>SearchJson</servlet-name>
        <servlet-class>com.lskj.controller.SearchServletJson</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>SearchJson</servlet-name>
        <url-pattern>/json</url-pattern>
    </servlet-mapping>
  7. 部署应用,测试访问


  目录