Express的基本使用/创建路由模块/创建服务器/中间件;nodemon包

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中间件的格式

next函数的作用

创建最简单的中间件函数

// 导入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的内置中间件

内置中间件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');
})
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,295评论 6 512
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,928评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,682评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,209评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,237评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,965评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,586评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,487评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,016评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,136评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,271评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,948评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,619评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,139评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,252评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,598评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,267评论 2 358

推荐阅读更多精彩内容