框架API方法
框架API方法
express
模块提供了很多API方法,要了解、使用这些API去解决一些实际问题,首先需要安装:
## 安装express
npm install express --save
Express框架主要提供了express对象
、application对象
、request对象
、response对象
、router对象
的API方法,往往在使用Express框架时, 项目入口文件的第一行就是对框架的引用,例如:
// 引入express模块
const express = require('express')
因为,这些API方法都来源express
模块,针对不用的应用场景做的一些封装
express()方法
express模块的入口其实是到处一个函数,通常是像上面引入一样,用变量express
来接受,查看源码:
可以看出引入的express
模块,实质是导出一个createApplication
方法,用来创建express
的应用实例,这也说明为什么往往在引入express
后, 第二行代码就是创建application
对象实例
// 导入模块
const express = require('express')
// 创建express应用对象
const app = express()
设置可以从源码中看到,这个application
对象上还绑定了request
、response
两个对象,使用Object.create
创建的、分别处理请求和响应。
除了提供创建app实例的方法,在源码导出时,还在express模块上挂载一些中间件,查看源码:
这里也许会有疑惑,导出的一个函数,使用express变量去接收时,创建出app实例对象,为什么在函数上又能去挂载一些中间件呢? 其实在js发展早期,很多概念都是利用函数、对象、原型链去实现的,导出的函数可以理解为构造函数,挂载的中间件实质上也是一些方法、对象, 可以理解为使用static关键字标记的静态方法。
总之,如果将这里导出的express理解为一个类
,将createApplication方法理解为构造函数,将中间件理解为静态方法,应该就要好理解很多。
js也是到ES6推出后才有了类的概念,并且也是利用函数+对象来实现的。
这里的理解,我在阅读源码的时候发现,结合Java的面向对象思想获取更好理解,接下来就说说express类上面挂载的静态方法、中间件
数据处理
Express框架内置中间件
express.json()
express.raw()
express.text()
express.urlencoded()
都是基于body-parser
模块,实质上就是利用body-parser
中的json()
、raw()
、text()
、urlencoded()
方法,查看源码:
具体用法可以参考模块:body-parser
可以对客户端请求传递的数据做处理,前置中间件处理好数据,交给下游的中间件、处理函数来实现逻辑
数据处理中间件的一些参数含义:
const express = require('express')
const app = express()
express.raw({
// 可选参数,布尔类型
// 是否禁用压缩的请求体数据,默认为true,false时拒绝请求数据
inflate: undefined,
// 可选参数,数字或字符
// 限制请求体的大小,默认100kb
limit: undefined,
// 可选参数,字符或字符数组
// 约定什么类型的数据会被该中间件处理,默认值:"application/octet-stream"
type: [],
// 可选参数,函数包含req、res、buffer、encoding四个参数
// 提供原始的请求正文Buffer数据、编码等信息,可以通过抛错来终止解析
verify(req, res, buf, encoding) {
},
})
express.json({
// ... 除raw函数包含的参数外,还额外包含
// 可选参数,布尔类型
// 设置是否使用严格模式,默认为true,只接收对象和数组
// 设置false时,接收一切可以JSON.parse()处理的数据
strict: true,
// 可选参数,函数类型
// 设置的这个函数,将直接放在JSON.parse()的第二个参数中使用
// 参考JSON.parse()的API:
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse#Example.3A_Using_the_reviver_parameter
reviver(key, value) {
},
})
express.text({
// ... 除raw函数包含的参数外,还额外包含
// 可选参数,字符串
// 如果请求的header中没有指定Content-Type类型,指定文本内容的编码类型, 默认utf-8
defaultCharset: undefined,
})
express.urlencoded({
// ... 除raw函数包含的参数外,还额外包含
// 可选参数,布尔类型
// 运行定制模块类解析URL地址中的参数
// false时,使用querystring模块解析
// true时,使用qs模块解析
extended: undefined,
// 可选参数,数字类型
// 允许URL地址中传递的参数最大字段个数,默认为1000
// 当参数个数超出时,返回客户端 413 状态码,表示请求体过大
parameterLimit: undefined,
})
这里要重点提一下JSON.parse()的用法,例如:
JSON.parse('{}') // {}
JSON.parse('true') // true
JSON.parse('"foo"') // "foo"
JSON.parse('[1, 5, "false"]') // [1, 5, "false"]
JSON.parse('null') // null
JSON.parse(
'{"p": 5}',
(key, value) =>
typeof value === 'number'
? value * 2 // return value * 2 for numbers
: value, // return everything else unchanged
)
// { p: 10 }
静态资源
Express中内置的中间件功能。提供静态文件托管管理,基于serve-static
。
模块用法参考:serve-static
express.static()
的基础用法:
const express = require('express')
const app = express()
const path = require('node:path')
// 服务启动端口
const port = 3000
// 指定接口的根路径映射到资源的根目录
app.use(express.static('public'))
// 设置不同的路径映射
app.use('/static', express.static('public'))
// 使用绝对路径
app.use('/static-back', express.static(path.join(__dirname, 'public')))
/**
* 服务启动,监听端口
*/
app.listen(port, () => {
console.log(`quick-start app listening on port ${port}`)
})
基于Express框架,关于静态文件托管,单独开了一篇做介绍,传送门:静态资源托管
路由
提供express.Router()
创建一个新的路由器对象,约定接口的请求路径,例如:
const express = require('express')
const router = express.Router()
// 当前路由配置中间件
router.use(async (req, res, next) => {
console.log('打印req对象', req)
console.log('打印res对象', res)
// 只有执行next()函数,请求才会继续向下走处理逻辑
await next()
})
// 设置该路由管理的路径
router.get('/get-request', async (req, res, next) => {
console.log('完成接口的一些业务逻辑')
res.json({
code: 200,
message: '响应成功',
})
})
express.Router()创建路由器对象时也支持一些额外的参数,查看源码:
其中:
caseSensitive
:配置是否对路由地址大小写敏感,布尔类型。默认false,即:大小写不敏感,/test
与/Test
效果一样。mergeParams
:保留req.params父路由器的值,布尔类型。如果父级和子级的参数名称有冲突,则子级的值优先。默认falsestrict
:是否开始严格模式路由,布尔类型。默认false,即:/test
与/test/
效果一样
路由器的用途还有很多,不仅支持多种请求类型的接口定义,还能分层管理,后面将单独开一篇详细讲讲,传送门:路由的使用