AJAX与JSON

1. AJAX介绍

  • AJAX(Asynchronous JavaScript And XML):异步的 JavaScript 和 XML。
  • AJAX是一种不需要刷新整个页面,进行局部刷新的技术。
  • 本身不是一种新技术,而是多个技术综合,用于快速创建动态网页的技术
  • AJAX通过浏览器与服务器进行少量数据交换,就可以使网页实现异步更新,也就是在不重新加载整个页面的情况下,对网页的部分内容进行局部更新
  • 学习ajax,必须具备javascript技术的基础和xml技术的基础。后期已经使用json替换了xml进行网络中数据的传输。

2. 原生JavaScript实现AJAX

2.1 代码实现
  • java代码
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/userServlet")
public class UserServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //设置请求和响应的乱码
        req.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html;charset=UTF-8");

        //1.获取请求参数
        String username = req.getParameter("username");

        //模拟服务器处理请求需要5秒钟
        /*try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }*/

        //2.判断姓名是否已注册
        if("zhangsan".equals(username)) {
            resp.getWriter().write("<font color='red'>用户名已注册</font>");
        }else {
            resp.getWriter().write("<font color='green'>用户名可用</font>");
        }
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req,resp);
    }
}
  • html代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>用户注册</title>
</head>
<body>
    <form autocomplete="off">
        姓名:<input type="text" id="username">
        <span id="uSpan"></span>
        <br>
        密码:<input type="password" id="password">
        <br>
        <input type="submit" value="注册">
    </form>
</body>
<script>
    //1.为姓名绑定失去焦点事件
    document.getElementById("username").onblur = function() {
        //2.创建XMLHttpRequest核心对象
        let xmlHttp = new XMLHttpRequest();

        //3.打开链接
        let username = document.getElementById("username").value;
        xmlHttp.open("GET","userServlet?username="+username,true);
        //xmlHttp.open("GET","userServlet?username="+username,false);

        //4.发送请求
        xmlHttp.send();

        //5.处理响应
        xmlHttp.onreadystatechange = function() {
            //判断请求和响应是否成功
            if(xmlHttp.readyState == 4 && xmlHttp.status == 200) {
                //将响应的数据显示到span标签
                document.getElementById("uSpan").innerHTML = xmlHttp.responseText;
            }
        }
    }
</script>
</html>
2.2 实现详解
  • 核心对象:XMLHttpRequest
    • 用于在后台与服务器交换数据。可以在不重新加载整个网页的情况下,对网页的某部分进行更新。
  • 打开链接:open(method,url,async)
    • method:请求的类型 GET 或 POST。
    • url:请求资源的路径。
    • async:true(异步) 或 false(同步)。
  • 发送请求:send(String params)
    • params:请求的参数(POST 专用)。
  • 处理响应:onreadystatechange
    • readyState:0-请求未初始化,1-服务器连接已建立,2-请求已接收,3-请求处理中,4-请求已完成,且响应已就绪。
    • status:200-响应已全部 OK。
  • 获得响应数据形式
    • responseText:获得字符串形式的响应数据。
    • responseXML:获得 XML 形式的响应数据。

3. JQuery实现AJAX

3.1 概述
  • jquery对js原生的ajax代码进行了封装。提供了便捷的操作方法:
    • get方法
    • post方法
    • ajax方法
3.2 get方法
  • 核心语法:$.get(url,[data],[callback],[type]);
    • url:请求的资源路径。
    • data:发送给服务器端的请求参数,格式可以是key=value,也可以是 js 对象。
    • callback:当请求成功后的回调函数,可以在函数中编写我们的逻辑代码。
    • type:预期的返回数据的类型,取值可以是 xml, html, js, json, text等。
  • 示例代码
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>用户注册</title>
    </head>
    <body>
        <form autocomplete="off">
            姓名:<input type="text" id="username">
            <span id="uSpan"></span>
            <br>
            密码:<input type="password" id="password">
            <br>
            <input type="submit" value="注册">
        </form>
    </body>
    <script src="js/jquery-3.3.1.min.js"></script>
    <script>
        //1.为用户名绑定失去焦点事件
        $("#username").blur(function () {
            let username = $("#username").val();
            //2.jQuery的GET方式实现AJAX
            $.get(
                //请求的资源路径
                "userServlet",
                //请求参数
                "username=" + username,
                //回调函数
                function (data) {
                    //将响应的数据显示到span标签
                    $("#uSpan").html(data);
                },
                //响应数据形式
                "text"
            );
        });
    </script>
    </html>
    

注意

  • 该方法只能发送get请求。
3.3 post方法
  • 核心语法:$.post(url,[data],[callback],[type]);
    • url:请求的资源路径。
    • data:发送给服务器端的请求参数,格式可以是key=value,也可以是 js 对象。
    • callback:当请求成功后的回调函数,可以在函数中编写我们的逻辑代码。
    • type:预期的返回数据的类型,取值可以是 xml, html, js, json, text等。
  • 代码实现
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>用户注册</title>
    </head>
    <body>
        <form autocomplete="off">
            姓名:<input type="text" id="username">
            <span id="uSpan"></span>
            <br>
            密码:<input type="password" id="password">
            <br>
            <input type="submit" value="注册">
        </form>
    </body>
    <script src="js/jquery-3.3.1.min.js"></script>
    <script>
        //1.为用户名绑定失去焦点事件
        $("#username").blur(function () {
            let username = $("#username").val();
            //2.jQuery的POST方式实现AJAX
            $.post(
                //请求的资源路径
                "userServlet",
                //请求参数
                "username=" + username,
                //回调函数
                function (data) {
                    //将响应的数据显示到span标签
                    $("#uSpan").html(data);
                },
                //响应数据形式
                "text"
            );
        });
    </script>
    </html>
    

注意

  • 该方法专门用来发送post请求。
3.4 通用方法(AJAX方法)
  • 该方法是通用的发送ajax请求的方法。可以发送get请求,也可以发送post请求。
  • 核心语法:$.ajax({name:value,name:value,…});
    • url:请求的资源路径。
    • async:是否异步请求,true-是,false-否 (默认是 true)。
    • data:发送到服务器的数据,可以是键值对形式,也可以是 js 对象形式。
    • type:请求方式,POST 或 GET (默认是 GET)。
    • dataType:预期的返回数据的类型,取值可以是 xml, html, js, json, text等。
    • success:请求成功时调用的回调函数。
    • error:请求失败时调用的回调函数。
  • 代码实现
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>用户注册</title>
    </head>
    <body>
        <form autocomplete="off">
            姓名:<input type="text" id="username">
            <span id="uSpan"></span>
            <br>
            密码:<input type="password" id="password">
            <br>
            <input type="submit" value="注册">
        </form>
    </body>
    <script src="js/jquery-3.3.1.min.js"></script>
    <script>
        //1.为用户名绑定失去焦点事件
        $("#username").blur(function () {
            let username = $("#username").val();
            //2.jQuery的通用方式实现AJAX
            $.ajax({
                //请求资源路径
                url:"userServletxxx",
                //是否异步
                async:true,
                //请求参数
                data:"username="+username,
                //请求方式
                type:"POST",
                //数据形式
                dataType:"text",
                //请求成功后调用的回调函数
                success:function (data) {
                    //将响应的数据显示到span标签
                    $("#uSpan").html(data);
                },
                //请求失败后调用的回调函数
                error:function () {
                    alert("操作失败...");
                }
            });
        });
    </script>
    </html>
    

4. JSON的处理

4.1 json介绍
  • JSON(JavaScript Object Notation):是一种轻量级的数据交换格式。
  • 它是基于 ECMAScript 规范的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。
  • 简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。易于人阅读和编写,同时也易于计算机解析和生成,并有效的提升网络传输效率。
  • 创建格式
    类型语法
    对象类型{name:value,name:value,…}
    数组/集合类型[{name:value,…},{name:value,…}]
    混合类型{name:[{name:value,…},{name:value,…}]}

    注意

    • name是字符串类型,value可以是任意类型
  • 常用方法
    成员方法说明
    stringify(对象)将指定对象转换为json格式字符串
    parse(字符串)将指定json格式字符串解析成对象
4.2 jackson工具包
4.2.1 介绍
  • 我们除了可以在 JavaScript 中来使用 JSON 以外,在 JAVA 中同样也可以使用 JSON。
  • JSON 的转换工具是通过 JAVA 封装好的一些 JAR 工具包。
  • 可以将 JAVA 对象或集合转换成 JSON 格式的字符串,也可以将 JSON 格式的字符串转成 JAVA 对象。
  • Jackson:开源免费的 JSON 转换工具,SpringMVC 转换默认使用 Jackson。
4.2.2 使用步骤
  • 引入jar包
    • jackson-annotations-2.2.3.jar
    • jackson-core-2.2.3.jar
    • jackson-databind-2.2.3.jar
  • 创建对象
    • ObjectMapper mapper = new ObjectMapper();
  • 使用方法进行转换
    方法:
    	* 将java对象转换为json串
    		String jsonStr = writeValueAsString(java对象)
    	* 将json串转换为java对象
    		readValue(json串,类型.class)
    		readValue(json串,new TypeReference<泛型>() {})
    		
    json串数据
    	{:,:}  <===>  map集合或者java实体类对象
    	[元素1,元素2]  <===>  list集合
    	[{},{},{}]    <===>  List<map或者实体类对象>
    	{:[{},{}]}  <===>  Map<String,List<map或者实体类对象>>
    
4.2.3 常用类
类名说明
ObjectMapper是Jackson工具包的核心类,它提供一些方法来实现JSON字符串和对象之间的转换
TypeReference对集合泛型的反序列化,使用TypeReference可以明确的指定反序列化的对象类型
4.2.4 ObjectMapper常用方法
方法名说明
String writeValueAsString(Object obj)将Java对象转换成JSON字符串
<T> T readValue(String json,Class<T> valueType)将JSON字符串转换成Java对象
<T> T readValue(String json,TypeReference valueTypeRef)将JSON字符串转换成Java对象
4.3 将java对象转换成json串
  • 实体类对象
    //User对象转json
    User user = new User("张三",23);
    
    String json = mapper.writeValueAsString(user); // {"name":"张三","age":23}
    System.out.println("json字符串:" + json);
    
  • map集合对象
    HashMap<String,String> map = new HashMap<>();
    map.put("name","张三");
    map.put("gender","男");
    
    String json = mapper.writeValueAsString(map); // {"name":"张三","gender":"男"}
    System.out.println("json字符串:" + json);
    
  • Map<String,User>
    HashMap<String,User> map = new HashMap<>();
    map.put("黑马一班",new User("张三",23));
    map.put("黑马二班",new User("李四",24));
    
    String json = mapper.writeValueAsString(map); 
    // {"黑马一班":{"name":"张三","age":23},"黑马二班",{"name":"李四","age":24}}
    System.out.println("json字符串:" + json);
    
  • List集合对象
    ArrayList<String> list = new ArrayList<>();
    list.add("张三");
    list.add("李四");
    
    String json = mapper.writeValueAsString(list); //["张三","李四"]
    System.out.println("json字符串:" + json);
    
  • List对象
    ArrayList<User> list = new ArrayList<>();
    list.add(new User("张三",23));
    list.add(new User("李四",24));
    
    String json = mapper.writeValueAsString(list); // [{"name":"张三","age":23},{"name":"李四","age":24}]
    System.out.println("json字符串:" + json);
    
4.4 将json串转换成java对象
String str = "{\"name\":\"张三\",\"age\":23}";

ObjectMapper mapper = new ObjectMapper();
User user = mapper.readValue(str, User.class);
System.out.println(user);

5. 案例:搜索联想功能

  • 分析
    • 页面
      • 为用户名输入框绑定鼠标点击事件。
      • 获取输入的用户名数据。
      • 判断用户名是否为空。
      • 如果为空,则将联想提示框隐藏。
      • 如果不为空,则发送 AJAX 请求,并将响应的数据显示到联想框。
    • 控制层
      • 获取请求参数。
      • 调用业务层的模糊查询方法。
      • 将返回的数据转成 JSON,并响应给客户端。
  • UserServlet
    //设置请求和响应的编码
    req.setCharacterEncoding("UTF-8");
    resp.setContentType("text/html;charset=UTF-8");
    
    //1.获取请求参数
    String username = req.getParameter("username");
    
    //2.调用业务层的模糊查询方法得到数据
    UserService service = new UserServiceImpl();
    List<User> users = service.selectLike(username);
    
    //3.将数据转成JSON,响应到客户端
    ObjectMapper mapper = new ObjectMapper();
    String json = mapper.writeValueAsString(users);
    resp.getWriter().write(json);
    
  • serch.html
    //1.为用户名输入框绑定鼠标点击事件
    $("#username").mousedown(function () {
        //2.获取输入的用户名
        let username = $("#username").val();
    
        //3.判断用户名是否为空
        if(username == null || username == "") {
            //4.如果为空,将联想框隐藏
            $("#show").hide();
            return;
        }
    
        //5.如果不为空,发送AJAX请求。并将数据显示到联想框
        $.ajax({
            //请求的资源路径
            url:"userServlet",
            //请求参数
            data:{"username":username},
            //请求方式
            type:"POST",
            //响应数据形式
            dataType:"json",
            //请求成功后的回调函数
            success:function (data) { //data是响应的数据  [{"id":1,"name":"张三","search_count":25},{"id":2,"name":"张三丰","search_count":20}]
                //将返回的数据显示到show的div
                let names = "";
                for(let i = 0; i < data.length; i++) {
                    names += "<div>"+data[i].name+"</div>";  // <div>张三</div><div>张三丰</div>
                }
                //将拼好的div写到搜索联想框中
                $("#show").html(names);
                //将搜索联想框显示出来
                $("#show").show();
            }
        });
    });
    

6. 案例:瀑布流分页

  • 需要的事件:
    • scroll() : 滚动条上下滚动事件
  • 注意:
    • 并不是鼠标滚动就发送异步请求。是滚动到底部后发送异步请求。如何判断呢?
  • 公式:
    • (滚动条距底部的距离 + 滚动条上下滚动的距离 + 当前窗口的高度) >= 当前文档的高度
  • 相关知识
    功能说明
    $(function(){})页面加载事件
    $(window)获取当前窗口对象
    scroll()鼠标滚动事件
    $(window).height()当前窗口的高度
    $(window).scrollTop()滚动条上下滚动的距离
    $(document).height()当前文档的高度
  • 实现思路
    • 页面
      • 定义发送请求标记。
      • 定义当前页码和每页显示的条数。
      • 定义滚动条距底部的距离。
      • 设置页面加载事件。
      • 为当前窗口绑定滚动条滚动事件。
      • 获取必要信息(当前窗口的高度,滚动条上下滚动的距离,当前文档的高度)。
      • 计算当前展示数据是否浏览完毕。
      • 判断请求标记是否为 true。
      • 将请求标记置为 false,当前异步操作完成前,不能重新发起请求。
      • 根据当前页和每页显示的条数来请求查询分页数据。
      • 当前页码+1。
    • 服务器
      • 获取请求参数(当前页,每页显示的条数)。
      • 根据当前页码和每页显示的条数,调用业务层的方法,得到分页 Page 对象。
      • 将得到的数据转为 json。
      • 将数据响应给客户端。
  • index.html页面中js代码如下:
    //1.定义发送请求标记
    let send = true;
    
    //2.定义当前页码和每页显示的条数
    let start = 1;
    let pageSize = 10;
    
    //3.定义滚动条距底部的距离
    let bottom = 1;
    
    //4.设置页面加载事件
    $(function () {
        //5.为当前窗口绑定滚动条滚动事件
        $(window).scroll(function () {
            //6.获取必要信息,用于计算当前展示数据是否浏览完毕
            //当前窗口的高度
            let windowHeight = $(window).height();
            //滚动条从上到下滚动距离
            let scrollTop = $(window).scrollTop();
            //当前文档的高度
            let docHeight = $(document).height();
            //7.计算当前展示数据是否浏览完毕
            //当 滚动条距底部的距离 + 当前滚动条滚动的距离 + 当前窗口的高度 >= 当前文档的高度
            if((bottom + scrollTop + windowHeight) >= docHeight) {
                //8.判断请求标记是否为true
                if(send == true) {
                    //9.将请求标记置为false,当前异步操作完成前,不能重新发起请求。
                    send = false;
                    //10.根据当前页和每页显示的条数来 请求查询分页数据
                    queryByPage(start,pageSize);
                    //11.当前页码+1
                    start++;
                }
            }
        });
    });
    
    //定义查询分页数据的函数
    function queryByPage(start,pageSize){
        //加载动图显示
        $(".loading").show();
        //发起AJAX请求
        $.ajax({
            //请求的资源路径
            url:"newsServlet",
            //请求的参数
            data:{"start":start,"pageSize":pageSize},
            //请求的方式
            type:"POST",
            //响应数据形式
            dataType:"json",
            //请求成功后的回调函数
            success:function (data) {
                if(data.length == 0) {
                    $(".loading").hide();
                    $("#no").html("我也是有底线的...");
                    return;
                }
                //加载动图隐藏
                $(".loading").hide();
                //将数据显示
                let titles = "";
                for(let i = 0; i < data.length; i++) {
                    titles += "<li>\n" +
                        "                <div class=\"title-box\">\n" +
                        "                    <a href=\"#\" class=\"link\">\n" +
                        data[i].title +
                        "                        <hr>\n" +
                        "                    </a>\n" +
                        "                </div>\n" +
                        "            </li>";
                }
    
                //显示到页面
                $(".news_list").append(titles);
                //将请求标记设置为true
                send = true;
            }
        });
    }
    
  • NewsServlet
    //设置请求和响应的编码
    req.setCharacterEncoding("UTF-8");
    resp.setContentType("text/html;charset=UTF-8");
    
    //1.获取请求参数
    String start = req.getParameter("start"); //当前页码
    String pageSize = req.getParameter("pageSize"); //每页显示的条目数
    
    //2.根据当前页码和每页显示的条数来调用业务层的查询方法,得到分页Page对象
    NewsService service = new NewsServiceImpl();
    Page page = service.pageQuery(Integer.parseInt(start), Integer.parseInt(pageSize));
    
    //3.将得到的数据转为JSON
    String json = new ObjectMapper().writeValueAsString(page); // [{"id":1,"title":"jsldjflkds"},{},{}]
    
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    
    //4.将数据响应给客户端
    resp.getWriter().write(json);
    
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值