赞
踩
express是基于nodejs,用来创建web服务器的。
express本质:基于nodejs内置http模块封装来的,是一个npm上的第三方包,提供了快速创建web服务器的便捷方法。
express可以用来创建web网站服务器和api接口服务器
express官网:http://www.expressjs.com.cn/
安装:npm i express
创建基本的web服务器
- // 1、导入express
- const express = reuqire('express')
- // 2、创建web服务器 express()返回值就是一个服务器实例
- const app = express()
- // 3、调用app.listen(端口号,启动成功后的回调),启动服务器
- app.listen(80, () => {
- console.log('express server running at http://127.0.0.1')
- })
通过app.get()方法,可以监听客户端的get请求
- // 参数1:客户端请求的url地址
- // 参数2:请求对应的处理函数
- // req:请求对象(包含了与请求相关的属性和方法)
- // res:响应对象(包含了与响应相关的属性和方法)
- app.get('请求url', function(req,res) {
-
- })
- app.post('请求url', function(req,res) {
-
- })
通过res.send()方法,可以把处理好的内容,发送给客户端
- app.get('/user', function(req,res) {
- res.send({name: 'tian', age: 18})
- })
通过req.query对象,可以访问到客户端通过查询字符串的形式,发送到服务器的参数。
- app.get('/', (req,res) => {
- // req.query 默认是一个空对象
- // 客户端可以使用 ?name=wifi&age=19 这种查询字符串形式,发送到服务器的参数可以通过req.query访问到
- // 例如:req.query.name req.query.age
- console.log(req.query)
- })
通过req.params对象,可以访问到url中,通过“:”匹配到的动态参数
- app.get('/user/:id', function(req,res) {
- console.log(req.params)
- })
通过express.static()这个函数,可以方便的创建一个静态资源服务器。
例如:通过下面的代码可以将public目录下的图片、css、js文件对外开放访问
- app.use(express.static('public'))
- /**
- * 现在就可以访问public目录下的所有文件了:
- * http://localhost:3000/img/1.png
- * http://localhost:3000/css/index.css
- * http://localhost:3000/js/index.js
- */
注意:express在指定的静态目录中查找文件,并对外提供资源的访问路径,因此,存放静态文件的目录名不会出现在url中。
- app.use(express.static('public'))
- app.use(express.static('src'))
如果希望在托管的静态资源访问路径之前,挂载路径前缀,可以使用下面的方式:
- app.use('/hh', express.static('public'))
- /**
- * 访问路径就变成了:http://127.0.0.1/hh/img/1.png
- */
express中的路由分3部分组成,分别是请求的类型、请求的url地址、请求函数
格式:
app.请求类型(请求地址,请求函数)
每当一个请求到达服务器之后,需要先经过路由的匹配,只要匹配成功之后,才会调用对应的处理函数。
在匹配时,会按照路由的顺序进行匹配,如果请求类型和请求的url同时匹配成功,则express会将这次请求转交给对应的function函数进行处理。
在express中使用路由最简单的方式就是把路由挂载到app上,例如:
- const express = require('express')
- // 创建web服务器,命名为app
- const app = express()
-
- // 挂载路由
- app.get('/', (req, res) => {res.send('method is get')})
- app.post('/', (req, res) => {res.send('method is post')})
-
- app.listen(80, () => {
- console.log('http://127.0.0.1');
- })
为了方便对路由进行模块化管理,express不建议将路由直接挂载到app上,而是推荐将路由抽离为单独的模块。
步骤如下:
(1)创建路由模块对应的js文件
(2)调用express.Router()函数创建路由实例对象
(3)向路由对象上挂载具体的路由
(4)使用module.exports向外共享路由
(5)使用app.use()函数注册路由模块
下面是路由模块的js代码(router.js)
- const express = require('express')
- // 1、创建路由对象
- const router = express.Router()
-
- // 2、挂载路由
- router.get('/user/list', (req, res) => {
- res.send('get user list')
- })
-
- router.post('/user/add', (req, res) => {
- res.send('add new user')
- })
-
- // 3、向外到处路由
- module.exports = router
下面是导入和注册路由模块(index.js)
- const express = require('express')
- const app = express()
-
- // 1、导入路由模块
- const userRouter = require('./router')
- // 2、使用app.use()注册路由模块
- app.use(userRouter)
-
- app.listen(80, () => {
- console.log('http://127.0.0.1');
- })
- const userRouter = require('./router')
- // 添加前缀
- app.use('/api', userRouter)
本质上就是一个function函数,中间件函数的形参中,必须包含next参数。而路由处理函数只包含req和res。
- app.get('/', function(req, res, next) {
- next();
- })
- // 定义中间件
- const mw = function(req, res, next) {
- next()
- }
客户端发起的任何请求,到达服务器之后,都会触发的中间件,叫做全局生效的中间件。
通过调用app.use(中间件函数),即可定义一个全局中间件
- // 定义中间件
- const mw = function(req, res, next) {
- next()
- }
- // 全局使用
- app.use(mw)
可以多次使用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.use()定义的中间件,叫局部中间件
- const mw1 = function (req, res, next) {
- next()
- }
-
- // mw1这个中间件只在当前路由生效,属于局部中间件
- app.get('/', mw1, (req, res) => {
- res.send('home')
- })
- // mw1不会影响下面这个路由
- app.get('/user', (req, res) => {
- res.send('user')
- })
写法:
- app.get('/', mw1, mw2, (req, res) => { res.send('aaa') })
- app.get('/', [mw1, mw2], (req, res) => { res.send('bbb') })
(1)一定要在路由之前注册中间件
(2)客户端发送过来的请求,可以连续调用多个中间件进行处理
(3)执行完中间件的业务代码之后,必须要调用next()函数
(4)在next()函数后,不要写其他的代码
(5)连续调用多个中间件时,多个中间件之间,共享req和res对象
通过app.use()或app.get()或app.post(),绑定到app实例上的中间件,叫做应用级别的中间件。
例如:全局和局部中间件
绑定到express.Router()实例上的中间件。它的用法和应用级别的中间件没有任何区别。只不过,应用级别的中间件事绑定到app实例上,路由级别的中间件绑定到router实例上。
- const express = require('express')
- const app = express()
- const router = express.Router()
-
- router.use((req, res, next) => {
- next()
- })
-
- app.use('/', router)
专门用来捕获整个项目中发生的异常错误。
注意:错误中间件必须注册在所有路由之后!!!
格式:错误中间件的处理函数中,必须含有4个参数,分别是(err,req,res,next)
- app.get('/', (req, res) => {
- throw new Error('服务器发生错误') // 抛出一个自定义错误,遇到错误直接到下面的错误中间件执行了,res.send('page')这个代码是没有执行的
- res.send('page')
- })
-
- app.use((err, req, res, next) => {
- console.log('发生了错误' + err.message);
- })
express内置了3个常用的中间件:
- // 通过express.json()这个中间件,来解析表单中的json格式的数据
- app.use(express.json())
-
- app.post('/user', (req, res) => {
- // 在服务器中,可以使用req.body这个属性,来接收客户端发送过来的请求体数据
- // 默认情况下,如果不配置解析表单数据的中间件,则req.body默认等于undefined
- console.log(req.body)
- res.send('ok')
- })
- app.use(express.urlencoded({extended: false}))
-
- app.post('/user', (req, res) => {
- console.log(req.body)
- res.send('ok')
- })
使用步骤:
const parser = require('body-parser')
- // 需要对url-encoded格式的数据进行解析,需要使用.urlencoded({extended: false})
- app.use(parser.urlencoded({extended: false}))
在中间件中,需要监听req对象的data事件,来获取客户端发送到服务器的数据。
如果数据量比较大,无法一次性发送完毕,则客户端会把数据切割后,分批发送到服务器。所有data事件可能会触发多次,每一次触发data事件时,获取到数据只是完整数据的一部分,需要手动对接收到的数据进行拼接。
当请求体数据接收完毕之后,会自动触发req的end事件。因此,可以在req的end事件中,拿到并处理完整的请求体数据。
- app.use((req, res, next) => {
- // 定义变量,用来存储客户端发送过来的请求体数据
- let str = ''
- // 监听req对象的data事件(客户端发送过来的新的请求体数据)
- req.on('data', (strData) => {
- str += strData
- })
- // 监听req对象的end事件(请求体发送完毕之后自动触发)
- req.on('end', () => {
- console.log(str);
- })
- })
nodejs内置了一个querystring模块,专门用来处理查询字符串。通过这个模块提供的parse()函数,可以把查询到的字符串,解析称对象的格式。
- // 导入
- const qs = require('querystring')
-
- app.use((req, res, next) => {
- let str = ''
- req.on('data', (strData) => {
- str += strData
- })
- req.on('end', () => {
- // 解析字符串数据为对象
- const body = qs.parse(str)
- console.log(body);
- next() // on是异步的,也可以放到外面
- })
- // next() 这里也行
- })
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。