Express 的作用和 Node.js 内置的 http 模块类似,是专门用来创建 Web 服务器的。
使用 Express,我们可以方便、快速的创建 Web 网站的服务器或 API 接口的服务器。
1、基本配置:
//1、导入express
const express = require("express");
//2、实例化
const WebServer = express();
//3、调用并启动服务器
WebServer.listen(80, () => {
console.log("启动");
});
2、get/post
send发送、query参数、params动态参数
//get。req请求对象,res响应对象
WebServer.get("/:id", (req, res) => {
//发送JSON
res.send({ name: "jacky", age: "18" });
//获取动态参数,匹配:后的值
//localhost/1
console.log(req.params); //{id:'1'}
});
//post
WebServer.post("/", (req, res) => {
//发送文本
res.send("jacky");
//获取参数,返回对象
//localhost?a=1
console.log(req.query); //{a:'1'}
});
3、资源托管
存放静态文件的目录名不会出现在 URL
添加参数,该参数其实可以是多级路由
先写的先查找
//1、导入express
const express = require("express");
//2、实例化
const WebServer = express();
//3、创建托管
WebServer.use('/material',express.static('../素材'))
//4、调用并启动服务器
WebServer.listen(80, () => {
console.log("启动");
});
//可以随时改变url从而获取不同的文件
4、路由匹配
Express 中的路由分 3 部分组成,分别是请求的类型、请求的 URL 地址、处理函数,格式如下:
WebServer.method(path, handler)/WebServer.get('/', ()=>{ } )
按照路由的顺序进行匹配,如果请求类型和请求的 URL 同时匹配成功,则 Express 会将这次请求,转交给对应的 function 函数进行处理。
5、路由模块化
为了防止路由过多而造成文件臃肿,一般会把路由单独抽取成文件,挂载到router上,然后exporst和require
//server.js
const express = require("express");
const WebServer = express();
//导入路由模块
const userRouter = require("./router");
//注册路由模块
WebServer.use(userRouter);
WebServer.listen(80, () => {
console.log("服务器启动,http://localhost");
});
//router.js
const express = require("express")
//调用 express.Router() 函数创建路由对象,挂载到router上
const router = express.Router()
router.get('/',()=>{
console.log('get');
})
router.post('/',()=>{
console.log('post');
})
module.exports = router
6、中间件:业务流程的中间处理环节
调用多个中间件,从而对这次请求进行预处理。
处理函数:中间件函数的形参列表中,必须包含 next 参数。而路由处理函数中只包含 req 和 res。
共享同一份 req 和 res。基于这样的特性,我们可以在上游的中间件中,统一为 req 或 res 对象添加自定义的属性或方法,供下游的中间件或路由进行使用。
连续调用的关键,它表示把流转关系转交给下一个中间件或路由。
全局生效中间件
任何请求,到达服务器之后,都会先触发的中间件,叫做全局生效的中间件。使用WebServer(app).use(中间件名称)
一定要在路由之前注册中间件
4、多个全局中间件流转
app.use() 连续定义多个全局中间件。客户端请求到达服务器之后,会按照中间件定义的先后顺序依次进行调用
const express = require("express");
const app = express();
//全局中间件1
app.use((req, res, next) => {
//该中间件获取系统时间
let time = Date.now();
//req挂载
req.startTime = time;
//流转
next();
});
//全局中间件2
app.use((req, res, next) => {
//该中间件获取上一轮的系统时间进行操作
req.startTime = req.startTime + "二次处理";
//流转
next();
});
//响应
app.get("/", (req, res) => {
res.send("" + req.startTime); //1651111.....二次处理
});
app.listen(80, () => {
console.log("Server has been started in http://localhost:80");
});
局部中间件
不使用 app.use() 定义的中间件,叫做局部生效的中间件
const partMid = (req, res, next) => {
req.partStr = "局部中间件,其他路径无效";
next();
};
app.get("/", partMid, (req, res) => {
let str = req.partStr ? req.partStr : "局部中间件未生效";
res.send(str); //局部中间件,其他路径无效
});
app.get("/user", (req, res) => {
let str = req.partStr ? req.partStr : "局部中间件未生效";
res.send(str); //局部中间件未生效
});
逗号分割或者用数组,顺序从前到后
app.get("/", partMid1, partMid2, (req, res) => {
app.get("/", [partMid1, partMid2], (req, res) => {
let str = req.partStr ? req.partStr : "局部中间件未生效";
res.send(str); //局部中间件,其他路径无效
});
7、express分类:
- 应用级别的中间件:通过 app.use() 或 app.get() 或 app.post()
- 路由级别的中间件:绑定到 express.Router() 实例上的中间件
- 错误级别的中间件:专门用来捕获整个项目中发生的异常错误,从而防止项目异常崩溃的问题。错误级别中间件的function 处理函数中,必须有 4 个形参,形参顺序从前到后,分别是 (err, req, res, next)。错误级别的中间件,必须注册在所有路由之后
const express = require("express");
const app = express();
app.get("/", (req, res) => {
throw new Error("500");
res.send('success')
});
//错误中间件,需要定义在组件之后
app.use((err, req, res, next)=>{
res.send(err.message)
})
app.listen(80,()=>{})
- Express 内置的中间件:
- express.static
- express.json
- express.urlencoded(option) 解析 URL-encoded 格式的请求体数据(有兼容性,仅在 4.16.0+ 版本中可用)选项options参数包含各种属性,例如扩展,膨胀,限制,验证等
//配置解析中间件
app.use(express.json())
app.use(express.urlencoded({extended:false}))
app.post('/',(req, res)=>{
console.log(req.body);
res.send('ok')
})
- 第三方的中间件(自定义中间件):需要了解一些内置的事件,比如req的on绑定事件(比如data事件、end事件)
app.use((req, res, next)=>{
let str = ''
//req的data事件
req.on('data',(chunk)=>{
//由于chunk是分块的,因此需要拼接才可获得一次完整的内容
str += chunk
})
//当请求接收完成,自动触发end事件
req.on('end',()=>{
const body = qs.parse(str)
req.body = body
next()
})
})
7、接口跨域:
1、CORS:CORS (Cross-Origin Resource Sharing,跨域资源共享)由一系列 HTTP 响应头组成,这些 HTTP 响应头决定浏览器是否阻止前端 JS 代码跨域获取资源
CORS响应头:
- Access-Control-Allow-Origin:origin 参数的值指定了允许访问该资源的外域 URL,可通配*允许任何外域,也可以具体域名接受指定来源请求
- Access-Control-Allow-Headers:默认情况下,CORS 仅支持客户端向服务器发送 9 个请求头,如果客户端向服务器发送了额外的请求头信息,则需要在服务器端对额外的请求头进行声明,否则这次请求会失败
- Access-Control-Allow-Methods:如果客户端希望通过 PUT、DELETE 等方式请求服务器的资源,则需要在服务器端指明实际请求所允许使用的 HTTP 方法。可通配*允许任何请求,也可以具体请求
res.setHeader('Access-Control-Allow-Origin','*')
res.setHeader('Access-Control-Allow-Headers', 'Content-Type')
res.setHeader('Access-Control-Allow-Methods', '*')
注意点:
- CORS 主要在服务器端进行配置。客户端浏览器无须做任何额外的配置,即可请求开启了 CORS 的接口。
- CORS 在浏览器中有兼容性。只有支持 XMLHttpRequest Level2 的浏览器,才能正常访问开启了 CORS 的服务端接口(例如:IE10+、Chrome4+、FireFox3.5+)。
简单请求(get、post、head,且无自定义头)和预检请求(其他请求类型如put等,有自定义头)
发送 OPTION 请求进行预检,以获知服务器是否允许该实际请求,所以这一次的 OPTION 请求称为“预检请求”。服务器成功响应预检请求后,才会发送真正的请求,并且携带真实数据。相比于简单请求的一次请求,预检请求会发送两次请求
const router = require('./router')
const cors = require('cors')
//在路由之前调用cors
app.use(cors())
app.use('/api', router)
2、JSONP(只支持get):浏览器端通过 <script> 标签的 src 属性,请求服务器上的数据,同时,服务器返回一个函数的调用。这种请求数据的方式叫做 JSONP
8、node操作mysql
npm i mysql
const mysql = require('mysql')
const db = mysql.createPool({
host: 'local',
user: 'root',
password: '123456',
database: 'my_db'
})
db.query('select 1', (err, res)=>{
if (err) {
return console.log(err.message);
}
console.log(res);
})