目录
在前端与后端的交互过程中,HTTP 协议起着核心作用,同时多种技术协同实现数据的请求与响应。下面将对相关技术进行详细阐述。
一、HTTP 协议基础
HTTP(HyperText Transfer Protocol)是浏览器与服务器通信的协议,它规定了请求和响应的格式。
(一)请求报文
- 请求行:包含请求方法(如 GET、POST 等)、请求路径和协议版本,例如post /index.html HTTP/1.1 。GET 请求主要用于获取资源,其参数会直接附加在 URL 后面;POST 请求则常用于提交数据,参数位于请求体中。
- 请求头:携带请求的相关信息,像请求资源的域名(Host)、端口、HTTP 版本、浏览器类型、语言、编码、缓存控制、内容类型等。这些信息有助于服务器理解请求的上下文,例如Content-Type字段用于告知服务器请求体的数据类型。
- 空行:用于隔离请求头和请求体,虽然看似简单,但在 HTTP 协议中是必不可少的分隔标识。
- 请求体:GET 请求时,请求体为空;POST 请求时,请求体可包含表单数据、JSON 数据等内容。例如在用户登录场景中,POST 请求体可包含用户名和密码。
(二)响应报文
- 响应行:由协议版本、状态码和状态描述组成,如HTTP/1.1 200 OK 。状态码是服务器对请求处理结果的重要标识,不同的状态码代表不同的含义。
- 响应头:包含响应的相关信息,如内容类型(Content-Type)、内容长度、日期、服务器信息等。Content-Type指定了响应体的数据类型,比如text/html表示 HTML 页面,application/json表示 JSON 数据。
- 空行:隔离响应头和响应体,确保协议格式的规范性。
- 响应体:服务器返回的结果,例如 HTML 页面内容<html>...</html> ,或者 JSON 格式的数据{"message": "success"} 。
(三)状态码
- 200 OK:表示请求成功,这是最常见的成功状态码,意味着服务器已成功处理请求并返回了相应数据。
- 404 Not found:请求的资源不存在,当用户访问一个不存在的页面或文件时,服务器会返回此状态码。
- 403 Forbidden:禁止访问,通常是由于用户没有足够的权限访问请求的资源。
- 401 Unauthorized:未授权访问,一般是因为用户未提供有效的身份验证信息。
- 400 Bad Request:错误的请求,可能是由于请求格式不正确、参数缺失或错误等原因导致。
- 500 Internal Server Error:服务器内部错误,这是服务器端出现了未预料到的错误情况。
通过浏览器控制台的 Network 选项,可以查看 HTTP 请求的详细过程,包括请求头、请求体、响应头和响应体等信息。这对于调试和分析前端与后端的交互非常有帮助。
二、请求参数相关
(一)Query String 参数
在 URL 中,参数以?key=value的形式添加,多个参数用&分隔,例如http://www.example.com/index.html?name=john&age=25 。在请求头中,参数以key:value的形式存在,如Host: www.example.com 、Content-Type: application/x-www-form-urlencoded 。这种参数传递方式简单直观,常用于向服务器请求特定资源。
(二)GET 与 POST 请求区别
- 参数位置:GET 请求参数在 URL 中,POST 请求参数在请求体中。这使得 GET 请求的参数可见,而 POST 请求的参数相对隐蔽。
- 数据量限制:GET 请求受 URL 长度限制,不能发送大量数据;POST 请求无此限制,适合发送大量数据,如文件上传。
- 功能差异:GET 请求主要用于请求资源,一般不修改服务器数据;POST 请求可用于请求资源和修改服务器数据,如提交表单、创建新资源等。
- 安全性:GET 请求参数暴露在 URL 中,安全性较低;POST 请求相对较高,但仍需注意防范 CSRF 等攻击。
三、Node.js 相关
(一)安装与检测
可从https://nodejs.org/en下载安装 Node.js。安装完成后,在命令提示符中输入node -v,若出现版本信息,则表示安装成功。Node.js 是基于 Chrome V8 引擎的 JavaScript 运行时,它使得 JavaScript 可以在服务器端运行,为前端后端交互提供了强大的支持。
(二)http 模块使用
- 创建 HTTP 服务器,并传入处理请求的回调函数。在回调函数中,我们可以获取请求参数和请求体,从而对请求进行处理。
- 在回调函数中获取请求参数和请求体。通过req对象,我们可以获取请求的各种信息,如请求方法、请求头、请求体等。
- 设置响应头。使用res.setHeader方法设置响应头,例如设置Content-Type 、Content-Length等。
- 响应数据。使用res.end方法将响应数据发送给客户端。
- 启动服务器并监听指定端口。通过server.listen方法启动服务器,并指定监听的端口号。
const http = require('http');
const server = http.createServer((req, res) => {
let body = '';
req.on('data', chunk => {
body += chunk.toString();
});
req.on('end', () => {
// 处理请求参数和请求体
res.setHeader('Content-Type', 'text/plain');
res.end('Hello, World!');
});
});
server.listen(3000, () => {
console.log('Server running at port 3000');
});
四、Express 框架使用
Express 是基于 Node.js 的 Web 开发框架,可快速搭建服务器。
(一)安装与初始化
在终端执行npm init --yes初始化项目,然后npm i express安装 Express,也可以使用npm list express查看安装版本。初始化项目会生成package.json文件,用于管理项目的依赖和配置。
(二)使用步骤
- 安装 Express 模块:npm install express --save 。--save选项会将 Express 添加到项目的依赖列表中。
- 导入 Express 模块:const express = require('express'); 。通过require方法导入 Express 模块,以便在项目中使用。
- 创建 HTTP 服务器:const app = express(); 。app对象是 Express 应用的核心,用于定义路由、中间件等。
- 设置路由:根据请求的 URL 执行相应的处理函数。路由是 Express 应用的重要组成部分,它决定了如何处理不同的请求。
app.get('/', (Request, Response) => {
Response.send('hello world');
});
app.post('/post - route', (Request, Response) => {
let data = Request.body;
Response.send('Received post data:'+ JSON.stringify(data));
});
- 启动服务器并监听端口:
app.listen(8000, () => {
console.log('服务器启动成功');
});
启动 Express 服务器时,在终端输入node 文件名,如node express基本使用.js。在浏览器地址栏输入http://127.0.0.1:8000/可查看响应结果。若要释放端口,按ctrl + C 。
五、Nodemon 工具
Nodemon 可帮助自动重启 Express 后台服务器。在终端执行npm install -g nodemon进行安装。安装完成后,使用nodemon 文件名启动服务器,如nodemon severs.js。当文件发生变化时,Nodemon 会自动检测并重启服务器,提高开发效率。
六、AJAX 技术
AJAX(Asynchronous JavaScript and XML)用于在不重新加载整个页面的情况下与服务器进行数据交互。
(一)使用 XMLHttpRequest 对象发送请求步骤
- 创建 XMLHttpRequest 对象:const xhr = new XMLHttpRequest(); 。XMLHttpRequest对象是 AJAX 的核心,用于发送 HTTP 请求和接收响应。
- 设置请求方式和请求地址:xhr.open('GET', 'http://www.example.com/api'); 。通过open方法设置请求的方法(GET、POST 等)和 URL。
- 设置请求头(可选):xhr.setRequestHeader('Content-Type', 'application/json'); 。根据需要设置请求头,如Content-Type 、Authorization等。
- 发送请求:xhr.send(); 。使用send方法发送请求,若为 POST 请求,可在send方法中传入请求体数据。
- 监听onreadystatechange事件,根据请求状态处理响应。readyState属性有 5 种值,0 表示未初始化,1 表示启动,2 表示发送,3 表示接收,4 表示完成。
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
console.log(xhr.responseText);
} else {
console.log('请求失败');
}
}
};
- 获取响应数据,可通过xhr.response(响应体)、xhr.responseText(响应文本数据)、xhr.responseXML(响应 XML 数据)、xhr.status(响应状态码)、xhr.statusText(响应状态字符串)、xhr.getAllResponseHeaders()(所有响应头)获取。
(二)JSONP 解决跨域(仅适用于 GET 请求)
JSONP 利用<script>标签的跨域能力发送请求。
<script src="http://127.0.0.1:8000/jsonp-server"></script> |
app.all("/jsonp-server", (request, response) => {
const data = {
name: "bdqn"
};
let str = JSON.stringify(data);
response.end(`handle(${str})`);
});
(三)CORS 解决跨域
通过设置响应头允许跨域请求。
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Headers", "*");
response.setHeader("Access-Control-Allow-Method", "*");
七、Axios 使用
Axios 是对原生 XMLHttpRequest 的封装,基于 Promise,可用于浏览器和 Node.js 的 HTTP 客户端。
(一)特点
能在浏览器和 Node.js 中发起请求、支持 Promise API、可拦截请求和响应、转换数据、取消请求以及自动转换 JSON 数据。这些特点使得 Axios 在前端开发中非常受欢迎。
(二)安装
通过 CDN 引入:<script src="https://unpkg.com/axios/dist/axios.min.js"></script> 。也可以使用npm install axios进行安装。
(三)基本使用
- 准备服务器:使用 json - server 模拟服务器。安装 json - server:npm install -g json-server ;创建数据源(如db.json);启动服务器,可使用json-server db.json 、json-server --watch db.json 或在package.json中配置别名后用npm run mock启动。
- 各种请求方式
// GET请求
axios.get('/axios-server', {
headers: {
id: "001"
}
}).then(response => {
console.log(response.data);
}, error => {
console.log(error.message);
});
// POST请求
axios.post('/axios - server', {
username: "admin",
password: "12345"
}).then(response => {
console.log(response.data);
}, error => {
console.log(error.message);
});
// PUT请求
axios.put('/axios - server/1', {
name: "newName"
}).then(response => {
console.log(response.data);
}, error => {
console.log(error.message);
});
// PATCH请求
axios.patch('/axios - server/1', {
name: "updatedName"
}).then(response => {
console.log(response.data);
}, error => {
console.log(error.message);
});
// DELETE请求
axios.delete('/axios - server/1').then(response => {
console.log(response.data);
}, error => {
console.log(error.message);
});
- 配置:配置优先级为请求配置 > 实例配置 > 全局配置。
// 全局配置
axios.defaults.timeout = 2000;
axios.defaults.baseURL = "http://localhost:3000";
// 实例配置
const instance = axios.create({
baseURL: "http://localhost:3000",
timeout: 2000
});
// 请求配置
axios.get("http://localhost:3000/list", {
timeout: 2000
});
- 拦截器:分为请求拦截器和响应拦截器。
// 请求拦截器
axios.interceptors.request.use(config => {
console.log("开启加载动画");
console.log("认证是否有token,如果没有,要去登录");
return config;
}, error => {
return Promise.reject(error);
});
// 响应拦截器
axios.interceptors.response.use(config => {
console.log("关闭加载动画");
console.log("对数据进行一些处理");
return config.data;
}, error => {
return Promise.reject(error);
});
(四)Vue 中使用 Axios
- 基本使用:通过npm install axios安装;在main.js文件中挂载到 Vue 原型:
import axios from 'axios'; Vue.prototype.$axios = axios; |
在组件中使用:
<button @click="getDate">点击发送请求</button>
<script>
export default {
name: 'App',
methods: {
async getDate() {
let res = await this.$axios.get('http://localhost:3000/list');
console.log(res.data);
}
}
}
</script>
- 一次封装:在src/utils目录下创建request.js文件进行封装。
import axios from "axios";
const request = axios.create({
baseURL: "http://localhost:3000",
timeout: 2000
});
request.interceptors.request.use(config => {
config.data = JSON.stringify(config.data);
config.headers = {
"Content-Type": "application/x-www-form-urlencoded"
};
const token = getCookie("名称");
if (token) {
config.params = { token: token };
config.headers.token = token;
}
return config;
}, error => {
return Promise.reject(error);
});
request.interceptors.response.use(response => {
console.log('关闭请求数据动画');
console.log('对数据进行处理');
return response.data;
}, error => {
return Promise.reject(error);
});
export default request;
在组件中引入使用:
<script>
import request from '../utils/request';
export default {
name: 'ShowList',
methods: {
async getList() {
let res = await request.get('/list');
console.log(res);
}
}
}
</script>
- 二次封装:在apis目录下创建相关 js 文件,定义具体请求函数。
// src/apis/showList.js
import request from "@/utils/request";
export function getListInfo1() {
return request.get("/list");
}
export function getUserInfo1() {
return request.get("/user");
}
在组件中导入使用:
<script>
import { getListInfo1, getUserInfo1 } from '../apis/showList';
export default {
name: 'ShowList',
methods: {
async getList1() {
let res = await getListInfo1();
console.log(res);
},
async getUser1() {
let res = await getUserInfo1();
console.log(res);
}
}
}
</script>
八、其他要点
(一)URL 编码
URL 编码用于将非 ASCII 字符转换为 ASCII 字符,非 ASCII 字符会被编码为%xx形式的十六进制字符,如 “你” 编码为%E4%BD%A0。这是为了确保 URL 能够正确传输和解析。
(二)跨域概念
同源要求协议、域名、端口号完全相同,违背同源策略即跨域。跨域会导致前端请求被浏览器拦截,需要通过一些技术手段(如 JSONP、CORS 等)来解决。
通过以上对 HTTP 协议、前端后端交互技术的详细介绍,有助于开发者深入理解并运用这些技术进行 Web 应用开发。在实际开发中,还