Node.js® 是一个基于 Chrome V8 引擎 的JavaScript 运行时环境。
Node.js介绍
Node.js可以做什么
Node.js作为一个JavaScript运行环境,仅仅提供了基础的功能和APi。然而,基于Node.js提供的这些基础功能,很多强大的工具和框架如雨后春笋,层出不穷,所以学习了Node.js,可以让前端程序员胜任更多的工作和岗位;
JavaScript 基础語法+Nodejs内置APl模块(s、path,http等)+第三方API模块(express.mysql 等)
区分LTS版本和Current 版本的不同
LTS为长期确定版,对于追求稳定性的企业级项目来说,推荐安装LTS版本的Node.j5.
Current为新特性类鲜版,对热表于装试新将性的用户来说,推荐安装Current 版本的Node js,但是,Current 版本中可
能存在隐副的Bug 呢安全性测同,因此不推荐在企业级项日中使用Current 版本的Node js。
ts模诀是Node,js官方提供的、用来操作文件的横诀,它提供了一系列的方法和属性,用来满足用户对文件的操作需求。
例如:
fs.readFile()
方法,用来读取指定文件中的内容
fs.witefile()
方法,用来向指定的文件中写入内容
如果要在JavaScript代码中,使用fs模块来操作文件,则需要使用如下的方式先导入官:
const fs = require('fs')
fs.witefile()
示例代码参数1:文件路径
参数2:编码格式
参数3:回调函数
function readFile(path, options, callback)
const fs = require('fs');
fs.readFile('input.txt', 'utf-8', function (err, data) {
if (err) {
return console.log("读取文件失败:" + err.message);
}
console.log("读取文件成功:" + data);
})
fs.witefile()
示例代码参数1:文件路径
参数2:写入内容
参数3:编码格式
参数4:回调函数
function writeFile(path, data, options, callback)
const fs = require('fs');
fs.writeFile('input.txt', "测试1", function (err) {
if (err) {
return console.log("文件写入内容失败!" + err.message)
}
console.log("文件写入成功");
})
__dirname
获取当前文件所属目录
在使用横块操作文件时,如果提供的操作路径是以./
成../
开头的相对路径
时,很容易出现路径动拼接错误的问题。
原因:代码在运行的时候,会以执行node命令时所处的目录
,动态拼接出被操作文件的完彪路径。
如果在input.txt上层目录执行node xxx/xxx.js 的话,如果出现错误读取不到文件,直接将./input.txt相对路径改为绝对路径读取。
const fs = require('fs');
fs.readFile('./input.txt', 'utf8', function (err, data) {
if (err) {
return console.log("读取文件失败" + err.message)
}
console.log("读取文件成功" + data);
})
//__dirname获取文件所处目录
const fs = require('fs');
fs.readFile(__dirname + '/input.txt', 'utf8', function (err, data) {
if (err) {
return console.log("读取文件失败" + err.message)
}
console.log("读取文件成功" + data);
console.log(__dirname)
})
path模块是Nodejs官方提供的、用来处理路径的模块。它提供了一系列的方法和属性,用来满足用户对路径的处理
例如:
path.join()
方法,用来将多个路径片段拼接成一个完整的路径字符串
path.basename()
方法,用来从路径字符申中,将文件名解析出来
如果要在JavaScript代码中,使用path模块来处理路径,则需要使用如下的方式先导入它:
const path = require('path')
使用
path.join0
方法,可以把多个路径片段拼接为完格的路径字符串:
const pathStr = path.join('/a', '/b/c', '../', './d', 'e')
console.log(pathStr)//指出\a\b\d\e
const pathStr2 = path.join(__dirname, '/files/1.txt')
console.log(pathStr2)//物出 当前文件所处目录\files\1.txt
path.basename()
的代码示例
使用path.basenam()
方法,可以从一个文件路径中,获取到文件的名称部分
basename(path: string, ext?: string)
const path = require("path");
const fpath = '/a/b/c/index.html';
let filename = path.basename(fpath);
//分割指定内容
let newFileName = path.basename(filename,".html");
console.log(filename);//index.html
console.log(newFileName)//index
使用 path.extname0方法,可以获取路径中的扩展名部分,语法格式如下:
path.extname(path)
参数解读:
const path = require("path");
const pathStr = "/a/b/c/index.html";
let extname = path.extname(pathStr);
console.log(extname)//.html
回顾:什么是客户端、什么是服务器?
在网络节点中,负责消费资源的电脑,叫做客户端;
负责对外提供网络资源
的电脑,叫做服务器。
http模块
是Node.js官方提供的、用来创建 web 服务器的模块
。通过http模块提供的http.createServer()
方法,就能方便的把一台普通的电脑,变成一台Web服务器,从而对外提供Web资源服务。如果要希望使用http模块创建Web服务器,则需要先导入它:
const http = require('http')
服务器和普通电脑的
区别
在于,服务器上安装了web服务器软件
,例如:IIS、Apache等。通过安装这些服务器软件,就能把一台普通的电脑变成一台web服务器。在
Node.js
中,我们不需要使用IIS、Apache等这些第三方web服务器款件。因为我们可以基于Node.js提供的
http模块,通过几行简单的代码,就能轻松的手写一个服务器软件,从而对外提供web服务。
①导入http模块
②创建 web 服务器实例
③为服务器实例绑定request事件,监听客户端的请求
④启动服务器
//导出http模块
const http = require('http');
//创建web服务器
const server = http.createServer();
//为服务器示例绑定request事件,监听客户端的请求
server.on('request', function (req, res) {
console.log("调用了request方法")
})
//启动服务器
server.listen(8080, function () {
console.log("访问http://127.0.0.1:8080 获取结果")
}
)
获取request里面的数据和属性参数
//导出http模块
const http = require('http');
let server = http.createServer();
// req是请求对象,包含了与客户端的数据和属性
server.on('request', (req, res) => {
const url = req.url;
const method = req.method;
const str = `url地址${url}, 方法是${method}`;
console.log(req);
console.log(str);
})
server.listen(8080, () => {
console.log('server running at http://127.0.0.1:8080');
})
响应结束
res.end();
解决中文乱码,设置Header
res.setHeader('Content-Type', 'application/json');
res.setHeader('Content-Type', 'text/html;charset=utf-8');
//response响应对象
const http = require('http');
let server = http.createServer();
// req是请求对象,包含了与客户端的数据和属性
server.on('request', (req, res) => {
const url = req.url;
const method = req.method;
const str = `url地址${url}, 方法是${method}`;
res.setHeader('Content-Type', 'text/html;charset=utf-8');
// res.setHeader('Content-Type', 'application/json');
res.end(str)
})
server.listen(8080, () => {
console.log('server running at http://127.0.0.1:8080');
})
const http = require('http');
let server = http.createServer();
server.on('request', function (req, res) {
//获取请求URL
let url = req.url;
let content = "404 Not found!
";
if (url === '/' || url === '/index.html') {
content = '首页
'
} else if (url === '/about.html') {
content = '关于页面
'
}
res.setHeader('Content-Type', 'text/html; charset=UTF-8');
res.end(content);
})
server.listen(8080, () => {
console.log("启动成功访问http://127.0.0.1:8080")
})
能够说出模块化的好处
能够知道CommonJS规定了哪些内容
能够说出Node.js中模块的三大分类各自是什么
能够使用npm管理包
能够了解什么是规范的包结构
能够了解模块的加载机制
编程领域中的模块化,就是遵守固定的规则,把一个大文件拆成独立并互相依赖的多个小模块。
把代码进行模块化拆分的好处:
模块化规范就是对代码进行模块化的拆分与组合时,需要遵守的那些规则。
例如:
模块化规范的好处
:大家都遵守同样的模块化规范写代码,降低了沟通的成本,极大方便了各个模块之间的相互调用,利人利己。Node.js中根据模块来源的不同,将模块分为了3大类,分别是:
内置模块
(内置模块是由 Node.js官方提供的,例如fs、path、http等)自定义横块
(用户创建的每个js文件,都是自定义横块)第三方模块
(由第三方开发出来的横块,并非官方提供的内置模块,也不是用户创建的自定义模块,使用前需要先下或)使用强大的require0方法,可以加载需要的内置模块、用户自定义模块、第三方模块进行使用。例如:
//1.加载内置的fs模块
const fs = require('fs')
//2.加载用户的自定义模块
const custom = require('./custom.js')
//3.加载箱三方模块(关于第三方模块的下载和使用,会在后面的课程中进行专门的讲解)
const moment = require('moment')
注意:使用 require0方法加载其它模块时,会执行被加载模块中的代码。
//使用 require0方法加载其它模块时,会执行被加载模块中的代码,在使用require0加载自定义模块可以省略.js后缀名`
const test = require('E:\\work2\\node-learning\\node基础\\01.使用readFile读取文件.js');
console.log(test)
//{}
//读取文件成功:测试1
和函数作用域类似,在自定义模块中定义的变量、方法等成员,只能在当前模块内被访问,这种模块级别的访问限制,叫做模块作用域。
防止了全局变量污染的问题,在模块内定义的成员不能被外部访问
在每个,js自定义横块中都有一个module 对象,它里面存储了和当前横块有关的信息,打印如下:
Module {
id: '.',
path: 'E:\\work2\\node-learning\\模块化',
exports: {},
parent: null,
filename: 'E:\\work2\\node-learning\\模块化\\04.module对象.js',
loaded: false,
children: [],
paths: [
'E:\\work2\\node-learning\\模块化\\node_modules',
'E:\\work2\\node-learning\\node_modules',
'E:\\work2\\node_modules',
'E:\\node_modules'
]
}
在自定义模块中,可以使用module.exports对象,将模块内的成员共享出去,供外界使用。
外界用require0方法导入自定义模块时,得到的就是module.exports所指向的对象。module.exports.username = ‘张三’ exports.username = '张三’指向的是同一个对象,一种简写方式
使用requireo方法导入模块时,导入的结果,
永远以module.exports 指向的对象为准
。
// { nikeName: '李四', test: [Function: test], aaa2: 25 }
module
变量代表当前模块module
变量是一个对象,module.exports
是对外的接口module.exports
属性
优先从缓存中加载
模块在第一次加载后会被缓存。这也意味看多次调用require()不会导致模块的代码被执行多次。
注意:不论是内置模块、用户自定义模块、还是第三方模块,它们都会优先从缓存中加载,从而提高模块的加载效率。
内置模块
是由Node.js官方
提供的模块,内置模块的加戦优先级最高。
例如,require(‘fs’)始终返回内置的fs模块,即使在node_modules目录下有名字相同的包也叫做fs.而不是加载第三方的
使用 require()加载自定义模块时,必须指定以
./
或../
开头的路径标识符。在加载自定义模块时,如果没有指定./
或../
这样的路径标识符,则node会把它当作内置模块
或第三方模块
进行加载。
同时,在使用requireO导入自定义模块时,如果省略了文件的扩展名,则Node.js会按顺序分别尝试加载以下的文件:
①按照确切的文件名进行加载
②补全js扩展名进行加载
③补全json扩展名进行加载
④补全.node扩展名进行加载
⑤加载失效,终端报错
如果传递给requir()的模块标识符不是一个内置模块,也没有以‘./’
或‘../’
开头,则Node.js会从当前模块的父目录开始,尝试从/node_modules 文件夹中加载第三方模块。如果没有找到对应的第三方模块,则移动到再上一层父目录中,进行加就,直到文件系统的根目录。
例如,假设在‘C:AUsersVitheima\project\
foo.js’文件里调用了require(‘tools’),则Node.js会按以下顺序查找:
①C:\Users\itheima\project\
node_modules\tools
②C:\Users\itheima\
node_modules\tools
③C:\Users
\node_modules\tools
④C:\
node_modules\tools
官方给出的概念:
Express
是基于Node.js
平台,快速、开放、极简的Web开发框架。通俗的理解:Express的作用和Node.js内置的http模块类似,是专门用来创建Web服务器的。
Express的本质
:就是一个npm上的第三方包,提供了快速创建Web服务器的便捷方法。
对于前端程序员来说,最常见的两种服务器,分别是:
Web 网站服务器
:专门对外提供Web 网页资源的服务器。API接口服务器
:专门对外提供API接口的服务器。使用Express,我们可以方便、快速的创建Web网站的服务器或APl接口的服务器。
安装依赖
node i [email protected]
//引入express模块
let express = require('express');
//创建服务器
let app = express();
//监听端口
app.listen(8080, () => {
console.log('express server running at http://localhost:8080');
})
//引入express
let express = require('express');
//创建服务器
let app = express();
//测试GET请求,获取参数
app.get('/user/:id/:name', function (req, res) {
let arrayData = [];
//获取动态参数,路径参数id,name
let params = req.params;
//获取query参数,查询条件
let query = req.query;
arrayData.push(params);
arrayData.push(query)
res.send(arrayData)
})
//测试POST请求获取参数
app.post('/user', (req, res) => {
res.send("请求成功")
})
//启动服务
app.listen(8080, () => {
console.log("测试GET POST请求,http://localhost:8080");
})
express.static()
方法可创建静态资源服务器,向外开放访问静态资源。const express = require('express');
const app = express();
//引入多个按照顺序加载,先去public找public没有然后去files文件夹找,http://localhost:8080/index.html
app.use(express.static("../public"))
app.use(express.static("../files"))
//指定访问前缀,指定访问前缀在访问静态文件需要添加上前缀http://localhost:8080/public/index.html
// app.use("/public", express.static("../public"))
app.listen(8080, () => {
console.log("访问静态文件http://localhost:8080")
})
在编写调试Node.js项目的时候,如果修改了项目的代码,则需要频繁的手动close掉,然后再重新启动,非常繁琐。现在,我们可以使用nodemon(https://www.npmjs.com/package/nodemon)这个工具,它能够监听项目文件的变动,当代码被修改后,nodemon会自动帮我们重启项目,极大方便了开发和调试。
npm i -g nodemon
当基于Node.js编写了一个网站应用的时候,传统的方式,是运行node app.js命令,来启动项目。这样做的坏处是代码被修改之后,需要手动重启项目。
现在,我们可以将node命令替换为nodemon
命令,使用nodemon app.js
来启动项目。这样做的好处是:代码被修改之后,会被nodemon
监听到,从而实现自动重启项目的效果。
node app.js
# 将上面的终端命令,替换为下血的终满命令,即可实现自动重启项目的效果
nodemon app.js
//1、导入express
const express = require('express');
//2、创建路由对象
const route = express.Router();
//添加get请求
route.get('/user/list', (req, res) => {
console.log("GET请求参数", req.query);
res.send(req.query)
})
//添加post请求
route.post('/user/add', (req, res) => {
console.log("POST请求参数", req.body);
res.send(req.body)
})
//导出路由对象
module.exports = route;
const express = require('express');
//引入Router自定义模块
const router = require('./04.路由简单用法Router');
//创建服务器
const app = express();
/**
* app.use()就是来注册全局中间件的
* 加载router模块,添加固定前缀api
* GET http://localhost:8080/api/user/list?aaa=123
* POST http://localhost:8080/api/user/add
*/
app.use('/api', router);
//启动服务
app.listen(8080, () => {
console.log("测试引用路由,http://localhost:8080")
})
req, res, next
三个参数,next()
参数把流转关系交给下一个中间件或路由中间件注意事项;
next()
函数next()
函数后别写代码req
、 res
对象app.use()
定义的中间件为全局中间件//1、引用express模块
const express = require('express');
//2、创建服务
const app = express();
//3、创建中间件函数
const mw = function (req, res, next) {
console.log("调用了中间件方法");
//最后必须要执行的方法,下一步
next();
}
//4、注册全局中间件
app.use(mw);
//创建中间件函数,并注册简化写法
// app.use(function (req, res, next) {
// console.log("调用了中间件方法");
// //最后必须要执行的方法,下一步
// next();
// });
//5、挂载方法
//挂载GET http://127.0.0.1:8080/
app.get('/', (req, res) => {
console.log("调用了/ 路由方法");
res.send("Home Page···")
})
//挂载GET http://127.0.0.1:8080/user
app.get('/user', function (req, res) {
console.log("调用了user 路由方法");
res.send('User Page···')
})
//6、启动服务
app.listen(8080, () => {
console.log("启动服务器http://127.0.0.1:8080");
})
//调用了中间件方法
//调用了/ 路由方法
可以使用
app.use()
连续定义多个全局中间件。客户端请求到达服务器之后,会按照中间件定义的先后顺序依次进行调用,示例代码如下:
const express = require('express');
const app = express();
app.use(function (req, res, next) {
console.log("第一个中间件函数")
next()
})
app.use(function (req, res, next) {
console.log("第二个中间件函数")
next()
})
app.get('/', (req, res) => {
console.log("调用get方法")
res.send("成功!")
})
app.listen(8080, () => {
console.log("服务启动成功,http://localhost:8080")
})
//http://localhost:8080/
//第一个中间件函数
//第二个中间件函数
//调用get方法
不使用
app.use()
定义的中间件,叫做局部生效的中间件
,示例代码如下:
const express = require('express');
let app = express();
const mw = function (req, res, next) {
console.log("局部生效中间件函数1")
req.startTime = new Date();
//必须
next()
}
const mw1 = function (req, res, next) {
console.log("局部生效中间件函数2")
req.startTime = new Date();
//必须
next()
}
app.get('/user', (req, res) => {
console.log("调用user方法", req.startTime);
res.send(req.startTime)
})
//设置局部生效中间件
app.get('/', mw, (req, res) => {
console.log("调用/方法", req.startTime);
res.send(req.startTime)
})
//设置多个局部生效中间件
app.get('/user/list1', mw, mw1, (req, res) => {
console.log("调用/方法", req.startTime);
res.send(req.startTime)
})
app.get('/user/list2', [mw, mw1], (req, res) => {
console.log("调用/方法", req.startTime);
res.send(req.startTime)
})
app.listen(8080, () => {
console.log("服务启动http://127.0.0.1:8080")
})
应用级别中间件
通过app.use()
或app.get()
或app.post()
,绑定到app实例上的中间件,叫做应用级别的中间件,代码示例如下:
//应用级别中间件(全局中间件)
app.use(function (req, res, next) {
console.log("全局中间件")
next()
})
//应用级别中间件(局部中间件)
const mw = function (req, res, next) {
console.log("局部生效中间件函数")
req.startTime = new Date();
//必须
next()
}
app.get('/', mw, (req, res) => {
console.log("调用/方法", req.startTime);
res.send(req.startTime)
})
路由级别中间件
绑定到express.Route()
实例上的中间件,叫做路由级别的中间件。它的用法和应用级别中间件没有任何区别。只不过,应用级别中间件是绑定到app实例上,路由级别中间件绑定到router实例上
,代码示例如下:
const express = require('express');
const router = express.Router();
//设置Router中间件
router.use(function (req, res, next) {
console.log("router级别中间件")
next();
})
//router绑定方法
router.get('/user', function (req, res) {
console.log("调用routerGET方法")
res.send("调用routerGET方法")
})
//向外暴露
module.exports = router
const express = require('express');
//引入05.router级别中间件自定义模块
const routerTest = require('./05.router级别中间件');
//创建服务器
let app = express();
//设置routerTest中间件
app.use(routerTest);
//服务启动GET http://localhost:8080/user
app.listen(8080, () => {
console.log("服务启动成功,http://localhost:8080")
})
错误级别中间件
错误级别中间件的作用
:专门用来捕获整个项目中发生的异常错误,从而防止项目异常崩溃的问题。
格式
:错误级别中间件的function 处理函数中,必须有4个形参,形参顺序从前到后,分别是(err,req,res,next)
。
错误级别的中间件,放到所有路由请求之后
const express = require('express')
const app = express()
app.get('/', (req, res) => {
throw new Error('服务器内部发生了错误!')
res.send('Home page.')
})
// 定义错误级别的中间件,捕获整个项目的异常错误,从而防止程序的崩溃
app.use((err, req, res, next) => {
console.log('发生了错误!' + err.message)
res.send('Error:' + err.message)
})
app.listen(8080, function () {
console.log('Express server running at http://127.0.0.1:8080')
})
Express 内置中间件
自Express 4.16.0版本开始,Express内置了
3个常用
的中间件,极大的提高了Express项目的开发效率和体验:
①express.static
快速托管静态资源的内置中间件,例如:HTML文件、图片、CSS样式等(无兼容性)
②express.json
解析JSON格式的请求体数据(有兼容性
,仅在4.16.0+
版本中可用)③
express.urlencoded
解析URL-encoded格式的请求体数据(有兼容性
,仅在4.16.0+
版本中可用)
//添加router.use(express.json()) json解析中间件,post请求req.body JSON参数可以正常取到,否则req.body=undefined
app.use(express.json())
//Body参数,x-www-form-urlencoded参数
app.use(express.urlencoded({ extended: false }))
--------------------------------------------------------------------
const express = require('express');
const app = express();
//Body参数,json参数
app.use(express.json())
//Body参数,x-www-form-urlencoded参数
app.use(express.urlencoded({ extended: false }))
app.post('/user/add', (req, res) => {
console.log(req.body);
res.send(req.body);
})
//启动服务
app.listen(8080, () => {
console.log("express内置中间件启动成功http://127.0.0.1:8080")
})
多个中间件之间,共享同一份
req
和res
,基于这样的特性,我们可以在上游的中间件中,统一为req或res对象添加自定义
的属性
或方法
,供下游
的中间件或路由进行使用。
// 引入express
const express = require('express');
//创建服务器
let app = express();
//定义中间件函数
const mw = function (req, res, next) {
console.log("进入了中间件函数");
//req设置自定义参数
req.startTime = new Date();
//调用next方法
next();
}
//注册中间件
app.use(mw)
//挂载方法
app.get('/', (req, res) => {
console.log("获取中间件设置的自定义参数", req.startTime)
res.send(req.startTime)
})
//启动服务
app.listen(8080, () => {
console.log("服务启动,http://127.0.0.1:8080")
})
//引入express模块
const express = require('express');
const app = express();
//引入querystring模块
const qs = require('querystring');
app.use(function (req, res, next) {
//定义变量
let str = '';
//开始
req.on('data', (chunk) => {
str += chunk;
})
//结束
req.on('end', () => {
//将字符串转对象
const parsedUrlQuery = qs.parse(str);
//对象设置body参数
req.body = parsedUrlQuery
next();
})
})
//挂载请求
app.post('/user/add', (req, res) => {
res.send(req.body);
})
//暴露外部模块
module.exports = app
const express = require('express');
//引入自定义中间件
const zidingyi = require('./09.自定义中间件01');
//获取服务器
const app = express();
//设置自定义中间件为全局中间件
app.use(zidingyi)
//启动服务
app.listen(8080, () => {
console.log("自定义模块启动,http://localhost:8080")
})
01.apiRouter.js
const express = require('express');
//1. 创建一个路由容器
const router = express.Router();
//2.编写接口
router.get('/get', function (req, res) {
//获取req.query查询参数
const query = req.query;
res.send(
{
code: 200,
message: 'GET查询成功',
data: query
}
)
})
router.post('/post', function (req, res) {
//获取body参数
const body = req.body;
res.send({
code: 200,
message: 'POST提交成功',
data: body
})
})
//3.路由外部暴露
module.exports = router
const express = require('express');
//1.创建服务器
const app = express();
//2.导入apiRouter路由模块
const router = require('./01.apiRouter')
//3.导入cors跨域模块
const cors = require('cors');
//4.注册JSON中间件、解析URL-encoded中间件 (内置中间件) \配置跨域中间件app.use(cors())
app.use(express.json())
app.use(express.urlencoded({extended: false}))
app.use(cors())
//5.注册router中间件
app.use(router);
//6.启动服务
app.listen(8080, function () {
console.log("api接口启动成功,http://localhost:8080")
})
cors是Express的一个第三方中间件。通过安装和配置cors中间件,可以很方便地解决跨域问题。
使用步骤分为如下3步:
//1.安装cors模块
npm install cors
//2.导入cors模块
const cors = require('cors');
//3.注册cors模块
app.use(cors())
Access-Control-Allow-Origin
:制定了允许访问资源的外域 URLres.setHeader('Access-Control-Allow-Origin', 'http://bruceblog.io')
res.setHeader('Access-Control-Allow-Origin', '*')
Access-Control-Allow-Headers
Accept、Accept-Language、Content-Language、DPR、Downlink、Save-Data、Viewport-Width、Width 、Content-Type (值仅限于 text/plain、multipart/form-data、application/x-www-form-urlencoded 三者之一)
ccess-Control-Allow-Headers
对额外的请求头进行声明,否则这次请求会失败!res.setHeader('Access-Control-Allow-Headers', 'Content-Type, X-Custom-Header')
Access-Control-Allow-Methods
Access-Control-Alow-Methods
来指明实际请求所允许使用的 HTTP 方法res.setHeader('Access-Control-Allow-Methods', 'POST, GET, DELETE, HEAD')
res.setHEader('Access-Control-Allow-Methods', '*')
在浏览器与服务器正式通信之前,浏览器会先发送 OPTION 请求进行预检,以获知服务器是否允许该实际请求,所以这一次的 OPTION 请求称为“预检请求”。服务器成功响应预检请求后,才会发送真正的请求,并且携带真实数据
、Downlink、Save-Data、Viewport-Width、Width 、Content-Type (值仅限于 text/plain、multipart/form-data、application/x-www-form-urlencoded 三者之一)`
ccess-Control-Allow-Headers
对额外的请求头进行声明,否则这次请求会失败!res.setHeader('Access-Control-Allow-Headers', 'Content-Type, X-Custom-Header')
Access-Control-Allow-Methods
Access-Control-Alow-Methods
来指明实际请求所允许使用的 HTTP 方法res.setHeader('Access-Control-Allow-Methods', 'POST, GET, DELETE, HEAD')
res.setHEader('Access-Control-Allow-Methods', '*')
在浏览器与服务器正式通信之前,浏览器会先发送 OPTION 请求进行预检,以获知服务器是否允许该实际请求,所以这一次的 OPTION 请求称为“预检请求”。服务器成功响应预检请求后,才会发送真正的请求,并且携带真实数据
最后准备了一份资料分享给大家,获取链接:2022年Java开发全套学习资料