Express框架

一、认识Web框架

前面我们已经学习了使用http内置模块来搭建Web服务器,为什么还要使用框架?

  • 原生http在进行很多处理时,会较为复杂;
  • 有URL判断、Method判断、参数处理、逻辑代码处理等,都需要我们自己来处理和封装;
  • 并且所有的内容都放在一起,会非常的混乱;

目前在Node中比较流行的Web服务器框架是express、koa:

  • 我们先来学习express,后面再学习koa,并且对他们进行对比;

express早于koa出现,并且在Node社区中迅速流行起来:

  • 我们可以基于express快速、方便的开发自己的Web服务器;
  • 并且可以通过一些实用工具和中间件来扩展自己功能;
  • Express整个框架的核心就是中间件,理解了中间件其他一切都非常简单!

二、Express安装

express的使用过程有两种方式:

  • 方式一:通过express提供的脚手架,直接创建一个应用的骨架;
  • 方式二:从零搭建自己的express应用结构;

方式一:安装express-generator

安装脚手架
npm install -g express-generator
创建项目
express express-demo
安装依赖
npm install
启动项目
node bin/www

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

方式二:从零搭建自己的express应用结构;

npm init -y

三、Express的基本使用

在这里插入图片描述

我们来创建第一个express项目:

  • 我们会发现,之后的开发过程中,可以方便的将请求进行分离:
  • 无论是不同的URL,还是get、post等请求方式;
  • 这样的方式非常方便我们已经进行维护、扩展;
  • 当然,这只是初体验,接下来我们来探索更多的用法;

请求的路径中如果有一些参数,可以这样表达:

  • /users/:userId;
  • 在request对象中获取可以通过 req.params.userId;

返回数据,我们可以方便的使用json:

四、认识中间件

Express是一个路由和中间件的Web框架,它本身的功能非常少:

  • Express应用程序本质上是一系列中间件函数的调用;

中间件是什么呢?

  • 中间件的本质是传递给express的一个回调函数;
  • 这个回调函数接受三个参数:
  1. 请求对象(request对象);
  2. 响应对象(response对象);
  3. next函数(在express中定义的用于执行下一个中间件的函数);

中间件中可以执行哪些任务呢?

  • 执行任何代码;
  • 更改请求(request)和响应(response)对象;
  • 结束请求-响应周期(返回数据);
  • 调用栈中的下一个中间件;

如果当前中间件功能没有结束请求-响应周期,则必须调用next()将控制权传递给下一个中间件功能,否则,请求
将被挂起。
在这里插入图片描述

五、应用中间件 – 自己编写

那么,如何将一个中间件应用到我们的应用程序中呢?

  • express主要提供了两种方式:app/router.use和app/router.methods;
  • 可以是 app,也可以是router,router我们后续再学习:
  • methods指的是常用的请求方式,比如: app.get或app.post等;

我们先来学习use的用法,因为methods的方式本质是use的特殊情况;

  • 案例一:最普通的中间件
    在这里插入图片描述
    在这里插入图片描述

  • 案例二:path匹配中间件
    在这里插入图片描述
    在这里插入图片描述

  • 案例三:path和method匹配中间件
    在这里插入图片描述

  • 案例四:注册多个中间件
    在这里插入图片描述

六、应用中间件 – body解析

并非所有的中间件都需要我们从零去编写:

  • express有内置一些帮助我们完成对request解析的中间件;
  • registry仓库中也有很多可以辅助我们开发的中间件;
    在客户端发送post请求时,会将数据放到body中:
  • 客户端可以通过json的方式传递;
  • 也可以通过form表单的方式传递;

在这里插入图片描述

七、编写解析request body中间件

在这里插入图片描述

八、应用中间件 – express提供

但是,事实上我们可以使用expres内置的中间件或者使用body-parser来完成:
在这里插入图片描述
如果我们解析的是 application/x-www-form-urlencoded:
在这里插入图片描述
extended属性:
true:那么对urlencoded进行解析时,它使用的是第三方库:qs
/false:那么对urlencoded进行解析时,它使用的是Node内置模快:querystring

const express = require('express')
const app = express()
// 编写处理json解析的中间件
app.use((req, res, next) => {
    if (req.headers["content-type"] === "application/json") {
        req.on('data', (data) => {
            const info = JSON.parse(data.toString())
            req.body = info
        })
        req.on('end', () => {
            next()
        })
    } else {
        next()
    }
})
//body-porser:express3.x内置express框架
//body-parser:express4.x被分离出去
//body-parser类似功能;express4,16.x内置成函数
// app.use(express.json())
app.post('/login', (req, res, next) => {
    // req.on('data', (data) => {
    //     console.log(data.toString())
    // })
    // req.on('end', () => {
    //     res.end('zep, Welcome Back~')
    // })
    console.log(req.body)
    res.end('zep, Welcome Back~')
})

app.post('/product', (req, res, next) => {
    req.on('data', (data) => {
        console.log(data.toString())
    })
    req.on('end', () => {
        res.end('Upload Product Info Success')
    })
})

app.listen(8000, () => {
    console.log('express服务器启动成功')
})

九、multer解析form-data

如果我们希望借助于multer帮助我们解析一些form-data中的普通数据,那么我们可以使用any:

在这里插入图片描述
注意: 这里不要把upload.any()作为全局中间件,否则会与后面文件上传功能冲突!!!
在这里插入图片描述
正确做法:
在这里插入图片描述

https://github.com/expressjs/multer
在这里插入图片描述
在这里插入图片描述

十、上传文件中间件multer

上传文件,我们可以使用express提供的multer来完成:
在这里插入图片描述

十一、上传文件中间件 – 添加后缀名

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

const express = require('express')
const multer = require('multer')
const path = require('path')
const app = express()
app.use(express.json())
app.use(express.urlencoded({extended: true}))
const storage = multer.diskStorage({
    destination: (req, file, cb) => {
        cb(null, './uploads/')
    },
    filename: (req, file, cb) => {
        // console.log(file)
        cb(null, Date.now() + path.extname(file.originalname))
    }
})
const upload = multer({
    // dest: './uploads/'
    storage
})

app.post('/upload', upload.single('file'), (req, res, next) => {
    console.log(req.files)
    res.end('文件上传成功~')
})
app.post('/login', upload.any(), (req, res, next) => {
    console.log(req.body)
    res.end('登录成功')
})
app.listen(8000, () => {
    console.log('express服务器启动成功')
})

十二、记录请求日志morgan

https://github.com/expressjs/morgan
如果我们希望将请求日志记录下来,那么可以使用express官网开发的第三方库:morgan

  • 注意:需要单独安装
    在这里插入图片描述
    在这里插入图片描述

在这里插入图片描述

十三、客户端发送请求的方式

客户端传递到服务器参数的方法常见的是5种:

  • 方式一:通过get请求中的URL的params;
  • 方式二:通过get请求中的URL的query;
  • 方式三:通过post请求中的body的json格式(中间件中已经使用过);
  • 方式四:通过post请求中的body的x-www-form-urlencoded格式(中间件使用过);
  • 方式五:通过post请求中的form-data格式(中间件中使用过);

目前我们主要有两种方式没有讲,下面我进行一个演练。

传递参数params和query

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

十四、响应数据

  1. end方法
  • 类似于http中的response.end方法,用法是一致的
    在这里插入图片描述
  1. json方法
  • json方法中可以传入很多的类型:object、array、string、boolean、number、null等,它们会被转换成
    json格式返回;
    在这里插入图片描述
    在这里插入图片描述
  1. status方法
  • 用于设置状态码:
    在这里插入图片描述
  1. 更多响应的方式:https://www.expressjs.com.cn/4x/api.html#res

十五、Express的路由

如果我们将所有的代码逻辑都写在app中,那么app会变得越来越复杂:

  • 一方面完整的Web服务器包含非常多的处理逻辑;
  • 另一方面有些处理逻辑其实是一个整体,我们应该将它们放在一起:
    比如对users相关的处理
  1. 获取用户列表;
  2. 获取某一个用户信息;
  3. 创建一个新的用户;
  4. 删除一个用户;
  5. 更新一个用户;

我们可以使用 express.Router来创建一个路由处理程序:

  • 一个Router实例拥有完整的中间件和路由系统;
  • 因此,它也被称为 迷你应用程序(mini-app);

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

十六、静态资源服务器

部署静态资源我们可以选择很多方式:

  • Node也可以作为静态资源服务器,并且express给我们提供了方便部署静态资源的方法;
    在这里插入图片描述

十七、服务端的错误处理

在这里插入图片描述

const express = require('express')

const userRouter = require('./routers/user.js')

const app = express()

const USERNAME_DOES_NOT_EXISTS = 'USERNAME_DOES_NOT_EXISTS'
const USERNAME_ALREADY_EXISTS = 'USERNAME_ALREADY_EXISTS'

app.use('/users', userRouter)

app.post('/login', (req, res, next) => {
    const isLogin = false
    if (isLogin) {
        res.json('user login success~')
    } else {
        // res.type(400)
        // res.json('username does not exists')
        next(new Error(USERNAME_DOES_NOT_EXISTS))
    }
})

app.post('/register', (req, res, next) => {
    const isExists = true
    if (!isExists) {
        res.json('user register success~')
    } else {
        // res.type(400)
        // res.json('username already exists')
        next(new Error(USERNAME_ALREADY_EXISTS))
    }
})

app.use((err, req, res, next) => {
    let status = 400
    let message = ''
    switch (err.message) {
        case USERNAME_DOES_NOT_EXISTS:
            message = 'username does not exists~'
            break
        case USERNAME_ALREADY_EXISTS:
            message = 'username already exists~'
            break
        default:
            message = 'NOT FOUND'
    }
    res.status(status)
    res.json({
        errCode: status,
        errMessage: message
    })
})
app.listen(8000, () => {
    console.log('路由服务器启动成功~')
})

在这里插入图片描述

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值