Web前端-Ajax(上)

目录

1 传统请求的缺点

2 Ajax概述

3 readyState状态值得理解

4  第一个Ajax请求详解

4.1 发送Ajax请求步骤

4.2 使用ajax发送get请求提交数据给服务器

4.3 POST请求模拟表单提交数据

5 验证用户名是否可用

6 基于JSON的数据交换

6.1 什么是JSON

6.2 在前端中如何将JSON字符串转为JSON对象

6.3 前后端进行JSON格式的字符串进行数据的交换

6.4 连接数据库得到JSON格式字符串数据

7 基于XML数据格式交换数据

8 关于乱码问题

9 Ajax的异步与同步


1 传统请求的缺点

为什么要学习Ajax?

传统请求方式有缺点:在之前我们学习发送请求的时候,每发送一次请求,页面就会刷新一次,也就是说当我在一个页面发送请求的时候,请求到另一个页面,整个页面就会变为请求后的页面。假如我正在看视频,视频正在缓存,但是这时我想登录,传统请求这时就会跳转到登录界面,我看的视频界面就没了,缓存也没了,需要重新打开视频,体验极差。

大概演示一下传统请求的请求是什么样子,下面是几个我们学过的请求:

这时的页面底层是这个样子:

我们点击一个请求:

我们发现页面直接刷新为请求后的页面了,大概这个意思。我们使用Ajax就可以使这两个页面变成一个页面,之前的请求就不用了。经典白学。

2 Ajax概述

  • Ajax全称为:Asynchronous JavaScript And Xml
  • Ajax不能称为一种技术,它是多种技术的综合产物,Ajax属于Web前端的JS代码,和后端的java没有关系,后端可以是别的语言比如C语言,php语言。
  • Ajax可以让浏览器发送一种特殊的请求,这种请求可以是异步的
  • 什么是异步,什么是同步?假设有两个线程t1和t2,t1和t2线程并发就是异步,t2在执行的时候必须等待t1执行完,它们是排队执行的,这是同步。
  • Ajax应用程序可能使用XML来传输数据,但将数据作为纯文本或JSON文本传输也同样常见
  • Ajax可以更新网页的部分,不需要加载整个页面。页面局部刷新
  • Ajax可以做到一个网页启动多个请求,类似多线程。

Ajax应用程序执行的过程是怎样的

  • 首先Web前端向服务器请求数据
  • 对于Ajax来说,服务器可能会给Web前端响应三种数据:普通文本;XML字符串;JSON字符串
  • Ajax会解析这些响应回来的数据,将解析之后的数据渲染到div图层中,这个div就更新了,这样页面就完成了局部刷新。

 那么学习Ajax之前要学习哪些内容呢,首先是JavaScript,我还不是很熟悉,再见,先滚去学JavaScript了。

3 readyState状态值得理解

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

  • 0:请求未初始化
  • 1:服务器连接已建立
  • 2:请求已收到
  • 3:正在处理请求
  • 4:请求已完成且响应已就绪

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

4  第一个Ajax请求详解

4.1 发送Ajax请求步骤

发送Ajax请求主要分为四步:

第一步:创建Ajax核心对象XMLHttpRequest,直接new就好

第二步:注册回调函数

  • 使用对象XMLHttpRequest调用onreadystatechange事件。得到一个回调函数,这个函数在XMLHttpRequest对象的readyState状态值发生改变的时候被调用。
  • 当XMLHttpRequest对象的readyState的状态是4的时候,表示响应结束了
  • 响应结束后一般会有一个HTTP的状态码
  • 常见的状态码包括:200表示成功了;404表示资源找不到;500表示服务器内部错误
  • 然后我们获取HTTP状态码,使用XMLHttpRequest对象的status方法得到
  • 得到状态码就可以根据状态码做选择,若是200则输出信息,通过XMLHttpRequest对象的responseText属性获取响应信息
  • 可以写一个div,然后将响应信息放到div图层中

第三步:开启通道(open只是浏览器和服务器建立连接,通道打开,并不会发送请求)

  • 其中open的参数的含义:
  • method:请求的方式——GET、POST、或者其它;
  • url:请求的路径;async:只能是true或者false,true表示ajax请求是一个异步请求,false则是同步请求。大部分是true;
  • user:用户名;pwd:
  • 密码,用户名和密码是进行身份验证的,说明想访问这个服务器上的资源可能需要提供一些口令才能访问,需不需要用户名和密码,服务器说了算。

第四步:发送请求,使用对象XMLHttpRequest的send方法

代码如下:

<!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请求
            //1.创建Ajax核心对象XMLHttpRequest
            var xhr = new XMLHttpRequest();
            //2.注册回调函数
            //这是一个回调函数,这个函数在XMLHttpRequest对象的readyState状态值发生改变的时候被调用
            xhr.onreadystatechange = function (){
                //这里的回调函数会被调用多次
                //console.log(xhr.readyState)
                //当XMLHttpRequest对象的readyState的状态是4的时候,表示响应结束了
                if (this.readyState == 4){
                    //响应结束
                    //alert("响应结束了")
                    //得到状态码
                    //alert(this.status)
                    //所以我们可以根据得到的状态码判断该做什么
                    if (this.status == 404){
                        alert("对不起,您访问的资源不存在,请检查请求路径")
                    }else if (this.status == 500){
                        alert("对不起,服务器内部发生严重错误,请联系管理员")
                    }else if (this.status == 200){
                        //响应成功
                        //alert("响应成功")
                        //通过XMLHttpRequest对象的responseText属性来获取响应信息
                        //alert(this.responseText)
                        //响应到div中
                        document.getElementById("mydiv").innerHTML = this.responseText
                    }
                }
            }
            //3.开启通道(open只是浏览器和服务器建立连接,通道打开,并不会发送请求)
            xhr.open("GET","/ajax/ajaxrequest",true)
            //4.发送请求
            xhr.send()
        }
    }
</script>

<input type="button" value="hello ajax" id="helloBtn">
<div id="mydiv"></div>
</body>
</html>
@WebServlet("/ajaxrequest")
public class AjaxServlet01 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        PrintWriter out = response.getWriter();
        out.write("hello ajax");
    }
}

4.2 使用ajax发送get请求提交数据给服务器

可以直接在请求路径后面加上?然后拼接请求内容如下:

            var username = document.getElementById("username").value
            var password = document.getElementById("password").value
            xhr.open("GET","/ajax/ajaxrequest2?username="+username+"&password="+password,true)

在重写ajax请求的代码时,出现一个错误,把onclick写成了click,焯!!

ajax get请求在低版本的ie浏览器上会出现缓存问题,就是访问同一个资源也就是url是同一个就会直接去找缓存而不是找服务器,这样当然速度会快,但是服务器更新了它依然找缓存,这就不好了,但是目前主流浏览器不存在这种问题了。。需要注意的是:post请求不会有缓存问题。

4.3 POST请求模拟表单提交数据

怎么使用AJax提交POST请求呢,肯定不能放在url后面进行请求,那是get请求了。可以放在send方法里面,要注意格式(name=value&name=value),其实就和get请求一样,不过是放在send函数中而已。但是这样还不够,我们还要send之前open之后执行setRequestHeader方法,它用来设置请求头的内容类型,用来模拟Ajax提交form表单,具体如下:

xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded")
var username = document.getElementById("username").value
var password = document.getElementById("password").value
xhr.send("username="+username+"&password="+password)

5 验证用户名是否可用

实现一个小案例:使用Ajax post请求实现用户注册的时候,用户名是否可用,实现步骤如下:

  • 在前端,用户输出用户名之后失去焦点事件blur发生,然后发送post请求,提交用户名
  • 在后端,接收用户名,连接数据库,根据用户名去表中搜索
  • 如果用户名存在,响应消息:对不起用户名已存在;如果用户名不存在响应消息:用户名可以使用

代码如下:

前端代码朴实无华,和上面差不多,主要展示后端代码:

package com.itzw.ajax.servlet;

import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.io.PrintWriter;
import java.sql.*;

@WebServlet("/ajaxrequest4")
public class AjaxServlet04 extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html");
        PrintWriter out = response.getWriter();
        String username = request.getParameter("username");
        //out.print("username:"+username);

        //连接数据库
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        //打布尔标记
        boolean ok = false;
        try {
            //注册驱动
            Class.forName("com.mysql.cj.jdbc.Driver");
            //获取连接
            String url = "jdbc:mysql://127.0.0.1:3306/db1";
            String user = "root";
            String password = "123456";
            conn = DriverManager.getConnection(url, user, password);
            //获取预编译的数据库操作对象
            String sql = "select username from t_user where username = ?";
            ps = conn.prepareStatement(sql);
            ps.setString(1,username);
            //执行SQL语句
            rs = ps.executeQuery();
            //处理结果集
            if (rs.next()){
                //有结果说明用户名重复
                ok = true;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            //释放资源
            if (rs != null) {
                try {
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (ps != null) {
                try {
                    ps.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
        //判断前端该输出什么内容
        if (ok){
            //用户名重复
            out.print("<font color='red'>用户名重复,请重新输入</font>");

        }else {
            //用户名可以使用
            out.print("<font color='green'>用户名可以使用</font>");
        }

    }
}

6 基于JSON的数据交换

我们发现目前存在的缺点:当我们想将数据传到前端,需要在后端进行java代码和HTML代码的拼接,这显然是非常愚蠢的,我们能不能直接将数据返回,让web前端能够拿到数据就行。当然可以,返回数据可以采用JSON的格式,也可以是XML格式,重点在JSON。

6.1 什么是JSON

这个在JavaScript中学过,这里简单回顾一下

<script type="text/javascript">
    //这样就可以创建一个JSON对象
    //JSON对象中的属性可以存任何类型,包括数组甚至另一个JSON对象,和java一样可以套娃
    var user = {
        "name":"王德发",
        "age":18,
        "hobby":["抽烟","喝酒","烫头"]
    }
    //这样就可以获取JSON对象中的数据
    alert(user.name)
    alert(user.hobby[0])
</script>

6.2 在前端中如何将JSON字符串转为JSON对象

有两种方式

第一种:使用eval函数

第二种:调用JavaScript语言中的内置对象JSON的一个方法parse即可。

第一种JavaScript中讲到过,第二种比较简单,下面演示一下第二种:

    //这是从java中获取到的JSON格式的字符串数据
    var fromJavaData = "{\"username\":\"张麻子\",\"password\":\"123456\"}";
    //这样就可以将字符串转为JSON对象
    var jsonObj = JSON.parse(fromJavaData)

6.3 前后端进行JSON格式的字符串进行数据的交换

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<script type="text/javascript">
    window.onload = function () {
        document.getElementById("displayStu").onclick = function (){
            var xhr = new XMLHttpRequest()
            xhr.onreadystatechange = function (){
                if (this.readyState == 4){
                    if (this.status == 200){
                        //得到学生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.sno+"</td>"
                            html+="<td>"+stu.name+"</td>"
                            html+="<td>"+stu.addr+"</td>"
                            html+="</tr>"
                        }
                        //把拼接的结果放到tbody中
                        document.getElementById("stubody").innerHTML = html
                    }else {
                        //失败
                        alert(this.status)
                    }
                }
            }
            xhr.open("GET","/ajax/ajaxrequest5",true)
            xhr.send()
        }
    }
</script>

<input type="button" id="displayStu" value="展示学员列表">
<table border="1px" width="50%">
    <tr>
        <th>序号</th>
        <th>学号</th>
        <th>姓名</th>
        <th>住址</th>
    </tr>
    <tbody id="stubody">
    </tbody>
</table>
</body>
</html>

后端模拟从数据库得到数据

        PrintWriter out = response.getWriter();
        //模拟从数据库获取到的数据
        String stuList = "[{\"sno\":\"110\",\"name\":\"王德发\",\"addr\":\"南京市\"},{\"sno\":\"120\",\"name\":\"张麻子\",\"addr\":\"北京市\"}]";
        out.print(stuList);

6.4 连接数据库得到JSON格式字符串数据

我们可以连接数据库得到数据然后一点点将得到的数据拼成JSON格式的字符串,显然这个很麻烦,还好有个工具可以使用,这个工具为:fastjson-1.2.2,它是一个jar包,下面演示:

            List<Student> stuList = new ArrayList<>();
            while (rs.next()){
                String sno = rs.getString("sno");
                String name = rs.getString("name");
                String addr = rs.getString("addr");
                Student s = new Student(sno,name,addr);
                stuList.add(s);
            }
            //将list集合转为JSON字符串
            jsonStr =  JSON.toJSONString(stuList);

这个jar包有个JSON类,用它调用toJSONString方法即可,需要注意的是,若想使用这个方法,需要先创建一个类,然后将数据封装到这个类里面然后再把它放在toJSONString里转换。演示:

7 基于XML数据格式交换数据

使用xml格式交换数据使用较少,这里演示一下即可

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<script type="text/javascript">
    window.onload = function (){
        document.getElementById("displayStu").onclick = function (){
            var xhr = new XMLHttpRequest()
            xhr.onreadystatechange = function (){
                if (this.readyState == 4){
                    if (this.status == 200){
                        //使用XMLHttpRequest对象的responseXML属性接收,可以自动封装成document对象(文档对象)
                        var xmlDoc = this.responseXML
                        //console.log(xmlDoc)
                        //获取所有<student>元素,返回多个对象,应该是个数组
                        var students = xmlDoc.getElementsByTagName("student")
                        //console.log(students[0])
                        var html = ""
                        for (var i = 0; i < students.length; i++) {
                            var student = students[i]
                            //获取student元素下的所有子元素
                            html += "<tr>"
                            html += "<td>"+(i+1)+"</td>"
                            var namOrAge = student.childNodes
                            for (var j = 0; j < namOrAge.length; j++) {
                                var node = namOrAge[j]
                                if (node.nodeName == "name"){
                                    //console.log(node.textContent)
                                    html += "<td>"+node.textContent+"</td>"
                                }
                                if (node.nodeName == "age"){
                                    //console.log(node.textContent)
                                    html += "<td>"+node.textContent+"</td>"
                                }
                            }
                            html += "<tr>"
                        }

                    document.getElementById("stuInfo").innerHTML = html
                    }else {
                        alert(this.status)
                    }
                }
            }
            xhr.open("GET","/ajax/ajaxrequest6",true)
            xhr.send()
        }
    }
</script>
<input type="button" value="展示学生信息" id="displayStu">
<table border="1px" width="50%">
    <tr>
        <td>序号</td>
        <td>姓名</td>
        <td>年龄</td>
    </tr>
    <tbody id="stuInfo">
    </tbody>
</table>
</body>
</html>

后端提交的数据:

        //response.setContentType("text/xml");
        PrintWriter out = response.getWriter();
        StringBuilder stuXML = new StringBuilder();
        stuXML.append("<students>");
        stuXML.append("    <student>");
        stuXML.append("        <name>马邦德</name>");
        stuXML.append("        <age>43</age>");
        stuXML.append("    </student>");
        stuXML.append("    <student>");
        stuXML.append("        <name>张麻子</name>");
        stuXML.append("        <age>44</age>");
        stuXML.append("    </student>");
        stuXML.append("</students>");
        out.print(stuXML);

8 关于乱码问题

对于tomcat10来说不需要考虑乱码问题,都给我用10,nnd

对于tomcat9来说:

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

9 Ajax的异步与同步

大部分情况下都是使用异步,但有时我们需要使用同步,比如在我们注册时:需要输入很多信息,在这些信息验证(验证用户名是否符合要求之类的)前不能进行注册,所以这时使用异步就会出现问题,同步等待前面信息验证完才能进行注册

到目前为止Ajax的基本语法就结束了

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值