Express是什么?
node中的一个第三方的包,和http模块类似功能,都是有创建服务器的功能;
如何安装
在项目目录中执行命令:npm i express@4.17.1
如何创建服务器
// 导入express模块
const express = requirt('express')
// 返回实例对象 创建服务器
const app = express()
app.listen(80,()=>{
console.log('http://127.0.0.1');
})
Express的基本使用
const express = require('express')
const app = express()
//基本使用
//通过app.get()方法,监听客户端的get请求;
//参数一:客户端请求的url地址;
//参数二:回调函数,req:请求数据(客户端发送的),res:响应数据(服务器响应的)
app.get('/',function(req,res){
console.log('Hello world!');
})
app.post('/',function(req,res){
console.log('Post Request');
})
app.listen(80,function(){
console.log('server running at http://127.0.0.1');
})
使用req.query对象获取URL中携带的查询参数
const express = require('express')
const app = express()
app.get('/',function(req,res){
// req.query默认是个空对象
// 客户端使用 ?name=zs&age=2 这种查询字符串形式,发送到服务器的参数,可以通过req.query对象访问到
console.log(req.query);
})
app.listen(80,function(){
console.log('server running at http://127.0.0.1');
})
使用req.params获取URL中的动态参数
const express = require('express')
const app = express()
// 使用req.params获取URL中的动态参数
app.get('/user:id',function(req,res){
// 默认情况下req.params是个空对象
// 里面存放着动态匹配到的参数值
// 比如在url输入http://127.0.0.1/user/1,那返回就是 req.params{"1"}
console.log(req.params);
})
app.listen(80,function(){
console.log('server running at http://127.0.0.1');
})
使用express.static()对外界托管静态资源
注意:要执行的js文件必须和node_modules放在同一父目录中,否则就无法使用里面的包;
const express = require('express')
const app = express()
// 在这里,调用 express.static() 方法,快速的对外提供静态资源
// express.static('./files') 把files文件夹内的所有内容对外界托管
// 要托管多个项目就调用多次 express.static()
// 挂载前缀路径:'/files',代表在目录http://127.0.0.1/files中的文件,不加前缀则无法访问files文件夹内容
app.use('/files', express.static('./files'))
app.use(express.static('./clock'))
app.listen(80, () => {
console.log('express server running at http://127.0.0.1')
})
nodemon是什么?
在node项目的软件开发中,经常需要边写边调试,因此node服务需要频繁手动重启,特别浪费时间。nodemon软件会自动监测文件的变化,当有变化时重新启动服务。
如何安装:npm i -g nodemon (全局安装)
Express路由
路由是什么?
举例生活中的路由:10086的客服电话,首先要用手机(当前的js)拨通10086这个号码(路由模块),路由模块里面挂载了一些功能,比如按1就是查询订单,0就是人工客服。
现实生活中,也要有电脑(当前的js)连接路由器(路由模块),才可以去上网冲浪;
就像你在A城市(客户端)要去B城市(服务器),就需要大马路或者桥(路由器)才能过去;
创建路由模块
// 路由器模块化
// 导入express
const express = require('express');
// 创建路由对象
// 注意:express()是创建服务器, express.router()是创建路由对象
const router = express.Router()
// 挂载获取用户列表的路由
router.get('/user/list',(req,res) => {
res.send('Get user list.')
})
// 挂载添加用户的路由
router.post('/user/add',(req,res) => {
res.send('Add new user.')
})
// 向外导出路由对象
module.exports = router
注册使用路由模块
// 注册路由模块
//导入express模块
const express = require('express')
// 创建express的对象实例
const app = express()
// 导入路由模块
const UseRouter = require('./router')
// 使用app.use()注册路由模块,并统一添加访问前缀 /api
// app.use()的作用就是注册全局中间件
app.use('/api',UseRouter)
// 启动服务器
app.listen(80,() => {
console.log('http://127.0.0.1');
})
中间件
中间件是什么?
举例就像污水排放一样,从处理到排放的3个处理环节,就是中间件;
express中间件的格式
创建最简单的中间件函数
// 导入express
const express = require('express')
// 创建服务器
const app = express()
// 定义一个最简单的中间件函数
const mw = function(req, res, next){
console.log('这是最简单的中间件函数');
// 调用next(),把流转关系,转交给下一个中间件或路由
next()
}
// 启动服务器
app.listen(80,() => {
console.log('http://127.0.0.1');
})
全局生效的中间件
客户端发起的任何请求,到达了服务器之后,都会触发的中间件就是全局生效的中间件;
通过app.use(中间件函数),即可定义全局生效的中间件
// 导入express
const express = require('express')
// 创建服务器
const app = express()
// 定义一个最简单的中间件函数
const mw = function(req, res, next){
console.log('这是最简单的中间件函数');
// 调用next(),把流转关系,转交给下一个中间件或路由
next()
}
// 将mw注册为全局生效的中间件
app.use(mw)
app.get('/',(req,res) => {
console.log('调用了 / 这个路由');
res.send('Home page')
})
app.get('/user',(req,res) => {
console.log('调用了 /user 这个路由');
res.send('User page')
})
// 运作流程:mv全局中间件——next()转交给/路由或者/user
// 启动服务器
app.listen(80,() => {
console.log('http://127.0.0.1');
})
定义全局中间件的简化形式
// 定义全局中间件的简化形式
app.use((req, res, next) => {
console.log('这是最简单的全局中间件');
next()
})
中间件的作用
// 导入express
const express = require('express')
// 创建服务器
const app = express()
// 定义全局中间件的简化形式
app.use((req, res, next) => {
// 获取到服务器的时间
const time = Date.now()
// 为req对象,挂载自定义属性,从而把时间共享给后面的路由器
req.startTime = time
next()
})
app.get('/',(req,res) => {
res.send('Home page' + req.startTime)
// 返回 Home page1637741241070
})
app.get('/user',(req,res) => {
res.send('User page' + req.startTime)
// 返回 User page1637741296926
})
// 运作流程:mv全局中间件——next()转交给/路由或者/user
// 启动服务器
app.listen(80,() => {
console.log('http://127.0.0.1');
})
定义多个全局中间件
// 导入express
const express = require('express')
// 创建服务器
const app = express()
// 定义多个全局中间件
// 可以使用app.use()连续定义多个全局中间件,按照先后顺序依次进行调用;
app.use((req, res, next) => {
console.log('调用了第1个全局中间件');
next()
})
app.use((req, res, next) => {
console.log('调用了第2个全局中间件');
next()
})
app.use((req, res, next) => {
console.log('调用了第3个全局中间件');
next()
})
app.get('/',(req,res) => {
console.log('调用了 / 这个路由');
res.send('Home page')
})
app.get('/user',(req,res) => {
console.log('调用了 /user 这个路由');
res.send('User page')
})
// 运作流程:mv全局中间件——next()转交给/路由或者/user
// 启动服务器
app.listen(80,() => {
console.log('http://127.0.0.1');
})
// 返回:调用了第1个全局中间件
// 调用了第2个全局中间件
// 调用了第3个全局中间件
// 调用了 / 这个路由
局部中间件
不使用app.use()定义的中间件;
// 导入express
const express = require('express')
// 创建服务器
const app = express()
// 局部中间件:不使用app.use()定义的中间件;
// 定义中间件函数
const m1 = function(req, res, next){
console.log('调用了局部生效的中间件');
next()
}
// 创建路由
// m1成了局部生效的中间件,只会在这个路由生效,不影响其他;
app.get('/', m1, (req,res) => {
res.send('Home page')
})
app.get('/user',(req,res) => {
res.send('User page')
})
// 启动服务器
app.listen(80,() => {
console.log('http://127.0.0.1');
})
创建与调用多个中间件
// 创建多个中间件
const m1 = function(req, res, next){
console.log('调用了第1个局部生效的中间件');
next()
}
const m2 = function(req, res, next){
console.log('调用了第2个局部生效的中间件');
next()
}
// 创建路由
// 调用掉个局部中间件
app.get('/', m1, m2, (req,res) => {
res.send('Home page')
})
app.get('/user',(req,res) => {
res.send('User page')
})
中间件的注意事项
1.中间件一定要写在路由前
2.可以连续调用多个中间件处理客户端的请求
3.执行完中间件的代码后记得调用next(),否则无法流转到路由或者中间件
4.next()后面就不要再写其他代码,否则逻辑混乱
5.连续调用多个中间件时,中间件之间的req,res可以共享(上游可以对req和res挂载自定义属性和方法,下游就可以使用上游的这个req和res)
错误中间件
express的内置中间件
内置中间件express.json()的使用
// 导入express
const express = require('express')
// 创建服务器
const app = express()
// 配置解析表单的内置中间件 express.json()
// 除了error错误级别中间件,其他的中间件必须写在路由前面
app.use(express.json())
// 挂载路由
app.post('/user', (req, res) => {
// 通过postman向服务器发送JSON格式的数据,在postman点击body——raw——JSON——在输入框中输入JSON格式的数据——send
// 在服务器可以通过req.body这个属性接收客户端发送的数据
// 默认情况下,如果无配置解析表单的中间件,则返回undefined
console.log(req.body);//{ name: 'niuniu', age: '3' }
res.send('ok!')
})
// 启动服务器
app.listen(80, () => {
console.log('express server running at http://127.0.0.1');
})
内置中间件express.urlencoded({extended: false})的使用
// 导入express
const express = require('express')
// 创建服务器
const app = express()
// 配置解析表单的内置中间件 express.urlencoded({extended: false})
app.use(express.urlencoded({extended: false}))
// 挂载路由
app.post('/book',(req,res) => {
// 在postman向服务器输入数据,body——w-www-form-erlencoder——键值对的方式输入数据——send
// 在服务器可以通过req.body这个属性接收客户端发送的数据
console.log(req.body);//[Object: null prototype] { bookname: '水浒传' }
res.send('OK!')
})
// 启动服务器
app.listen(80, () => {
console.log('express server running at http://127.0.0.1');
})
第三方中间件body-parser模块的使用
// 导入express
const express = require('express')
// 导入node.js的内置模块querystring,专门用来把字符串转换成对象的工具
const qs = require('querystring')
// 创建服务器
const app = express()
// 这是解析表单数据的中间件
app.use((req,res,next) => {
// 定义中间件的具体逻辑
// 定义变量 专门存储客户端发送过来的数据
let str = '';
// 监听req的data事件
req.on('data',(chunk) => {
str += chunk;
})
// 请求体数据接收完毕会自动触发end事件
// 监听req的end事件
req.on('end',() => {
// 在postman中的urlencoded输入一些数据
// 返回 name=%E7%93%9C%E7%93%9C%E7%89%9B&age=2
console.log(str);
// 把字符串格式的请求体数据,转行成对象的格式
const body = qs.parse(str)
console.log(body);
// 返回对象模式
// [Object: null prototype] { name: '瓜瓜牛', age: '2' }
next()
})
})
// 挂载路由
app.use('/user',(req,res) => {
res.send('OK!')
})
// 启动服务器
app.listen(80, () => {
console.log('express server running at http://127.0.0.1');
})