前言
express特别像node.js内置的http模块一样,帮助我们来创建web服务器的,express实际上就是npm中的一个第三方的包,它里面提供了快捷创建Web服务器的方法,本篇将讲到如何使用express进行web服务器和路由的创建
初识express
既然是一个包那么首先就要进行安装这个包
使用npm i express@4.17.1来进行安装,安装成功后就可以直接使用了
express给我们带来的主要效果就是进行一个服务器的创建,那么下面就让我们一起来进行一个最基本的服务器创建
使用express创建基本的web服务器
web服务器的创建一共分为三部
1.导入express
2.创建web服务器
3.调用app.listen(端口号,回调函数),启动服务
// 导入express const express = require('express'); // 创建web服务器 const app = express(); // 调用app.listen app.listen(80, () => { console.log('express server running at http://localhost'); })
这样一个简单的服务器就创建好了(这么一看和http的用法差不多吗)
用get和post进行一个请求的监听
● 监听GET请求
● 监听post请求
● 获取URL中携带的查询参数
通过req.query对象,可以访问到客户端通过查询字符串的形式,发送到服务器的参数
● 获取url中动态参数
● 托管静态资源
通过express.static()创建一个静态资源服务器
注:多次使用express.static()就可以得到多个静态资源服务器了
初识express路由
在Express中,路由指的是客户端的请求与服务器处理函数之间的映射关系。 Express中的路由由3部分组成,分别是请求的类型、请求的URL地址、处理函数
METHON(请求类型) PATH(请求URL地址) HANDLER(处理函数)
路由匹配概念
当一个请求到达服务器之后,需要先经过路由的匹配,匹配成功之后,调用对应的处理函数。 在匹配时,会按照路由的顺序进行匹配,如果请求类型和请求的URL同时匹配成功,Express会将这次请求,转交给对应的function函数进行处理。(也就是说满足请求类型和请求的URL同时匹配成功这个条件时才能进行函数处理,否则不会进行对客户端的请求进行处理)
注:路由会按照定义的先后顺序自上而下进行匹配,并且请求类型和请求的URL必须匹配成功才能进行函数处理
1.导入express模块。2,挂载路由。3,监听80端口
const express = require('express'); const app = express() // 挂载路由 app.get('/', (req, res) => { res.send('hello friend') }) app.post('/', (req, res) => { res.send('hello my friend') }) app.listen(80, () => { console.log('express server running at http://localhost'); })
路由模块化
就是将路由模块单独提出来,进行暴露共享,然后再供其他的模块使用
const express = require('express'); // 导入express const router = express.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; // 暴露共享对象
使用路由模块
const express = require('express'); const app = express() // 导入路由模块 const router = require('./04路由模块化.js') // 注册路由模块,挂载前缀 app.use(router); // app.use()用来注册全局中间件 app.listen(80, () => { console.log('express server running at http://localhost'); })
中间件
中间件和路由的区别
express的中间件本质上是一个函数,它类似于路由处理函数我们可以进行一下对比
区分他俩的标志就是next这个参数,有next函数的就是中间件的处理函数,没有的就是路由处理函数,在预处理中next函数至关重要next函数是实现多个中间件连续调用的关键,它表示把流转关系转交给下一一个中间件或路由。
定义中间件函数
跟路由很相似
const express = require('express'); const app = express(); // 定义一个简单的中间件函数 const mw = (req, res, next) => { console.log('中间件函数'); next(); } app.listen(80, () => { console.log('http://localhost'); })
全局中间件
就是客户端无论发起什么请求,到达服务器之后都得出发的中间件叫做全局中间件
简化中间件函数
中间件作用
多个中间件之间,共享同一份req和res。基于这样的特性,我们可以在前面的的中间件中,统一为req或res对象添加自定义的属性或方法,供后面的的中间件或路由进行使用。(简而言之,中间件里面的req,res可以供给后面的中间件或者是路由使用)
局部生效中间价
不使用app.use()定义的中间件,叫做局部生效的中间件
const express = require('express'); const app = express(); // 1.定义中间件函数 const mw1 = (req, res, next) => { console.log('局部中间件已调用'); next() } // 2.创建路由 app.get('/', mw1, (req, res) => { res.send('Home page.') }) app.get('/user', (req, res) => { res.send('User page.') }) app.listen(80, function () { console.log('Express '); })
注意事项:
①一定要在路由之前注册中间件 ②客户端发送过来的请求,可以连续调用多个中间件进行处理 ③执行完中间件的业务代码之后,不要忘记调用next()函数 ④为了防止代码逻辑混乱,调用next()函数后不要再写额外的代码 ⑤连续调用多个中间件时,多个中间件之间,共享req和res对象
中间件分类
在express中,把中间件分为了五大类分别是
1.应用级别中间件
(通过app.use()/app.get()/app.post(),绑定到app实例上的中间件)
2.路由级别的中间件
(绑定到express.Router(实例上的中间件,叫做路由级别的中间件。它的用法和应用级别中间件没有任何区别。只不过,应用级别中间件是绑定到app实例上,路由级别中间件绑定到router实例上)
3.错误级别中间件
(专门用来捕获整个项目中发生的异常错误,从而防止项目异常崩溃的问题。错误级别中间件的function处理函数中,必须有4个形参,形参顺序从前到后,分别是(err, req, res, next),错误级别的中间件一定要在路由后面否则不会执行该错误级别中间件。)
4.内置中间件
1.express.static快速托管静态资源的内置中间件
2.express.json解析JSON格式的请求体数据(4.16.0及以上版本可用)
3.express.urlencoded解析URL-encoded格式的请求体数据(4.16.0及以上版本可用)
4.body-parser的使用
// 导入express 模块 const express = require('express'); const app = express(); // 导入body-parser const parser = require('body-parser'); // 注册中间件 app.use(parser.urlencoded({ extended: false })) app.post('/', (req, res) => { // 如果没有配置任何解析表单数据的中间件,则req. body默认等于undefined console.log(req.body); res.send('ok') }) app.listen(80, () => { console.log('express server running at http://127.0.0.1'); })
5.自定义中间件
将该模块进行封装
// 导入querystring内置模块 const qs = require('querystring'); const parser = (req, res, next) => { // 用来储存客户端发送的数据 let str = '' // 监听req的data事件 req.on('data', (chunk) => { str += chunk; }) // 监听req的end事件 req.on('end', () => { // 打印储存完整的请求体数据 // 使用querystring内置模块解析请求体数据 // 把字符串数据解析为对象格式 // 将解析出来的数据对象挂载为req.body const body = qs.parse(str); req.body = body; next() }) } module.exports = parser;
使用该模块
const express = require('express'); const app = express(); // 导入querystring内置模块 const qs = require('querystring'); // 定义解析表单的中间件具体的业务逻辑 const cousttomParser = require('./12对自定义的中间件进行模块化') app.use(cousttomParser) app.post('/', (req, res) => { res.send(req.body) }) app.listen(80, () => { console.log('express server running at http://127.0.0.1'); })
使用apipost发送请求