Ajax

发布时间 2024-01-07 21:12:33作者: 千夜ん

Ajax

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

Ajax 不是一种新的编程语言,而是一种用于创建更好更快以及交互性更强的Web应用程序的技术。

C/S

增加B/S的体验性

B/S: 未来的主流,并且会爆发式的持续增长;

产品链:H5+网页+客户端+手机端(Android, IOS) +小程序

使用jQuery需要先导入jQuery的js文件;

1.原理图解

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

AJAX可以在浏览器当中发送异步请求。请求A和请求B是异步的。谁也不需要等谁,类似于多线程并发。

AJAX的请求发送之后,不会出现页面清空,然后展示新页面的效果。AJAX不是这样的。

这个图想表示的最核心的是:AJAX请求1和AJAX请求2是异步的。并发的,谁也不干扰谁。

image-20220831221926772

浏览器上发送AJAX请求,这些代码是JS语法的代码。其实发送AJAX请求,就是需要编写JS代码的。

2.异步,同步

什么是异步,什么是同步?

  • 假设有t1和t2线程,t1和t2线程并发,就是异步。
  • 假设有t1和t2线程,t2在执行的时候,必须等待t1线程执行到某个位置之后t2才能执行,那么t2在等t1,显然他们是排队的,排队的就是同步。
  • AJAX是可以发送异步请求的。也就是说,在同一个浏览器页面当中,可以发送多个AJAX请求,这些AJAX请求之间不需要等待,是并发的。
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<script>
    function sayHello() {
        alert("Hello,world!");
    }
</script>
<!--需求:页面上有一个按钮,用户点击按钮之后,执行一段JS代码-->
<input type="button" value="hello" onclick="sayHello()">

<!--通过JS代码给按钮绑定事件-->
<input type="button" value="hello2" id="helloBtn">

<script type="text/javascript">
    //页面加载完毕之后,给id="helloBtn"的元素绑定鼠标单击事件
    //这个function就是一个回调函数,这个回调函数什么时候执行?当load事件发生之后,
    // 这个回调函数才会执行。
    //什么是load事件?load事件什么时候发生? 注意:页面加载完毕之后,load事件发生。
    window.onload = function (){
        //获取id="helloBtn"的对象
        var helloBtn = document.getElementById("helloBtn");
        //给id="helloBtn"元素绑定click事件
        //这个function也是一个回调函数,这个回调函数什么时候执行?
        //当helloBtn被click的时候,被鼠标单击的时候,这个回调函数会执行。
        //鼠标单击五次,这个回调函数就会被调用五次。
        helloBtn.onclick = function (){
            // alert("hello javaScript2");

            //alert(this)
            //这个回调函数中的this是谁呢?
            //this是发生事件的事件源对象。是按钮发生了鼠标单击,那么this代表的就是这个按钮对象。
            alert(this.value);
        }
    }
</script>
</body>
</html>

在AJAX的请求,以及AJAX接收服务器的响应,完全都是依靠XMLHttpRequest对象的。

XMLHttpRequest对象中的readyState属性记录下XMLHttpRequest对象的状态。

XMLHttpRequest对象的readyState属性对应的状态值:

0:请求未初始化

1:服务器连接已建立

2:请求已收到

3:正在处理请求

4:请求已完成且响应已就绪

当XMLHttpRequest对象的readyState属性的值变成4的时候,表示这个AJAX请求以及响应已经全部完成了。

image-20220831231151191

3.第一个Ajax程序

package com.feng;
import javax.servlet.annotation.WebServlet;
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;

@WebServlet("/ajaxrequest1")
public class AjaxRequest1Servlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //String s = null;
        //s.toString();

        // Servlet向浏览器响应一段数据
        PrintWriter out = resp.getWriter();
        //out对象向浏览器输出信息
        //服务器的代码实际上和以前的代码还是完全一样的。
        //只不过这个out在响应的时候,浏览器客户端的XMLHttpRequest对象会接收到这个响应的信息。
        out.print("welcome to study ajax!!!");
    }

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

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<script type="text/javascript">
    window.onload  = function () {
        document.getElementById("helloBtn").onclick = function () {
            //发送ajax get请求
            // console.log("发送ajax get请求");
            //1.第一步:创建AJAX核心对象XMLHttpRequest
            var xhr = new XMLHttpRequest();
            //2.第二步:注册回调函数
            //这是一个回调函数,
            // 这个函数在XMLHttpRequest对象的readyState状态值发生改变的时候被调用。
            xhr.onreadystatechange = function (){
                //这里的回调函数会被调用多次。
                //0 -> 1 被调用一次
                //1 -> 2 被调用一次
                //2 -> 3 被调用一次
                //3 -> 4 被调用一次
                // console.log(xhr.readyState);

                //当XMLHttpRequest对象的readyState的状态是4的时候,表示响应结束了。
                // if(xhr.readyState == 4){
                //
                // }

                if(this.readyState == 4){
                    //响应结束了
                    // console.log("响应结束了");
                    //响应结束之后,一般会有一个HTTP的状态码。
                    //HTTP状态码常见的包括:200表示成功了,404表示资源找不到,500表示服务器内部错误。
                    //HTTP状态码是HTTP协议的一部分,HTTP协议中规定的。服务器响应之后都会有一个状态码。
                    //获取HTTP状态码
                    // console.log("HTTP响应状态码:" +this.status);
                    if(this.status == 404){
                        alert("对不起,您访问的资源不存在,请检查请求路径");
                    }else if(this.status == 500){
                        alert("对不起,服务器发生了严重的内部错误,请联系管理员");
                    }else if(this.status == 200){
                        // alert("响应成功,完美");
                        // 200表示完全响应完毕,成功结束了。
                        // 通过XMLHttpRequest对象获取响应的信息。
                        // 通过XMLHttpRequest对象的responseText属性来获取响应的信息。
                        // alert(this.responseText)

                        //把响应信息放到div图层当中,渲染
                        document.getElementById("mydiv").innerHTML = this.responseText;
                    }
                }


            }
            //3.第三步:开启通道(open只是浏览器和服务器建立连接,通道打开,并不会发送请求)
            //XMLHttpRequest对象的open方法
            //open(method,url,async,user,psw)
            //method:请求的方式,可以是GET,也可以是POST,也可以是其它请求方式。
            //url:请求的路径
            //async:只能是true或者false,true表示此ajax请求是一个异步请求,
            // false表示此ajax请求是一个同步请求,
            //(大部分请求都是true,要求异步。极少数情况需要同步)
            //user: 用户名 pwd:密码,用户名和密码是进行身份认证的,说明要想访问这个服务器上的资源,
            // 可能需要提供一些口令才能访问。需不需要用户名和密码,主要看服务器的态度。
            xhr.open("GET","/ajax1/ajaxrequest1",true);
            //4.第四步:发送请求
            xhr.send();

        }
    }
</script>
<!--给一个按钮,用户点击这个按钮的时候发送ajax请求-->
<input type="button" value="hello ajax" id="helloBtn">

<!--给一个div图层,ajax接收了响应的数据之后,在div中进行渲染-->
<div id="mydiv"></div>
</body>
</html>
<dependencies>
  <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.11</version>
    <scope>test</scope>
  </dependency>
  <dependency>
    <groupId>javax.servlet.jsp</groupId>
    <artifactId>jsp-api</artifactId>
    <version>2.2</version>
  </dependency>
  <dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>servlet-api</artifactId>
    <version>2.5</version>
  </dependency>
  <dependency>
    <groupId>org.apache.tomcat.embed</groupId>
    <artifactId>tomcat-embed-core</artifactId>
    <version>9.0.58</version>
  </dependency>
</dependencies>

4.AJAX GET请求

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>发送ajax get请求</title>
</head>
<body>
<script type="text/javascript">
    window.onload = function (){
        document.getElementById("btn").onclick = function (){
            //1.创建AJAX核心对象
            var xhr = new XMLHttpRequest();
            //2.注册回调函数
            xhr.onreadystatechange = function (){
                if(this.readyState == 4){
                    debugger
                    if(this.status == 200){
                        //通过XMLHttpRequest对象的responseText属性可以获取到服务器响应回来的内容。
                        //并且不管服务器响应回来的是什么,
                        // 都以普通文本的形式获取。(服务器可能响应回来:普通文本, XML,JSON,HTML...)
                        // innerHTML属性是javascript中的语法,和ajax的XMLHttpRequest对象无关。
                        // innerHTML可以设置元素内部的HTML代码。(innerHTMl可以将后面的内容当做一段HTML代码解释并执行)
                        document.getElementById("myspan").innerHTML = this.responseText;
                    }else{
                        alert(this.status)
                    }
                }
            }
            //3. 开启通道
            xhr.open("GET","/ajax1/ajaxrequest2",true);
            //4.发送请求
            xhr.send();
        }
    }
</script>
<button id="btn">发送ajax get请求</button>
<span id="myspan"></span>
</body>
</html>
package com.feng;
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;
import java.io.PrintWriter;

/**
 * @auther fengpeng
 * @date 2022/9/4
 */

@WebServlet("/ajaxrequest2")
public class AjaxRequest2Servlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //设置响应的内容类型以及字符集
        resp.setContentType("text/html;charset=UTF-8");
        //获取响应流
        PrintWriter out = resp.getWriter();
        //响应
        out.print("<font color='red'>用户名已存在!!!</font>");
    }

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

  • AJAX get请求如何提交数据呢?
    • get请求提交数据是在"请求行"上提交,格式是: url?name=value&name=value&name=value...
    • 其实这个get请求提交数据的格式是HTTP协议中规定的,遵循协议即可。

提交数据

          //3. 开启通道
            // 获取到用户填写的usercode和username
            var usercode = document.getElementById("usercode").value;
            var username = document.getElementById("username").value;
            xhr.open("GET","/ajax1/ajaxrequest2?usercode="+usercode+"&username="+username,true);
            //4.发送请求
            xhr.send();
        }
    }
</script>
usercode<input type="text" id="usercode"><br>
username<input type="text" id="username"><br>
<button id="btn">发送ajax get请求</button>
<span id="myspan"></span>
</body>

5.AJAX GET请求的缓存问题

  • 对于低版本的IE浏览器来说,AJAX的get请求可能会走缓存。存在缓存问题。

  • 对于现代的浏览器来说,大部分浏览器都不存在AJAX get缓存问题了。

  • 什么是AJAX GET请求缓存问题呢?

    • 在HTTP协议中是这样规定get请求的:get请求会被缓存起来。
    • 发送AJAX GET请求时,在同一个浏览器上,前后发送的AJAX请求路径一样的话,对于低版本的IE来说,第二次的AJAX GETq请求会走缓存,不走服务器。
  • POST请求在HTTP协议中规定的是:POST请求不会被浏览器缓存。

  • GET请求缓存的优缺点:

    • 优点:直接从浏览器缓存中获取资源,不需要从服务器上重新加载资源,速度较快,用户体验好。
    • 缺点:无法实时获取最新的服务器资源。
  • 浏览器什么时候会走缓存?

    • 第一:是一个GET请求
    • 第二:请求路径已经被浏览器缓存过了。第二次发送请求的时候,这个路径没有变化,会走浏览器缓存。
  • 如果是低版本的IE浏览器,怎么解决AJAX GET请求的缓存问题呢?

    • 可以在请求路径url后面添加一个时间戳,这个时间戳是随时变化的。所以每一次发送的请求路径都是不一样的,这样就不会走浏览器的缓存问题了。
    • 可以采用时间戳:"url?t=" + new Date().getTime()
    • 或者可以通过随机数:"url?t=" + Math.random()
    • 也可以随机数+时间戳...

6.AJAX POST请求

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>发送ajax post请求</title>
</head>
<body>
<script>
    window.onload = function (){
        document.getElementById("mybtn").onclick = function (){
            // 发送AJAX POST请求
            // 1.创建AJAX核心对象
            var xhr = new XMLHttpRequest();
            // 2.注册回调函数
            xhr.onreadystatechange = function (){
                if (this.readyState == 4) {
                    if(this.status == 200){
                        document.getElementById("mydiv").innerHTML = this.responseText
                    }else{
                        alert(this.status)
                    }
                }
            }
            // 3.开启通道
            xhr.open("POST","/ajax1/ajaxrequest3",true);
            // 4.发送请求
            xhr.send();
        }
    }
</script>
<button id="mybtn" >发送AJAX POST请求</button>

<div id="mydiv"></div>
</body>
</html>
package com.feng;

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;
import java.io.PrintWriter;

/**
 * @auther fengpeng
 * @date 2022/9/5
 */
@WebServlet("/ajaxrequest3")
public class AjaxRequest3Servlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=UTF-8");
        PrintWriter out = resp.getWriter();
        out.print("<font color='red'>用户名已存在!!!</font>");
    }

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

7.AJAX POST请求模拟表单提交数据

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>发送ajax post请求</title>
</head>
<body>
<script>
    window.onload = function (){
        document.getElementById("mybtn").onclick = function (){
            // 发送AJAX POST请求
            // 1.创建AJAX核心对象
            var xhr = new XMLHttpRequest();
            // 2.注册回调函数
            xhr.onreadystatechange = function (){
                if (this.readyState == 4) {
                    if(this.status == 200){
                        document.getElementById("mydiv").innerHTML = this.responseText
                    }else{
                        alert(this.status)
                    }
                }
            }

            // 3.开启通道
            xhr.open("POST","/ajax1/ajaxrequest3",true);

            // 4.发送请求
            // 怎么模拟AJAX提交form表单呢? 设置请求头的内容类型
            // (这行代码非常关键,是模拟form表单提交的关键代码。)
            // 设置请求头的内容类型时,必须在open之后。
            xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded")

            // 放到send()这个函数的小括号当中的数据,会自动在请求体当中提交数据。
            // 使用JS代码获取用户填写的用户名和密码
            var username = document.getElementById("username").value;
            var password = document.getElementById("password").value;
            //xhr.send("注意格式: 放在这里的数据就是在请求体当中提交的,格式不能随便来,
            // 还是需要遵循HTTP的协议:name=value&name=value&name=value)
            xhr.send("username="+username+"&password="+password);
        }
    }
</script>
用户名<input type="text" id="username"><br>
密码<input type="password" id="password"><br>
<button id="mybtn" >发送AJAX POST请求</button>
<div id="mydiv"></div>
</body>
</html>
package com.feng;

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;
import java.io.PrintWriter;

/**
 * @auther fengpeng
 * @date 2022/9/5
 */
@WebServlet("/ajaxrequest3")
public class AjaxRequest3Servlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=UTF-8");
        PrintWriter out = resp.getWriter();
        //out.print("<font color='red'>用户名已存在!!!</font>");

        // 获取提交数据
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        out.print("用户名是:"+username+",密码是:"+password);
    }

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

  • AJAX POST请求和GET请求的代码区别在哪里?就是前端代码有区别。后端代码没有区别。
//4.发送AJAX POST请求
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded")
//获取表单中的数据
var username = document.getElementById("username").value;
var password = document.getElementById("password").value;
//send函数中的参数就是发送的数据,这个数据在"请求体"当中发送。
xhr.send("username"+ username+"&password"+ password)
  • 实现一个案例:使用AJAX POST请求实现用户注册的时候,用户名是否可用。(验证用户名是否可以注册),实现步骤如下:
    • 在前端,用户输入用户名之后,失去焦点事件blur发生,然后发送AJAX POST请求,提交用户名
    • 在后端,接收到用户名,连接数据库,根据用户名去表中搜索
    • 如果用户名已存在
      • 后端响应消息:对不起,用户名已存在(在前端页面以红色字体展示)
    • 如果用户名不存在
      • 后端响应消息:用户名可以使用(在前端页面以绿色字体展示)
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>AJAX POST请求验证用户名是否可用</title>
</head>
<body>
<script type="text/javascript">
    window.onload = function (){
        document.getElementById("username").onfocus = function (){
            document.getElementById("tipMsg").innerHTML = "";
        }
        document.getElementById("username").onblur = function (){
            // console.log("正在发送AJAX POST请求验证用户名 ")
            //发送AJAX POST请求
            //1.
            var xhr = new XMLHttpRequest();
            //2.
            xhr.onreadystatechange = function (){
                if (this.readyState == 4) {
                    if(this.status == 200){
                        document.getElementById("tipMsg").innerHTML = this.responseText
                    }else {
                        alert(this.status)
                    }
                }
            }
            //3.
            xhr.open("POST","/ajax1/ajaxrequest4",true)
            //4.
            xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded")
            // 获取表单数据
            var username = document.getElementById("username").value;
            xhr.send("username="+ username)
        }
    }

</script>

用户名:<input type="text" id="username">
<span id="tipMsg"></span>

</body>
</html>
package com.feng;

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;
import java.io.PrintWriter;
import java.sql.*;

/**
 * @auther fengpeng
 * @date 2022/9/12
 */
@WebServlet("/ajaxrequest4")
public class AjaxRequest4Servlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取用户名
        String username = req.getParameter("username");
        // 打布尔标记(一种编程模型)
        boolean flag = false; // 默认是用户名不存在
        //连接数据库验证用户名是否存在
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            // 1.注册驱动
            Class.forName("com.mysql.cj.jdbc.Driver");
            // 2.获取连接
            conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC","root","fp");
            // 3.获取预编译的数据库操作对象
            String sql = "select * from mybatis.t_user where name = ?";
            ps = conn.prepareStatement(sql);
            ps.setString(1,username);
            // 4.执行SQL语句
            rs = ps.executeQuery();
            // 5.处理结果集
            if (rs.next()) {
                // 用户名已存在。
                flag = true;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            // 6.释放资源
            if (rs != null) {
                try {
                    rs.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
            if (ps != null) {
                try {
                    ps.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }

        }

        //响应结果到浏览器
        resp.setContentType("text/html;charset=UTF-8");
        PrintWriter out = resp.getWriter();
        if (flag) {
            //用户名已存在,不可用
            out.print("<font color='red'>对不起,用户名已存在</font>");
        }else {
            // 用户名不存在,可以使用
            out.print("<font color='green'>用户名可以使用</font>");
        }
    }

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

8.创建json对象

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>json test</title>
</head>
<body>
<script type="text/javascript">

    // 在javascript语言中怎么创建一个json对象呢? 语法是什么?
    //     var jsonobj = {
    //         "属性名1" : 属性值,
    //         "属性名2" : 属性值,
    //         "属性名3" : 属性值,
    //         "属性名4" : 属性值,
    //         "属性名5" : 属性值
    //     }
    //
    //     注意:
    //         属性值的数据类型,那就随意了。可能是数字,可能是布尔类型,可能是字符串,可能是数组....

    // 另一个json对象
    var address = {
        "city" : "北京",
        "street" : "北京大兴区",
        "zipcode" : "123456"
    }

    var user = {
        "usercode" : 111,
        "username" : "zhangsan",
        "sex" : true,
        "age" : 20,
        "hobbies" : ["抽烟","喝酒","烫头"],
        "addr" : address
    }


    // 访问json对象的属性
    // 第一种方式
    console.log(user.username)
    console.log(user.usercode)
    console.log(user.sex ? "男" : "女")
    console.log(user.age)

    for (var i  = 0; i < user.hobbies.length ; i++) {
        console.log(user.hobbies[i])
    }

    // 访问这个用户是哪个街道的?
    console.log(user.addr.street)

    //第二种方式
    console.log(user["usercode"])
    console.log(user["username"])
    console.log(user["sex"] ? "男的" : "女的")
    console.log(user["age"])

</script>
</body>
</html>

基于JSON的数据交换

  • 在WEB前端中,如何将一个json格式的字符串转换成json对象
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>json test2</title>
</head>
<body>
<script type="text/javascript">

    // 这是一个json对象
    var user = {
        "username" : "zhangsan",
        "password" : "123456"
    }

    // 是json对象,才能这样访问。
    alert(user.username + "," +user.password)

    // 从服务器端返回来的不是一个json对象,是一个json格式的字符串 , \转义字符
    var fromJavaServerJsonStr = "{\"usercode\" : 111, \"age\" : 20}"

    // 有两种方式:
    // 第一种方式:使用eval函数。(javascript中的内容)
    // 第二种方式:调用javascript语言中的内置对象JSON的一个方法parse
    var jsonobj = JSON.parse(fromJavaServerJsonStr);
    alert(jsonobj.usercode + "," +jsonobj.age)
</script>
</body>
</html>

9.连接数据库动态拼接JSON字符串

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>发送AJAX请求,显示学生列表</title>
</head>
<body>

<script type="text/javascript">
    window.onload = function (){
        document.getElementById("btn").onclick = function(){
            // 1.创建核心对象
            var xhr = new XMLHttpRequest();
            // 2.注册回调函数
            xhr.onreadystatechange = function (){
                if (this.readyState == 4) {
                    if (this.status == 200) {
                        // document.getElementById("stutbody").innerHTML = this.responseText
                        // 将json格式的字符串转换成json对象
                        var stuList = JSON.parse(this.responseText);// 是一个数组,并且数组中有多个学生数据
                        var html = ""
                        for (var i = 0; i < stuList.length; i++) {
                            var stu = stuList[i]
                            html += "<tr>"
                            html += "<td>"+(i+1)+"</td>"
                            html += "<td>"+stu.name+"</td>"
                            html += "<td>"+stu.age+"</td>"
                            html += "<td>"+stu.addr+"</td>"
                            html += "</tr>"
                        }
                        document.getElementById("stutbody").innerHTML = html
                    }else{
                        alert(this.status)
                    }
                }
            }
            // 3.开启通道
            xhr.open("GET","/ajax1/ajaxrequest5",true)
            // 4.发送请求
            xhr.send()
        }
    }
</script>

<input type="button" value="显示学员列表" id="btn">
<table width="50%" border="1px">
    <thead>
        <tr>
            <th>序号</th>
            <th>姓名</th>
            <th>年龄</th>
            <th>住址</th>
        </tr>
    </thead>

    <tbody id="stutbody">
        <!--<tr>-->
        <!--    <td>1</td>-->
        <!--    <td>张三</td>-->
        <!--    <td>20</td>-->
        <!--    <td>北京大兴区</td>-->
        <!--</tr>-->
        <!--<tr>-->
        <!--    <td>2</td>-->
        <!--    <td>李四</td>-->
        <!--    <td>22</td>-->
        <!--    <td>北京海淀区</td>-->
        <!--</tr>-->
    </tbody>
</table>
</body>
</html>
package com.feng;

import javax.jws.WebService;
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;
import java.io.PrintWriter;
import java.sql.*;

/**
 * @auther fengpeng
 * @date 2022/9/12
 */
@WebServlet("/ajaxrequest5")
public class AjaxRequest5Servlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //连接数据库,查询学员信息,拼接HTML代码,响应HTML代码到浏览器(这里就不再连接数据库了,写死了)
        resp.setContentType("text/html;charset=UTF-8");
        PrintWriter out = resp.getWriter();

        //连接数据库,拼接HTML代码
        StringBuilder html = new StringBuilder();

        // 目前存在的缺点:在后端的java代码中又开始拼接HTML代码了。显然这是在后端java中写前端的HTML代码。不好维护。
        // 能不能直接将数据返回,给WEB前端数据就行了。让WEB前端能够拿到数据就行,然后页面展示的功能交给WEB前端来处理。
        // 我们后端的java代码能不能只返回数据???可以。(返回数据可以采用JSON的格式,也可以采用XML的格式)
        //  html.append("<tr>");
        //  html.append("<td>1</td>");
        //  html.append("<td>张三</td>");
        //  html.append("<td>20</td>");
        //  html.append("<td>北京大兴区</td>");
        //  html.append("</tr>");
        //  html.append("<tr>");
        //  html.append("<td>2</td>");
        //  html.append("<td>李四</td>");
        //  html.append("<td>22</td>");
        //  html.append("<td>北京海淀区</td>");
        //  html.append("</tr>");
        //
        //out.print(html);

        // 将以上程序拼接HTML,换成拼接JSON格式的字符串
        //String jsonStr =  "[{\"name\":\"王五\",\"age\":20,\"addr\":\"北京大兴区\"},{\"name\":\"李四\",\"age\":22,\"addr\":\"北京海淀区\"}]";


        // 准备StringBuilder对象,拼接JSON
        StringBuilder json = new StringBuilder();
        String jsonStr = "";
        // 连接数据库,查询所有的学生,拼接json字符串
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            // 1.注册驱动
            Class.forName("com.mysql.cj.jdbc.Driver");
            // 2.获取连接
            conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC","root","fp");
            // 3.获取预编译的数据库操作对象
            String sql = "select name,age,addr from mybatis.t_student";
            ps = conn.prepareStatement(sql);
            // 4.执行SQL语句
            rs = ps.executeQuery();
            json.append("[");
            // 5.处理结果集
            while(rs.next()) {
                // 获取每个学生的信息
                String name = rs.getString("name");
                String age = rs.getString("age");
                String addr = rs.getString("addr");
                // 拼接json格式的字符串
                // {"name":"   王五   ","age":   20   ,"addr":"  北京大兴区   "}
                json.append("{\"name\":\"");
                json.append(name);
                json.append("\",\"age\":");
                json.append(age);
                json.append(" ,\"addr\":\"");
                json.append(addr);
                json.append("\"},");
            }
            jsonStr = json.substring(0,json.length()-1) + "]";
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            // 6.释放资源
            if (rs != null) {
                try {
                    rs.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
            if (ps != null) {
                try {
                    ps.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }

        }

        //响应JSON格式的字符串给前端。/
        out.print(jsonStr);
    }

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

10.fastjson

package com.feng.fastjson;

import com.alibaba.fastjson.JSON;

import java.util.ArrayList;
import java.util.List;

public class FastjsonTest {
    public static void main(String[] args) {
        //创建一个User类型的对象
        User user = new User("111", "zhangsan", 20);

        //将以上的User对象转换为json格式的字符串
        //使用阿里巴巴的fastjson组件中的JSON类即可。
        //fastjson中又一个类,叫做:JSON。全部大写。
        //JSON类中的方法都是静态的方法,直接调用即可。
        String jsonstr = JSON.toJSONString(user);
        System.out.println(jsonstr);

        //尝试List集合是否可以转换成数组
        List<User> userList = new ArrayList<>();
        User user1 = new User("111", "lisi", 20);
        User user2 = new User("111", "wangwu", 20);
        userList.add(user1);
        userList.add(user2);
        String jsonStr2 = JSON.toJSONString(userList);
        System.out.println(jsonStr2);
    }
}

image-20221003214031730

11.基于XML的数据交换

  • 注意:如果服务器端响应XML的话,响应的内容类型需要写成:
resp.setContentType("text/xml;charset=utf-8");
  • xml和JSON都是常用的数据交换格式
    • XML体积大,解析麻烦,较少用。
    • JSON体积小,解析简单,较常用。
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>使用XML完成数据交换</title>
</head>
<body>
<script type="text/javascript">
    window.onload = function (){
        document.getElementById("btn").onclick = function (){
            //1.创建XMLHttpRequest对象
            var xhr = new XMLHttpRequest();
            //2.注册回调函数
            xhr.onreadystatechange = function (){
                if (this.readyState == 4) {
                    if (this.status == 200) {
                        //服务器端响应了一个XML字符串,这里怎么接收呢?
                        //使用XMLHttpRequest对象的responseXML属性,接收返回之后,可以自动封装成document对象(文档对象)
                        var xmlDoc = this.responseXML
                        // console.log(xmlDoc)
                        //获取所有的<student>元素,返回了多个对象,应该是数组。
                        var students = xmlDoc.getElementsByTagName("student")
                        // console.log(student[0].nodeName)
                        var html = ''
                        for (var i = 0; i < students.length; i++) {
                            var student = students[i]
                            //获取<student>元素下的所有子元素
                            html+="<tr>"
                            html+="<td>" +(i+1)+"</td>"
                            var nameOrAge = student.childNodes
                            for (var j = 0; j < nameOrAge; j++) {
                                var node = nameOrAge[j]
                                if (node.nodeName = "name") {
                                    html += "<td>" +node.textContent+"</td>"
                                }
                                if (node.nodeName == "age") {
                                    html += "<td>" +node.textContent+"</td>"
                                }
                            }
                            html += "</tr>"
                        }
                        document.getElementById("stutbody").innerHTML = html
                    }else {
                        alert(this.status)
                    }
                }
            }
            //3.开启通道
            xhr.open("GET","/f/ajaxrequest6",true);
            //4.发送请求
            xhr.send();
        }
    }
</script>
<button id="btn">显示学生列表</button>
<table width="500px" border="1px">
    <thead>
        <tr>
            <th>序号</th>
            <th>姓名</th>
            <th>年龄</th>
        </tr>
    </thead>
    <tbody id="stutbody">
        <tr>
            <td>1</td>
            <td>zhangsan</td>
            <td>20</td>
        </tr>
        <tr>
            <td>2</td>
            <td>lisi</td>
            <td>22</td>
        </tr>
    </tbody>
</table>
</body>
</html>
package com.feng.fastjson;

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;
import java.io.PrintWriter;

/**
 * @Author feng peng
 * @Date 2022/10/4
 * @Time 9:13
 */
@WebServlet("/ajaxrequest6")
public class AjaxRequest6Servlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //注意:响应的内容类型是XML。
        resp.setContentType("text/xml;charset=UTF-8");
        PrintWriter out = resp.getWriter();
        /*
        * <students>
            <student>
            *   <name>zhangsan</name>
            *   <age>20</age>
        *   </student>
        * </student>
        *<students>
            <student>
            *   <name>lisi</name>
            *   <age>22</age>
        *   </student>
        * </student>
        *
        * */


        StringBuilder xml = new StringBuilder();
        xml.append("<students>");
        xml.append("student>");
        xml.append("<name>zhangsan</name>");
        xml.append("<age>20</age>");
        xml.append("</student>");
        xml.append("</students>");

        xml.append("<students>");
        xml.append("student>");
        xml.append("<name>lisi</name>");
        xml.append("<age>22</age>");
        xml.append("</student>");
        xml.append("</students>");
        out.print(xml);
    }

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

12.AJAX乱码问题

  • 测试内容:

    • 发送ajax get请求
      • 发送数据到服务器,服务器获取的数据是否乱码?
      • 服务器响应给前端的中文,会不会乱码?
    • 发送ajax post请求
      • 发送数据到服务器,服务器获取的数据是否乱码?
      • 服务器响应给前端的中文,会不会乱码?
  • 包括还要测试tomcat服务器的版本:

    • tomcat9 测试。

      • 响应中文的时候,会出现乱码,怎么解决?
      response.setContentType("text/html;charset=UTF-8");
      
      • 发送ajax post请求的时候,发送给服务器的数据,服务器接收之后乱码,怎么解决?
      request.setCharacterEncoding("UTF-8");
      

13.AJAX的异步和同步

  • 什么是异步?什么是同步?
    • ajax请求1和ajax请求2,同时并发,谁也不用等谁,这就是异步。(a不等b,b也不等a)
    • 如果ajax请求1在发送的时候需要等待ajax请求2结束之后才能发送,那么这就是同步。(a等待b,或者b等待a,只要发生等待,就是同步。)
  • 异步和同步在代码如何实现?
//假设这个是ajax请求1
//如果第三个参数是false:这个就表示"ajax请求1"不支持异步,也就是说ajax请求1发送之后,会影响其他的ajax请求的发送,只有当我这个请求结束之后,你们其他的ajax请求才能发送。
xhr1.open("请求方式","URL",false)
xhr1.send()
    
//假设这个是ajax请求2
//如果第三个参数是true:这个就表示"ajax请求2"支持异步请求,也就是说ajax请求2发送之后,不影响其他的ajax请求的发送。
xhr2.open("请求方式","URL",true)
xhr2.send()
  • 什么情况下用同步?(大部分情况下我们都是使用ajax异步方式,同步很少用。)
    • 举一个列子
      • 用户注册
        • 用户名需要发送ajax请求进行校验
        • 邮箱地址也需要发送ajax请求校验。
        • 其他的也可能需要发送ajax请求。。。
        • 并且最终注册按钮的时候,也是发送ajax请求进行注册。
        • 那么显然,注册的Ajax请求和校验的ajax请求不能异步,必须等待所有的校验ajax请求结束之后,注册的ajax请求才能发。
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>演示ajax同步和异步</title>
</head>
<body>
<script type="text/javascript">
    window.onload = function () {
        document.getElementById("btn1").onclick = function () {
            var xhr = new XMLHttpRequest();
            xhr.onreadystatechange = function () {
                if (xhr.readyState == 4) {
                    if (xhr.status == 200) {
                        document.getElementById("div1").innerHTML = this.responseText
                    }else {
                        alert(status)
                    }
                }
            }
            // xhr.open("GET","/ajax/ajaxrequest8?"+ new Date().getTime(),true)
            // 我不支持异步了,我这个请求只要发,你们都得靠边站。都得等着我结束你们才能发请求。
            xhr.open("GET","/ajax/ajaxrequest8?"+ new Date().getTime(),false)
            xhr.send()
        }

        document.getElementById("btn2").onclick = function () {
            var xhr = new XMLHttpRequest();
            xhr.onreadystatechange = function () {
                if (xhr.readyState == 4) {
                    if (xhr.status == 200) {
                        document.getElementById("div2").innerHTML = this.responseText
                    }else{
                        alert(status)
                    }
                }
            }
            xhr.open("GET","/ajax/ajaxrequest9?"+ new Date().getTime(),true)
            xhr.send()
        }
    }
</script>
<button id="btn1">ajax请求1</button>
<div id="div1"></div>
<button id="btn2">ajax请求2</button>
<div id="div2"></div>
</body>
</html>
package com.feng;

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;

/**
 * @Author feng peng
 * @Date 2022/10/4
 * @Time 17:37
 */
@WebServlet("/ajaxrequest8")
public class AjaxRequest7Servlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        try {
            Thread.sleep(10*1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        response.setContentType("text/html;charset=UTF-8");
        response.getWriter().print("ajax请求1");
    }

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

package com.feng;

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;

/**
 * @Author feng peng
 * @Date 2022/10/4
 * @Time 17:38
 */
@WebServlet("/ajaxrequest9")
public class AjaxRequest8Servlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        response.getWriter().print("ajax请求2");
    }

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

13.AJAX代码封装

  • AJAX请求相关的代码都是类似的,有很多重复的代码,这些重复的代码能不能不写,能不能封装一个工具类。要发送ajax请求的话,就直接调用这个工具类中的相关函数即可。
  • 接下来,手动封装一个工具类,这个工具类我们可以把它看做是一个JS的库。我们把这个JS库起一个名字,叫做jQuery。(我这里封装的jQuery只是一个前端的库,和后端的java没有关系,只是为了方便web前端代码的编写,提高WEB前端的开发效率)

13.1 js中类的相关回顾

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>回顾javascript中类的定义,对象的创建。属性的访问,方法的访问。</title>
</head>
<body>
<script type="text/javascript">
    // 在JS当中怎么定义一个类
    function User(usercode,username){
        //属性
        this.usercode = usercode;
        this.username = username;
        // 方法(实例方法,通过对象调用的。)
        this.doSome = function (){
            console.log(username + " doSome....")
        }

        // 静态方法(直接用类名调用)
        User.doOther = function (){
            console.log("user doOther....")
        }
    }

    //第二种定义类
    /* User = function (usercode,username){
        //属性
        this.usercode = usercode;
        this.username = username;
        // 方法(实例方法,通过对象调用的。)
        this.doSome = function (){
            console.log(username + " doSome....")
        }

        // 静态方法(直接用类名调用)
        User.doOther = function (){
            console.log("user doOther....")
        }
    }*/


    // 创建对象,访问对象的属性,访问对象的方法,访问静态方法
    // User(); 直接这样调用,你只是把它当做一个普通的函数去执行,不会创建对象,在堆中没有这个对象。
    // new User(); 这样调用的话,其实就是调用该类的构造方法,创建对象,并且在堆中分配空间。
    var user = new User("111","zhangsan");
    //访问属性
    alert(user.usercode+ "," +user.username)
    //调用方法(实例方法)
    user.doSome()
    // 调用静态方法
    User.doOther()

    // 后期如果想给某个类型扩展方法,还可以使用prototype属性
    User.prototype.扩展的 = function (){
        console.log("打印。。。")
    }

    user.扩展的()
</script>
</body>
</html>

13.2 自己封装jQuery

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>手动封装JS库jQuery</title>
</head>
<body>
<script type="text/javascript">
    /*封装一个函数,通过这个函数可以获取到html页面中的节点,这个函数我给他起一个名字,叫做: jQuery*/
    /*要封装的代码是:根据id来获取元素。document.getElementById("btn")*/
    /*设计思路来自于CSS的语法。 #id 可以获取到这个元素*/
    function jQuery(selector){   /*selector可能是#id,也可能是其他的选择器,例如类选择器: .class  也可以是任何类型(弱类型)*/
        // 根据id获取元素
        if (typeof selector == "string") {
            if(selector.charAt(0) == "#"){
                // selector是一个id选择器
                /*var domObj = document.getElementById(selector.substring(1))*/

                //升级成全局变量
                domObj = document.getElementById(selector.substring(1))

                //返回的dom对象
                // return domObj

                //返回的jQuery对象
                return new jQuery()
            }
        }


        //页面加载完毕之后,注册回调函数。
        if (typeof selector == "function") {
            window.onload = selector
        }

        // 定义一个html()函数,代替: domObj.innerHTML = ""
        this.html = function (htmlStr){
            domObj.innerHTML = htmlStr
        }

        // 定义一个click()函数,代替: domObj.onclick = function(){}
        this.click = function (fun){
            domObj.onclick = fun
        }

        this.val = function (v){
            if (v == undefined) {
                return domObj.value
            }else{
                domObj.value = v
            }
        }


    }

    $ = jQuery

/*    window.onload = function (){
        /!* document.getElementById("btn").onclick = function (){
            document.getElementById("div1").innerHTML = "<font color='red'>用户名不可用!!!</font>"
        }*!/

        /!*  jQuery("#btn").onclick = function (){
            jQuery("#div1").innerHTML = "<font color='red'>用户名不可用!!!</font>"
        }*!/

        $("#btn").onclick = function (){
            $("#div1").innerHTML = "<font color='red'>用户名不可用!!!</font>"
        }

    }*/


    /* $(function (){} 作用是什么?*/
    /* 只要你写上以上的代码,就表示在页面加载完毕之后,执行里面的回调函数。*/
    /*$(function (){
        $("#btn").onclick = function (){
            $("#div1").innerHTML = "<font color='red'>用户名不可用!!!</font>"
        }
    })*/  /*$--> jQuery   (function)--> 传递了一个函数   */

    $(function (){
        $("#btn").click(function (){
            $("#div1").html("<font color='red'>用户名不可用!!!</font>")

            // 获取到文本框中的用户名
          /* var username = document.getElementById("username").value
            alert(username)*/

            var username = $("#username").val();
            alert(username)

            // 修改文本框的value
            // document.getElementById("username").value = "呵呵"
            $("#username").val("呵呵。。。。")
        })
    })

</script>
用户名:<input type="text" id="username">

<button id="btn">显示信息</button>

<div id="div1"></div>
</body>
</html>

把封装的jQuery放入js文件中

function jQuery(selector){
    if (typeof selector == "string") {
        if(selector.charAt(0) == "#"){
            domObj = document.getElementById(selector.substring(1))
            return new jQuery()
        }
    }
    if (typeof selector == "function") {
        window.onload = selector
    }
    this.html = function (htmlStr){
        domObj.innerHTML = htmlStr
    }
    this.click = function (fun){
        domObj.onclick = fun
    }
    this.val = function (v){
        if (v == undefined) {
            return domObj.value
        }else{
            domObj.value = v
        }
    }
}
$ = jQuery

测试封装的jQuery

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>测试我们自己编写的jQuery库(jQuery本质上就是JS的库)</title>
</head>
<body>

<!--使用jQuery库的第一件事,是把jQuery库引进来-->
<script type="text/javascript" src="js/jQuery-1.0.0.js"></script>
<script type="text/javascript">
    $(function (){
        $("#btn").click(function (){
            // alert("hello")
            // 获取文本框内容
            alert($("#usercode").val())
            //修改文本框的value
            $("#usercode").val("张三")
            //设置div内容
            $("#mydiv").html("我们自己封装的div!!!")
        })
    })
</script>

<button id="btn">hello</button>
<br>
用户代码:<input type="text" id="usercode">
<br>
<div id="mydiv"></div>
</body>
</html>

13.3 手动开发jQuery,源代码

jQuery.js

function jQuery(selector){
    if (typeof selector == "string") {
        if(selector.charAt(0) == "#"){
            domObj = document.getElementById(selector.substring(1))
            return new jQuery()
        }
    }
    if (typeof selector == "function") {
        window.onload = selector
    }
    this.html = function (htmlStr){
        domObj.innerHTML = htmlStr
    }
    this.click = function (fun){
        domObj.onclick = fun
    }
    this.val = function (v){
        if (v == undefined) {
            return domObj.value
        }else{
            domObj.value = v
        }
    }

    //静态的方法,发送ajax请求
    /**
     *  分析:使用ajax函数发送的ajax请求的时候,需要程序员给我们传过来什么?
     *      请求的方式(type): GET/POST
     *      请求的URL(url): url
     *      请求时提交的数据(data): data
     *      请求时发送异步请求还是同步请求(async): true表示异步,false表示同步。
     *
     */
    jQuery.ajax = function (jsonArgs){
        //1.
        var xhr = new XMLHttpRequest();
        //2.
        xhr.onreadystatechange = function (){
            if (xhr.readyState == 4) {
                if (xhr.status == 200) {
                    // 我们这个工具类在封装的时候,先不考虑那么多,假设服务器返回的都是json格式的字符串。
                    var jsonObj = JSON.parse(this.responseText)
                    // 调用函数
                    jsonArgs.success(jsonObj)

                }
            }
        }

        if(jsonArgs.type.toUpperCase() == "POST"){
            //3.
            xhr.open("POST",jsonArgs.url,jsonArgs.async)
            //4.
            xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded")
            xhr.send(jsonArgs.data)
        }

        if (jsonArgs.type.toUpperCase() == "GET") {
            xhr.open("GET",jsonArgs.url + "?" +jsonArgs.data,jsonArgs.async)
            xhr.send()
        }
    }
}
$ = jQuery

new jQuery()

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>测试我们自己手动开发的jQuery库</title>
</head>
<body>
<!--引入自己写的jQuery库-->
<script type="text/javascript" src="js/jQuery-1.0.0.js"></script>

<script type="text/javascript">
    $(function (){
        $("#btn1").click(function (){
            //发送ajax请求
            $.ajax({
                // type : "GET",
                type : "POST",
                url : "/ajax/ajaxrequest11",
                data : "username=" + $("#username").val(),
                async : true,
                success : function (json){
                    $("#div1").html(json.uname)
                }
            })
        })
    })
</script>
<button id="btn1">发送ajax请求</button>
<br>
用户名: <input type="text" id="username">
<br>
<div id="div1"></div>

</body>
</html>
package com.feng;

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;
import java.util.Locale;

/**
 * @Author feng peng
 * @Date 2022/10/5
 * @Time 17:47
 */
@WebServlet("/ajaxrequest11")
public class AjaxRequest10Servlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String username = request.getParameter("username");
        response.setContentType("text/html;charset=UTF-8");
        //{"username","zhangsan"}
        response.getWriter().print("{\"uname\":\""+username.toUpperCase()+"\"}");
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String username = request.getParameter("username");
        response.setContentType("text/html;charset=UTF-8");
        //{"username","zhangsan"}
        response.getWriter().print("{\"uname\":\""+username.toLowerCase()+"\"}");
    }
}
		
  • 使用以上库,怎么用?
<!--引入自己写的jQuery库-->
<script type="text/javascript" src="js/jQuery-1.0.0.js"></script>
<script type="text/javascript">
    $(function (){
        $("#btn1").click(function (){
            //发送ajax请求
            $.ajax({
                // type : "GET",
                type : "POST",
                url : "/ajax/ajaxrequest11",
                data : "username=" + $("#username").val(),
                async : true,
                success : function (json){
                    $("#div1").html(json.uname)
                }
            })
        })
    })
</script>

14.AJAX实现省市联动

  • 什么是省市联动?

    • 在网页上,选择对应的省份之后,动态的关联出该省份对应的市。选择对应的市之后,动态的关联出该市对应的区。(首先要清楚需求)
  • 进行数据库表的设计

    • t_area (区域表)
      id(PK-自增)      code           name              pcode
      -------------------------------------------------------
          1             001           河北省              null
          2             002           河南省              null
          3             003           石家庄              001
          4             004           邯郸                001
          5             005           郑州                002
          6             006           洛阳                002
          7             007           丛台区              004
      

      将全国所有的省,市,区,县等信息都存储到一张表当中。

      采用的存储方式实际上是code pcode形式。

自定义的jQuery库:

function jQuery(selector){
    if (typeof selector == "string") {
        if(selector.charAt(0) == "#"){
            domObj = document.getElementById(selector.substring(1))
            return new jQuery()
        }
    }
    if (typeof selector == "function") {
        window.onload = selector
    }
    this.html = function (htmlStr){
        domObj.innerHTML = htmlStr
    }
    this.click = function (fun){
        domObj.onclick = fun
    }
    this.change = function (fun){
        domObj.onchange = fun
    }
    this.val = function (v){
        if (v == undefined) {
            return domObj.value
        }else{
            domObj.value = v
        }
    }

    //静态的方法,发送ajax请求
    /**
     *  分析:使用ajax函数发送的ajax请求的时候,需要程序员给我们传过来什么?
     *      请求的方式(type): GET/POST
     *      请求的URL(url): url
     *      请求时提交的数据(data): data
     *      请求时发送异步请求还是同步请求(async): true表示异步,false表示同步。
     *
     */
    jQuery.ajax = function (jsonArgs){
        //1.
        var xhr = new XMLHttpRequest();
        //2.
        xhr.onreadystatechange = function (){
            if (xhr.readyState == 4) {
                if (xhr.status == 200) {
                    // 我们这个工具类在封装的时候,先不考虑那么多,假设服务器返回的都是json格式的字符串。
                    var jsonObj = JSON.parse(this.responseText)
                    // 调用函数
                    jsonArgs.success(jsonObj)

                }
            }
        }

        if(jsonArgs.type.toUpperCase() == "POST"){
            //3.
            xhr.open("POST",jsonArgs.url,jsonArgs.async)
            //4.
            xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded")
            xhr.send(jsonArgs.data)
        }

        if (jsonArgs.type.toUpperCase() == "GET") {
            xhr.open("GET",jsonArgs.url + "?" +jsonArgs.data,jsonArgs.async)
            xhr.send()
        }
    }
}
$ = jQuery

new jQuery()

定义类,用于json格式传参:

package com.feng.beans;


/**
 * @Author feng peng
 * @Date 2022/10/5
 * @Time 22:25
 */
public class Area {
    private String code;
    private String name;

    public Area() {
    }

    public Area(String code, String name) {
        this.code = code;
        this.name = name;
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

}

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>省市联动</title>
</head>
<body>
<!--引入我们自己编写的jQuery库-->
<script type="text/javascript" src="js/jQuery-1.0.0.js"></script>
<script type="text/javascript">
    $(function (){
        //发送ajax请求,获取所有的省份。省份的pcode是null
        $.ajax({
            type: "get",
            url: "/ajax/listArea",
            data: "t="+ new Date().getTime(),
            async: true,
            success: function (jsonArr){ /*在jQuery库中,把返回的json字符串解析成json对象返回。*/
                // [{"code":"001","name":"河北省"},{"code":"002","name":"河南省"}]
                // 以上格式的json是我们自己设计出来的,希望服务器能够给我们返回这样一个json格式的字符串。
                var html = "<option value=''>--请选择省份--</option>";
                for (var i = 0; i < jsonArr.length; i++) {
                    var area = jsonArr[i]
                    html += "<option value='"+area.code+"'>" +area.name+ "</option>"
                }
                $("#province").html(html)
            }
        })

        // 只要change发生,就发送ajax请求
        /*jQuery库中记得写change事件*/
        $("#province").change(function (){
            // alert("发送ajax请求")
            // alert(this)
            // alert(this.value)

            //发送ajax请求
            $.ajax({
                type: "get",
                url: "/ajax/listArea",
                data: "t="+ new Date().getTime()+"&pcode=" + this.value,
                async: true,
                success: function (jsonArr){
                    // [{"code":"006","name":"xxx"},{"code":"008","name":"yyyy"}]
                    var html = "<option value=''>--请选择市--</option>";
                    for (var i = 0; i < jsonArr.length; i++) {
                        var area = jsonArr[i]
                        html += "<option value='"+area.code+"'>" +area.name+ "</option>"
                    }
                    $("#city").html(html)
                }
            })
        })
    })
</script>

<select id="province">
<!--    <option value="">请选择省份</option>
    <option value="001">河北省</option>
    <option value="002">河南省</option>-->

</select>
<select id="city">

</select>
</body>
</html>
package com.feng.servlet;

import com.alibaba.fastjson2.JSON;
import com.feng.beans.Area;

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;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;

/**
 * @Author feng peng
 * @Date 2022/10/5
 * @Time 22:09
 */
@WebServlet("/listArea")
public class ListAreaServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String pcode = request.getParameter("pcode");
        // 连接数据库,获取所有的对应区域。最终响应一个JSON格式的字符串给WEB前端。
        Connection conn = null;
        PreparedStatement ps =null;
        ResultSet rs = null;
        List<Area> areaList = new ArrayList<>();
        try {
            // 注册驱动
            Class.forName("com.mysql.cj.jdbc.Driver");
            // 获取连接
            String url = "jdbc:mysql://localhost:3306/mybatis?userUnicode=true&characterEncoding=UTF-8";
            String user = "root";
            String password = "fp";
            conn = DriverManager.getConnection(url,user,password);
            // 获取预编译数据库操作对象
            String sql = "";
            if (pcode == null) {
                sql = "select code,name from t_area where pcode is null";
                ps = conn.prepareStatement(sql);
            }else{
                sql = "select code,name from t_area where pcode = ?";
                ps = conn.prepareStatement(sql);
                ps.setString(1,pcode);
            }
            // 执行SQL
            rs = ps.executeQuery();
            // 处理结果集
            while (rs.next()) {
                String code = rs.getString("code");
                String name = rs.getString("name");
                Area a = new Area(code,name);
                areaList.add(a);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            // 释放资源
            if (rs != null) {
                try {
                    rs.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
            if (ps != null) {
                try {
                    ps.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
        }

        response.setContentType("text/html;charset=UTF-8");
        // 使用fastjson将java对象转换成json字符串。
        String json = JSON.toJSONString(areaList);
        // 响应JSON。
        response.getWriter().print(json);
    }
}

15.AJAX 跨域

15.1 理解

image-20221006091206071

超链接可以跨域吗?

配置两个Tomcat

image-20230606211809508

image-20230606211826627

image-20230606212014622

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>a应用的index页面</title>
</head>

<body>
<!--通过超链接的方式可以跨域吗?-->
<a href="http://localhost:8082/b/index.html">b的index页面(跨域访问)</a>

</body>
</html>

image-20230606212111446

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>b应用的index页面</title>
</head>
<body>
<h1>b应用的index页面</h1>
</body>
</html>

运行测试

image-20230606212246466

form表单发送请求可以跨域吗?

image-20230606214710201

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>a应用的index页面</title>
</head>

<body>
<!--通过超链接的方式可以跨域吗?-->
<a href="http://localhost:8082/b/index.html">b的index页面(跨域访问)</a>

<!--form表单发送请求可以跨域吗?-->
<form action="http://localhost:8082/b/user/reg" method="post">
    用户名:<input type="text" name="username"><br>
    密码:<input type="password" name="password"><br>
    <input type="submit" value="注册">
</form>
</body>
</html>

image-20230606214816978

UserRegServlet

package com.feng.servlet;

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("/user/reg")
public class UserRegServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 获取用户名和密码
        String username = req.getParameter("username");
        String password = req.getParameter("password");

        //响应到前端
        resp.getWriter().print(username+" : " + password);
    }

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

运行测试

image-20230606215004505

image-20230606215120322