Nodejs
初始Node.js
Node
.
js
® 是一个基于 Chrome V8 引擎 的JavaScript 运行时环境。
Node.js介绍
Node.js中的JavaScript环境
Node.js可以做什么
Node.js作为一个JavaScript运行环境,仅仅提供了基础的功能和APi。然而,基于Node.js提供的这些基础功能,很多强大的工具和框架如雨后春笋,层出不穷,所以学习了Node.js,可以让前端程序员胜任更多的工作和岗位;
-
基于
Express 框架 (opens new window)
,可以快速构建 Web 应用 -
基于
Electron 框架 (opens new window)
,可以构建跨平台的桌面应用 -
基于
restify 框架 (opens new window)
,可以快速构建 API 接口项目 - 读写和操作数据库、创建实用的命令行工具辅助前端开发、etc…
NodeJs学习路径
JavaScript
基础語法+Nodejs内置APl模块(s、path,http等)+第三方API模块(express.mysql 等)
NodeJs环境安装
区分LTS版本和Current 版本的不同
LTS
为长期确定版,对于追求稳定性的企业级项目来说,推荐安装LTS版本的Node.j5.
Current
为新特性类鲜版,对热表于装试新将性的用户来说,推荐安装Current 版本的Node js,但是,Current 版本中可
能存在隐副的Bug 呢安全性测同,因此不推荐在企业级项日中使用Current 版本的Node js。
fs文件系统模块
什么是fs文件系统模块
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路径模块
什么是Path路径模块
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)
参数解读:
- path必选参数,表示一个路径的字符串
- 返回:返回得到的扩展名字符串
const path = require("path");
const pathStr = "/a/b/c/index.html";
let extname = path.extname(pathStr);
console.log(extname)//.html
http模块
什么是http模块
回顾:什么是客户端、什么是服务器?
在网络节点中,负责消费资源的电脑,叫做客户端;
负责对外提供网络资源
的电脑,叫做服务器。
http模块
是Node.js官方提供的、用来创
建 web 服务器的模块
。通过http模块提供的
http.createServer()
方法,就能方便的把一台普通的电脑,变成一台Web服务器,从而对外提供Web资源服务。如果要希望使用http模块创建Web服务器,则需要先导入它:
const http = require('http')
http模块作用
服务器和普通电脑的
区别
在于,服务器上安装了
web服务器软件
,例如:IIS、Apache等。通过安装这些服务器软件,就能把一台普通的电脑变成一台web服务器。在
Node.js
中,我们不需要使用IIS、Apache等这些第三方web服务器款件。因为我们可以基于Node.js提供的
http模块,通过几行简单的代码,就能轻松的手写一个服务器软件,从而对外提供web服务。
创建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请求
获取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');
})
response响应
响应结束
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');
})
根据不同URL相应不同内容
const http = require('http');
let server = http.createServer();
server.on('request', function (req, res) {
//获取请求URL
let url = req.url;
let content = "<h1>404 Not found!</h1>";
if (url === '/' || url === '/index.html') {
content = '<h1>首页</h1>'
} else if (url === '/about.html') {
content = '<h1>关于页面</h1>'
}
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 对象
在自定义模块中,可以使用module.exports对象,将模块内的成员共享出去,供外界使用。
外界用require0方法导入自定义模块时,得到的就是module.exports所指向的对象。module.exports.username = ‘张三’ exports.username = ‘张三’指向的是同一个对象,一种简写方式
共享成员注意点
使用requireo方法导入模块时,导入的结果,
永远以module.exports 指向的对象为准
。
// { nikeName: '李四', test: [Function: test], aaa2: 25 }
CommonJS 模块化规范
-
每个模块内部,
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
什么是express
官方给出的概念:
Express
是基于
Node.js
平台,快速、开放、极简的Web开发框架。通俗的理解:Express的作用和Node.js内置的http模块类似,是专门用来创建Web服务器的。
Express的本质
:就是一个npm上的第三方包,提供了快速创建Web服务器的便捷方法。
express能做什么
对于前端程序员来说,最常见的两种服务器,分别是:
-
Web 网站服务器
:专门对外提供Web 网页资源的服务器。 -
API接口服务器
:专门对外提供API接口的服务器。
使用Express,我们可以方便、快速的创建Web网站的服务器或APl接口的服务器。
express基本使用
安装依赖
node i express@4.17.1
//引入express模块
let express = require('express');
//创建服务器
let app = express();
//监听端口
app.listen(8080, () => {
console.log('express server running at http://localhost:8080');
})
express GET\POST
//引入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()
方法可创建静态资源服务器,向外开放访问静态资源。 - Express 在指定的静态目录中查找文件,并对外提供资源的访问路径,存放静态文件的目录名不会出现在 URL 中
- 访问静态资源时,会根据托管顺序查找文件
- 可为静态资源访问路径添加前缀
- 托管多个静态文件目录,引入多个按照引入顺序加载
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")
})
nodemon
在编写调试Node.js项目的时候,如果修改了项目的代码,则需要频繁的手动close掉,然后再重新启动,非常繁琐。现在,我们可以使用nodemon(https://www.npmjs.com/package/nodemon)这个工具,它能够监听项目文件的变动,当代码被修改后,nodemon会自动帮我们重启项目,极大方便了开发和调试。
npm i -g nodemon
使用nodemon
当基于Node.js编写了一个网站应用的时候,传统的方式,是运行node app.js命令,来启动项目。这样做的坏处是代码被修改之后,需要手动重启项目。
现在,我们可以将node命令替换为
nodemon
命令,使用
nodemon app.js
来启动项目。这样做的好处是:代码被修改之后,会被
nodemon
监听到,从而实现自动重启项目的效果。
node app.js
# 将上面的终端命令,替换为下血的终满命令,即可实现自动重启项目的效果
nodemon app.js
express路由
引用路由
- 定义路由模块
//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")
})
express中间件
- 中间件是指流程的中间处理环节
- 服务器收到请求后,可先调用中间件进行预处理
-
中间件是一个函数,包含
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")
})
express写接口例子
api路由接口文件
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
api服务模块
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跨域资源共享
解决跨域问题
cors是Express的一个第三方中间件。通过安装和配置cors中间件,可以很方便地解决跨域问题。
使用步骤分为如下3步:
//1.安装cors模块
npm install cors
//2.导入cors模块
const cors = require('cors');
//3.注册cors模块
app.use(cors())
CORS
- CORS(Cross-Origin Resource Sharing,跨域资源共享)解决跨域,是通过 HTTP 响应头决定浏览器是否阻止前端 JS 代码跨域获取资源
- 浏览器的同源安全策略默认会阻止网页“跨域”获取资源。但如果接口服务器配置了 CORS 相关的 HTTP 响应头,就可解除浏览器端的跨域访问限制
- CORS 主要在服务器端进行配置。客户端浏览器无须做任何额外的配置,即可请求开启了 CORS 的接口。
- CORS 在浏览器中有兼容性。只有支持 XMLHttpRequest Level2 的浏览器,才能正常访问开启了 CORS 的服务端接口(例如:IE10+、Chrome4+、FireFox3.5+)。
CORS 常见响应头
-
Access-Control-Allow-Origin
:制定了允许访问资源的外域 URL
res.setHeader('Access-Control-Allow-Origin', 'http://bruceblog.io')
res.setHeader('Access-Control-Allow-Origin', '*')
-
Access-Control-Allow-Headers
-
默认情况下,CORS 仅支持客户端向服务器发送如下的 9 个请求头:
Accept、Accept-Language、Content-Language、DPR、Downlink、Save-Data、Viewport-Width、Width 、Content-Type (值仅限于 text/plain、multipart/form-data、application/x-www-form-urlencoded 三者之一)
-
如果客户端向服务器发送了额外的请求头信息,则需要在服务器端,通过 A
ccess-Control-Allow-Headers
对额外的请求头进行声明,否则这次请求会失败!
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, X-Custom-Header')
-
Access-Control-Allow-Methods
-
默认情况下,CORS 仅支持客户端发起 GET、POST、HEAD 请求。如果客户端希望通过 PUT、DELETE 等方式请求服务器的资源,则需要在服务器端,通过
Access-Control-Alow-Methods
来指明实际请求所允许使用的 HTTP 方法
res.setHeader('Access-Control-Allow-Methods', 'POST, GET, DELETE, HEAD')
res.setHEader('Access-Control-Allow-Methods', '*')
CORS 请求分类
简单请求
- 请求方式:GET、POST、HEAD 三者之一
- HTTP 头部信息不超过以下几种字段:无自定义头部字段、Accept、Accept-Language、Content-Language、DPR、Downlink、Save-Data、Viewport-Width、Width 、Content-Type(只有三个值 application/x-www-formurlencoded、multipart/form-data、text/plain)
预检请求
- 请求方式为 GET、POST、HEAD 之外的请求 Method 类型
- 请求头中包含自定义头部字段
- 向服务器发送了 application/json 格式的数据
在浏览器与服务器正式通信之前,浏览器会先发送 OPTION 请求进行预检,以获知服务器是否允许该实际请求,所以这一次的 OPTION 请求称为“预检请求”。服务器成功响应预检请求后,才会发送真正的请求,并且携带真实数据
、Downlink、Save-Data、Viewport-Width、Width 、Content-Type (值仅限于 text/plain、multipart/form-data、application/x-www-form-urlencoded 三者之一)`
-
如果客户端向服务器发送了额外的请求头信息,则需要在服务器端,通过 A
ccess-Control-Allow-Headers
对额外的请求头进行声明,否则这次请求会失败!
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, X-Custom-Header')
-
Access-Control-Allow-Methods
-
默认情况下,CORS 仅支持客户端发起 GET、POST、HEAD 请求。如果客户端希望通过 PUT、DELETE 等方式请求服务器的资源,则需要在服务器端,通过
Access-Control-Alow-Methods
来指明实际请求所允许使用的 HTTP 方法
res.setHeader('Access-Control-Allow-Methods', 'POST, GET, DELETE, HEAD')
res.setHEader('Access-Control-Allow-Methods', '*')
CORS 请求分类
简单请求
- 请求方式:GET、POST、HEAD 三者之一
- HTTP 头部信息不超过以下几种字段:无自定义头部字段、Accept、Accept-Language、Content-Language、DPR、Downlink、Save-Data、Viewport-Width、Width 、Content-Type(只有三个值 application/x-www-formurlencoded、multipart/form-data、text/plain)
预检请求
- 请求方式为 GET、POST、HEAD 之外的请求 Method 类型
- 请求头中包含自定义头部字段
- 向服务器发送了 application/json 格式的数据
在浏览器与服务器正式通信之前,浏览器会先发送 OPTION 请求进行预检,以获知服务器是否允许该实际请求,所以这一次的 OPTION 请求称为“预检请求”。服务器成功响应预检请求后,才会发送真正的请求,并且携带真实数据
最后
最后准备了一份资料分享给大家,获取链接:
2022年Java开发全套学习资料