前后端交互

前后端交互

一、前后端交互基本概念

网络应用的分类

网络应用分为BS架构和CS架构这两类。BS架构指Browser+Server,浏览器+服务器的组合。CS架构指Client+Server,客户端+服务器的组合。

服务器:

从硬件的角度来说服务器是在互联网上的一台(一群)远程计算机。从软件角度来说服务器是运行在计算机上的服务端程序。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0iPfD69M-1663896962966)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220708094908775.png)]

客户端:

狭义上的的客户端指安装在客户机(手机、电脑、平板)上的应用程序。

浏览器:

通过在浏览器上运行的网页与服务端程序进行数据交互

CS:Client端展示数据、收集数据 Server端存储数据、传输数据。

BS:Broswe端展示数据、收集数据 Server端存储数据、传输数据。

广义上的客户端指用户使用的程序。

网络传输协议

客户端与服务器要进行数据交互依赖通讯协议。在WEB应用中广泛使用的是HTTP协议。HTTP协议是应用层协议。HTTP协议底层是TCP/IP协议。

TCP/IP:协议明确了计算机之间要进行数据传输的基本条件。

  • 进行数据交互两台计算机必须在同一个网络中(互联网或局域网)。
  • 每一台计算机在网络中都有一个唯一的网络地址(IP地址)
  • IP地址分为外网地址和内网地址。在同一个内网中的计算机可以使用内网地址找到对方。
  • 在计算机中有6万多个端口,每一个网络应用在运行时都可以和某一个端口进行绑定。我们向某一台计算机上的应用发送数据,其实是在向这台计算机的某一个端口发送信息。

HTTP协议:HTTP是一种应用层协议,它对数据传输的细节、数据的含义、数据的格式进行了规范。

HTTP中有两个重要的术语:请求响应

请求指客户端程序向服务端程序发送数据的过程。

响应指服务端程序向客户端程序发送数据的过程。

目前的WEB程序基本都是请求+响应这种数据交互模型。

如何向服务器发送请求?

客户端需要通过接口地址向服务器发送请求。接口地址的组成:http://IP:端口/接口名称

向服务器发送请求时需要发送哪些数据?

  • 请求方式method (get/post/put/patch/delete)

  • 请求类型contentType(form/data、json)

  • 请求参数方式:发送给服务器的业务数据(地址栏参数、请求体参数)

  • **请求参数的格式:**服务要求传哪些数据必须传哪些数据。

    具体采用何种方式、何种类型、参数使用什么传递方式由服务器决定,作为前端只需要按照服务器的要求发送请求就行。后端会为前端开发人员提供接口文档,文档中会详细的说明一个接口的请求方式、请求类型以及参数发送方式。

服务器响应给客户端的数据有哪些?

服务器会响应HTTP请求状态到客户端。该状态代表了本次请求的执行状态。

常见状态如下:

200:表示成功,服务器收到了客户端的请求并成功的响应了数据。

401:表示传输的参数格式不满足服务器的要求。

404:表示发送请求的地址不存在

500:表示服务器出现错误

服务器还会将本次请求的业务数据(JSON)响应到客户端。

当我们在进行增删改操作时,服务器只需要响应本次增删改的执行结果。

当我们在执行查询操作时,服务器除了响应本次的执行结果之外,还会将查询的数据一起响应。

二、AJAX

客户端首先需要向服务器发送请求,服务器被动的向发送请求的客户端响应数据。

AJAX的全称 Asynchronous Java Script And XML(异步的javascript和XML)。是js中的一种异步的使用了HTTP作为通讯协议的前后端数据交互技术。

例如要通过Ajax访问和风天气接口,接口文档如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VvS0VJo5-1663896962968)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220708141807762.png)]

从文档中我们发现如下信息:

请求地址:https://devapi.qweather.com/v7/weather/now?[请求参数]

请求方式:get

请求参数:地址栏参数

参数内容:key和location,key是密钥、location城市经纬度或者城市ID

编码实现过程

//1.创建XMLHttpRequest对象
let xhr=new XMLHttpRequest();
//2.设置请求方式和请求地址
xhr.open("GET","https://devapi.qweather.com/v7/weather/now?key=3676a20663e243ebb45d5d24ec313519&location=101040100");
//3.添加onreadystatechange事件监听ajax请求状态的变化(状态发生改变事件触发)
xhr.onreadystatechange=function(){
    //ajax请求状态为4 HTTP请求状态为200表示服务器正确的响应了数据
    if(xhr.readyState==4&&xhr.status==200){
    	let text=xhr.responseText;
        let data=JSON.parse(text);
    }
}
//4.发送请求
xhr.send();

Jquery的Ajax编码实现过程

$.ajax({
    url:"https://devapi.qweather.com/v7/weather/now?key=3676a20663e243ebb45d5d24ec313519&location=101040100",//请求地址,默认是当前页面地址
    type:"GET",//请求方式
    //data:传递给服务器的数据
    dataType:"JSON",//确定服务器响应的数据类型,Jquery便于转换
    success:function(data){//回调函数,Juqery在服务器响应数据以后调用该回调
        //data表示的是服务器响应到客户端的数据
    }
});

除了Ajax函数之外,Jquery还提供了get和post的API。

AJax的异步

Ajax的异步指请求在发出以后,程序不会就此阻塞,而是会继续向下执行,在这种情况下我们无法在ajax的请求发出以后立刻去获取数据的。异步优势是效率高,劣势是当我们多个ajax请求之间有依赖关系时(发送第二个AJAX请求需要第一个请求拿到的数据),Ajax要通过嵌套的形式来编写。

let key = "3676a20663e243ebb45d5d24ec313519";
        $("#search").click(function () {
            let id;
            let city = $("#city").val();
            //查询城市代号
            let searchCity = `https://geoapi.qweather.com/v2/city/lookup?key=${key}&location=${city}`;
            $.ajax({
                url: searchCity,
                type: "GET",
                dataType: "json",
                success: function (cityInfo) {
                    id = cityInfo.location[0].id;
                	 //查询城市天气
            let searchWeather = `https://devapi.qweather.com/v7/weather/now?key=${key}&location=${id}`;
            $.ajax({
                url: searchWeather,
                type: "GET",
                dataType: "json",
                success: function (weatherInfo) {
                    $("#img").prop("src", `../icons/${weatherInfo.now.icon}.svg`);
                    $("#weather").html(weatherInfo.now.text);
                    $("#temp").html(weatherInfo.now.temp);
                    $("#sd").html(weatherInfo.now.humidity);
                    $("#wind").html(weatherInfo.now.windDir);
                }
            });
                }
            });
        });

​ Ajax嵌套Ajax会造成回调地狱问题,Jquery的Ajax提供了一个可选参数,async,将其设置为false,则可以将异步Ajax设置为同步,在服务器响应数据之前,后面的代码会处于阻塞状态。

let key = "3676a20663e243ebb45d5d24ec313519";
        $("#search").click(function () {
            let id;
            let city = $("#city").val();
            //查询城市代号
            let searchCity = `https://geoapi.qweather.com/v2/city/lookup?key=${key}&location=${city}`;
            $.ajax({
                url: searchCity,
                type: "GET",
                dataType: "json",
                async: false,
                success: function (cityInfo) {
                    id = cityInfo.location[0].id;
                }
            });
            //查询城市天气
            let searchWeather = `https://devapi.qweather.com/v7/weather/now?key=${key}&location=${id}`;
            $.ajax({
                url: searchWeather,
                type: "GET",
                dataType: "json",
                success: function (weatherInfo) {
                    $("#img").prop("src", `../icons/${weatherInfo.now.icon}.svg`);
                    $("#weather").html(weatherInfo.now.text);
                    $("#temp").html(weatherInfo.now.temp);
                    $("#sd").html(weatherInfo.now.humidity);
                    $("#wind").html(weatherInfo.now.windDir);
                }
            });
        });

不同参数的传递方式

在Ajax请求中,data和contentType需要根据服务器接口文档的要求灵活的传值。当接口文档中对于参数的要求是body(请求体参数)时,需要给data传值。data传值的方式由contentType来决定,默认的contentType是用于传递表单参数的。

  • 在body中传表单参数

    在body中传入表单参数要求是传入如下的数据格式:name=张三&gender=1&age=18的字符串数据。我们可以自己将表单控件的数据取出拼成字符串,也可以使用Jquery提供serialize()函数

    let form=$("#insert-form").serialize();
    console.log(form);
    $.ajax({
        url: "http://192.168.90.79:8080/student",
        type: "post",
        data: form,
        dataType:"json",
        success:function(data){
            if(data.code=="200"){
                //调用select函数
                select();
            }
        }
    })
    
  • 在body中传JSON参数

    在body中传入JSON参数要求是传入一个JSON格式的字符串。我们可以自己定义一个对象将数据先使用对象存储起来,然后使用JSON.stringify(对象)转为JSON字符串。也可以使用jquery.serializejson.js中的serializeJSON()从一个表单中获取一个数据对象,再将对象转为JSON字符串。同时一定要注意contentType必须设置为application/json。

    //使用Juqery的API将一个表单中的所有数据转为JSON对象
    let json=$("#insert-form").serializeJSON();
    $.ajax({
        url: "http://192.168.90.79:8080/student",
        type: "post",
        data: JSON.stringify(json),//将JSON对象转为字符串
        contentType:"application/json",
        dataType:"json",
        success:function(data){
            if(data.code=="200"){
                //调用select函数
                select();
            }
        }
    })
    
  • 地址栏参数

    目前后端的地址栏参数,基本都是接口地址/参数的方式。

    let id=$(this).closest("tr").children(":first").html();
    $.ajax({
        url:`http://192.168.90.79:8080/student/${id}`,
        type:"delete",
        dataType:"json",
        success:function(data){
            if(data.code=="200"){
                select();
            }
        }
    })
    

文件上传

  • 最简单的单个文件上传

    <input type="file" id="file">
        <input type="button" value="上传头像" id="upload-btn">
            <script>
            $("#upload-btn").click(function(){
            //FormData是表单数据对象,通过该对象可以将表单中包含文件类的信息一起存储起来
            //FormData的使用步骤:
            //1.创建一个空的FormData对象
            let formData=new FormData();
            //2.将数据保存到FormData中,文件数据来源于表单控件
            let files=$("#file")[0].files;
            formData.append("file",files[0]);
            //通过Ajax上传文件
            $.ajax({
                url:"http://192.168.90.79:8080/student/upload",
                type:"post",
                contentType:false,//contentType设置为false的目的是为了让Jquery将contentType值设置为multipart/form-data
                processData:false,//processData是Jquery内部的参数转换开关,打开时只要参数不是字符串就会将其转为字符串,但是文件数据是二进制数据不能转为字符串,将开关关闭
                data:formData,//当formData时 contentType默认就是multipart/form-data
                success:function(data){
                    console.log(data);
                }
            })
        });
    
  • 带预览功能的带进度条的文件上传

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <script src="../js/jquery-3.6.0.js"></script>
        <style>
            * {
                margin: 0;
                padding: 0;
            }
    
            .file-list {
                width: 80%;
                margin: 0 auto;
                border-right: 1px solid #ccc;
                border-bottom: 1px solid #ccc;
            }
    
            .file-list td,
            .file-list th {
                height: 50px;
                text-align: center;
                border-top: 1px solid #ccc;
                border-left: 1px solid #ccc;
            }
    
            .progress-box {
                width: 90%;
                height: 40px;
                margin: 0 auto;
                background-color: #EEE;
            }
    
            .progress {
                width: 0%;
                height: 40px;
                background-color: green;
            }
        </style>
    </head>
    
    <body>
        <input type="file" id="file">
        <input type="button" value="上传" id="upload-btn">
        <table class="file-list">
            <tr>
                <td width="10%">文件名称</td>
                <td width="20%">预览图</td>
                <td width="10%">文件大小</td>
                <td width="10%">类型</td>
                <td width="50%">进度</td>
            </tr>
            <!-- <tr>
                <td>girl.png</td>
                <td><img src="../img/id10.jpg" height="100px"></td>
                <td>2.4M</td>
                <td>PNG</td>
                <td>
                    <div class="progress-box">
                        <div class="progress"></div>
                    </div>
                </td>
            </tr> -->
        </table>
        <script>
            //给文件域绑定change事件
            $("#file").change(function () {
                //取出文件域中的第一个文件
                let file = $("#file")[0].files[0];
                let name = file.name;
                let size = (file.size / 1024 / 1024).toFixed(2) + "M";
                let type = file.type;
                //使用FileReader读取出文件内容
                let reader = new FileReader();
                //读取文件内容需要时间,使用onload事件监听文件读取完毕
                reader.onload = function () {
                    //先清除之前的tr
                    $(".file-list tr:gt(0)").remove();
                    //拼接tr标签
                    let tr = `
                            ${name}
                            ${reader.result}" height="100px">
                            ${size}
                            ${type}
                            
                                
    `
    ; $(".file-list").append(tr); } //读取文件的内容 reader.readAsDataURL(file); }); //给文件上传按钮绑定点击事件 $("#upload-btn").click(function () { //FormData的使用步骤: //1.创建一个空的FormData对象 let formData = new FormData(); //2.将数据保存到FormData中,文件数据来源于表单控件 let files = $("#file")[0].files; formData.append("file", files[0]); //通过Ajax上传文件 $.ajax({ url: "http://192.168.90.79:8080/student/upload", type: "post", contentType: false,//contentType设置为false的目的是为了让Jquery将contentType值设置为multipart/form-data processData: false,//processData是Jquery内部的参数转换开关,打开时只要参数不是字符串就会将其转为字符串,但是文件数据是二进制数据不能转为字符串,将开关关闭 data: formData,//当formData时 contentType默认就是multipart/form-data success: function (data) { alert(data.message); }, xhr:function(){ //为Jquery提供一个我们自己创建的XMLHttpRequest对象 //因为我们要为该对象绑定文件上传进度事件 let xhr=new XMLHttpRequest(); xhr.upload.onprogress=function(){ //在事件源对象中存储了已经上传的大小和总大小 let loaded=window.event.loaded;//已经上传的大小 let total=window.event.total; let width=loaded/total*100+"%"; $(".progress").css("width",width); } return xhr; } }) }); </script> </body> </html>
  • 知识点整理

如何获取文件域选中的文件:

//文件域标签对象中有属性files,保存文件域中所有选中的文件,一定是原生的DOM对象才具备该属性
document.getElementById("file").files;
doucment.querySelector("#file").files;
$("#file")[0].files

每一个文件对象中包含的属性:

let files=$("#file")[0].files;
files[下标].name;//文件名称
files[下标].size;//文件大小,单位B
files[下标].type;//文件类型

如何读取一个图片文件的内容:

//JS提供一个FileReader的对象,通过该对象可以读取图片的内容(Base64)
//1.创建FileReader对象
let reader=new FileReader();
//2.使用onload事件监听文件读取完毕
reader.onload=function(){
    console.log(reader.result);//Base64内容
    //img标签的src属性识别Base64数据,将内容设置到img的src属性中就可以使用img显示这张图片
}
//3.读取一个文件的内容
reader.readAsDataURL($("#file")[0].files[0]);//从文件域中取出File对象

如何监听文件上传进度

//XMLHttpRequest对象中的子对象upload可以绑定onprogress事件,它可以监听文件上传的进度
//问题:使用的是Jquery封装好的Ajax函数,无法取出其中的XMLHttpRequest对象,无法访问upload绑定事件
//解决办法:Jquery的Ajax允许我们传入一个回调函数,Jquery会调用该回调函数使用回调函数的返回值来替换原本的XMLHttpRequest对象,所以我们可以在回调函数中自己创建一个新的XMLHttpRequest对象,在该对象的upload中绑定onprogress事件,最后将XMLHttpRequest对象返回到函数调用处。
$.ajax({
    ......,
    xhr:function(){
    	let a=new XMLHttpRequest();
    	a.upload.onprogress=function(){
            //如何获取已经上传的文件大小和总大小
            //在事件源对象中保存了上传的大小和总大小
            window.event.loaded;//已经上传的大小
            window.event.total;//总大小
        }
    	return a;
	}
})
  • 多文件上传
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="../js/jquery-3.6.0.js"></script>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        .file-list {
            width: 80%;
            margin: 0 auto;
            border-right: 1px solid #ccc;
            border-bottom: 1px solid #ccc;
        }

        .file-list td,
        .file-list th {
            height: 50px;
            text-align: center;
            border-top: 1px solid #ccc;
            border-left: 1px solid #ccc;
        }

        .progress-box {
            width: 90%;
            height: 40px;
            margin: 0 auto;
            background-color: #EEE;
        }

        .progress {
            width: 0%;
            height: 40px;
            background-color: green;
        }
    </style>
</head>

<body>
    <input type="file" id="file" multiple>
    <input type="button" value="上传" id="upload-btn">
    <table class="file-list">
        <tr>
            <td width="10%">文件名称</td>
            <td width="20%">预览图</td>
            <td width="10%">文件大小</td>
            <td width="10%">类型</td>
            <td width="50%">进度</td>
        </tr>
        <!-- <tr>
            <td>girl.png</td>
            <td><img src="../img/id10.jpg" height="100px"></td>
            <td>2.4M</td>
            <td>PNG</td>
            <td>
                <div class="progress-box">
                    <div class="progress"></div>
                </div>
            </td>
        </tr> -->
    </table>
    <script>
        //给文件域绑定change事件
        $("#file").change(function () {
            //先清除之前的tr
            $(".file-list tr:gt(0)").remove();
            //取出文件域中的第一个文件
            for (let i = 0; i < $("#file")[0].files.length; i++) {
                let file = $("#file")[0].files[i];
                let name = file.name;
                let size = (file.size / 1024 / 1024).toFixed(2) + "M";
                let type = file.type;
                //使用FileReader读取出文件内容
                let reader = new FileReader();
                //读取文件内容需要时间,使用onload事件监听文件读取完毕
                reader.onload = function () {
                    $(`img:eq(${i})`).prop("src", reader.result);
                }
                //拼接tr标签
                let tr = `
                        ${name}
                        
                        ${size}
                        ${type}
                        
                            
`
; $(".file-list").append(tr); //读取文件的内容 reader.readAsDataURL(file); } }); //给文件上传按钮绑定点击事件 $("#upload-btn").click(function () { uploadFile();//调用文件上传函数 }); let index=0;//定义文件序号 //定义文件上传函数 function uploadFile() { let files = $("#file")[0].files; //FormData的使用步骤: //1.创建一个空的FormData对象 let formData = new FormData(); //2.将数据保存到FormData中,文件数据来源于表单控件 formData.append("file", files[index]); //通过Ajax上传文件 $.ajax({ url: "http://192.168.90.47:8080/student/upload", type: "post", contentType: false,//contentType设置为false的目的是为了让Jquery将contentType值设置为multipart/form-data processData: false,//processData是Jquery内部的参数转换开关,打开时只要参数不是字符串就会将其转为字符串,但是文件数据是二进制数据不能转为字符串,将开关关闭 data: formData,//当formData时 contentType默认就是multipart/form-data success: function (data) { if(index<files.length-1){ index++; uploadFile();//递 }else{ alert("上传成功");//归 } }, xhr: function () { //为Jquery提供一个我们自己创建的XMLHttpRequest对象 //因为我们要为该对象绑定文件上传进度事件 let a = new XMLHttpRequest(); a.upload.onprogress = function () { //在事件源对象中存储了已经上传的大小和总大小 let loaded = window.event.loaded;//已经上传的大小 let total = window.event.total; let width = loaded / total * 100 + "%"; $(`.progress:eq(${index})`).css("width", width); } return a; } }) } </script> </body> </html>
            //为Jquery提供一个我们自己创建的XMLHttpRequest对象
                //因为我们要为该对象绑定文件上传进度事件
                let a = new XMLHttpRequest();
                a.upload.onprogress = function () {
                    //在事件源对象中存储了已经上传的大小和总大小
                    let loaded = window.event.loaded;//已经上传的大小
                    let total = window.event.total;
                    let width = loaded / total * 100 + "%";
                    $(`.progress:eq(${index})`).css("width", width);
                }
                return a;
            }
        })
    }

```

你可能感兴趣的:(服务器,网络,http)