Node.js之express框架学习心得

Node.js:颠覆传统的服务器端开发

Node.js是基于Chrome V8引擎构建的JavaScript运行时,它采用了完全不同的开发模型。Node.js使用事件驱动和非阻塞I/O的方式处理请求,通过单线程和异步机制,实现高效的并发处理。这意味着在Node.js中,一个线程可以处理数千个并发连接,大大提高了服务器的性能和可伸缩性。

一、认识Web框架

image.png

二、Express安装

image.png

三、Express的基本使用

image.png

const express = require('express')// 1.创建express的服务器
const app = express()// 客户端访问URL: /login和/home
app.post('/login', (req, res) => {// 处理login请求res.end('登录成功, 欢迎回来~')
})app.get('/home', (req, res) => {res.end('首页的轮播图/推荐数据列表~')
})// 2.启动服务器, 并且监听端口
app.listen(9000, () => {console.log('express服务器启动成功~')
})

四、认识中间件

image.png

image.png

4.1、注册普通中间件

image.png

const express = require('express')const app = express()// 总结: 当express接收到客户端发送的网络请求时, 在所有中间中开始进行匹配
// 当匹配到第一个符合要求的中间件时, 那么就会执行这个中间件
// 后续的中间件是否会执行呢? 取决于上一个中间件有没有执行next// 通过use方法注册的中间件是最普通的/简单的中间件
// 通过use注册的中间件, 无论是什么请求方式都可以匹配上
// login/get
// login/post
// abc/patch
app.use((req, res, next) => {console.log('normal middleware 01')// res.end('返回结果了, 不要等了')next()
})app.use((req, res, next) => {console.log('normal middleware 02')
})// 开启服务器
app.listen(9000, () => {console.log('express服务器启动成功~')
})

4.2、注册路径匹配的中间件

const express = require('express')const app = express()// 注册普通的中间件
// app.use((req, res, next) => {
//   console.log('match normal middleware')
//   res.end('--------')
// })// 注册路径匹配的中间件
// 路径匹配的中间件是不会对请求方式(method)进行限制
app.use('/home', (req, res, next) => {console.log('match /home middleware')res.end('home data')
})app.listen(9000, () => {console.log('express服务器启动成功~')
})

4.3、方法、路径匹配的中间件

const express = require('express')const app = express()// 注册中间件: 对path/method都有限制
// app.method(path, middleware)
app.get('/home', (req, res, next) => {console.log('match /home get method middleware')res.end('home data')
})app.post('/users', (req, res, next) => {console.log('match /users post method middleware')res.end('create user success')
})app.listen(9000, () => {console.log('express服务器启动成功~')
})

4.4、匹配多个中间件

const express = require('express')const app = express()// app.get(路径, 中间件1, 中间件2, 中间件3)
app.get('/home', (req, res, next) => {console.log('match /home get middleware01')next()
}, (req, res, next) => {console.log('match /home get middleware02')next()
}, (req, res, next) => {console.log('match /home get middleware03')next()
}, (req, res, next) => {console.log('match /home get middleware04')
})app.listen(9000, () => {console.log('express服务器启动成功~')
})

4.5、中间件案例一

先匹配普通中间件,有next()才会继续向下匹配

const express = require('express')const app = express()// 1.注册两个普通的中间件
app.use((req, res, next) => {console.log('normal middleware01')next()
})app.use((req, res, next) => {console.log('normal middleware02')next()
})// 2.注册路径path/method的中间件
app.get('/home', (req, res, next) => {console.log('/home get middleware01')next()
}, (req, res, next) => {console.log('/home get middleware02')next()
})app.post('/login', (req, res, next) => {console.log('/login post middleware')next()
})// 3.注册普通的中间件
app.use((req, res, next) => {console.log('normal middleware03')next()
})app.use((req, res, next) => {console.log('normal middleware04')
})app.listen(9000, () => {console.log('express服务器启动成功~')
})

4.6、中间件案例二

const express = require('express')const app = express()// 注册两个实际请求的中间件
// 案例一: 用户登录的请求处理 /login post => username/password
app.post('/login', (req, res, next) => {// 1.获取本次请求过程中传递过来的json数据let isLogin = falsereq.on('data', (data) => {const dataString = data.toString()const dataInfo = JSON.parse(dataString)if (dataInfo.username === 'coderwhy' && dataInfo.password === '123456') {isLogin = true}})req.on('end', () => {if (isLogin) {res.end('登录成功, 欢迎回来~')} else {res.end('登录失败, 请检测账号和密码是否正确~')}})
})// 案例二: 注册用户的请求处理 /register post => username/password
app.post('/register', (req, res, next) => {// 1.获取本次请求过程中传递过来的json数据let isRegister = falsereq.on('data', (data) => {const dataString = data.toString()const dataInfo = JSON.parse(dataString)// 查询数据库中该用户是否已经注册过isRegister = false})req.on('end', () => {if (isRegister) {res.end('注册成功, 开始你的旅程~')} else {res.end('注册失败, 您输入的用户名被注册~')}})
})app.listen(9000, () => {console.log('express服务器启动成功~')
})

4.7、中间件案例二(重构)

//下面这个代码就相当于app.use(express.json())的原理,以后开发直接用app.use(express.json())app.use((req, res, next) => {if (req.headers['content-type'] === 'application/json') {req.on('data', (data) => {const jsonInfo = JSON.parse(data.toString())req.body = jsonInfo})req.on('end', () => {next()})} else {next()}
})
const express = require('express')const app = express()// app.use((req, res, next) => {
//   if (req.headers['content-type'] === 'application/json') {
//     req.on('data', (data) => {
//       const jsonInfo = JSON.parse(data.toString())
//       req.body = jsonInfo
//     })//     req.on('end', () => {
//       next()
//     })
//   } else {
//     next()
//   }
// })// 直接使用express提供给我们的中间件
app.use(express.json())// 注册两个实际请求的中间件
// 案例一: 用户登录的请求处理 /login post => username/password
app.post('/login', (req, res, next) => {console.log(req.body)
})// 案例二: 注册用户的请求处理 /register post => username/password
app.post('/register', (req, res, next) => {console.log(req.body)
})app.listen(9000, () => {console.log('express服务器启动成功~')
})

image.png

image.png

4.8、中间件应用-urlencoded解析

const express = require('express')// 创建app对象
const app = express()// 应用一些中间件
app.use(express.json()) // 解析客户端传递过来的json
// 解析传递过来urlencoded的时候, 默认使用的node内置querystring模块
// { extended: true }: 不再使用内置的querystring, 而是使用qs第三方库
app.use(express.urlencoded({ extended: true })) // 解析客户端传递过来的urlencoded// 编写中间件
app.post('/login', (req, res, next) => {console.log(req.body)res.end('登录成功, 欢迎回来~')
})// 启动服务器
app.listen(9000, () => {console.log('express服务器启动成功~')
})

4.9、应用中间件 – 第三方中间件

image.png

//记录日志
const fs = require('fs')
const express = require('express')
const morgan = require('morgan')// 创建app对象
const app = express()// 应用第三方中间件
const writeStream = fs.createWriteStream('./logs/access.log')
app.use(morgan('combined', { stream: writeStream }))// 编写中间件
app.post('/login', (req, res, next) => {res.end('登录成功, 欢迎回来~')
})// 启动服务器
app.listen(9000, () => {console.log('express服务器启动成功~')
})

单个文件上传

const express = require('express')
const multer = require('multer')// 创建app对象
const app = express()// 应用一个express编写第三方的中间件
const upload = multer({dest: './uploads'
})// 编写中间件
// 上传单文件: singer方法
app.post('/avatar', upload.single('avatar') , (req, res, next) => {console.log(req.file)res.end('文件上传成功~')
})// 启动服务器
app.listen(9000, () => {console.log('express服务器启动成功~')
})

4.9、中间件应用-多个文件上传

image.png

const express = require('express')
const multer = require('multer')// 创建app对象
const app = express()// 应用一个express编写第三方的中间件
const upload = multer({// dest: './uploads'storage: multer.diskStorage({destination(req, file, callback) {callback(null, './uploads')},// 自定义文件名filename(req, file, callback) {callback(null, Date.now() + '_' + file.originalname)}})
})// 编写中间件
// 上传单文件: single方法
app.post('/avatar', upload.single('avatar') , (req, res, next) => {console.log(req.file)res.end('文件上传成功~')
})// 上传多文件: 
app.post('/photos', upload.array('photos'), (req, res, next) => {console.log(req.files)res.end('上传多张照片成功~')
})// 启动服务器
app.listen(9000, () => {console.log('express服务器启动成功~')
})

5.0、中间件应用-formdata解析

image.png

const express = require('express')
const multer = require('multer')// 创建app对象
const app = express()// express内置的插件
app.use(express.json())
app.use(express.urlencoded({ extended: true }))// 编写中间件
const formdata = multer()app.post('/login', formdata.any(), (req, res, next) => {console.log(req.body)res.end('登录成功, 欢迎回来~')
})// 启动服务器
app.listen(9000, () => {console.log('express服务器启动成功~')
})

5.1、客户端参数解析

image.png

image.png

const express = require('express')// 创建app对象
const app = express()// 编写中间件
// 1.解析queryString
app.get('/home/list', (req, res, next) => {// offset/sizeconst queryInfo = req.queryconsole.log(queryInfo)res.end('data list数据')
})// 2.解析params参数
app.get('/users/:id', (req, res, next) => {const id = req.params.idres.end(`获取到${id}的数据~`)
})// 启动服务器
app.listen(9000, () => {console.log('express服务器启动成功~')
})

5.2、服务器响应数据类型

image.png

const express = require('express')// 创建app对象
const app = express()// 编写中间件
app.post('/login', (req, res, next) => {// 1.res.end方法(比较少)// res.end('登录成功, 欢迎回来~')// 2.res.json方法(最多)// res.json({//   code: 200,//   message: '欢迎回来~',//   list: [//     { name: 'iPhone', price: 111 },//     { name: 'iPad', price: 111 },//     { name: 'iMac', price: 111 },//     { name: 'Mac', price: 111 },//   ]// })// 3.res.status方法: 设置http状态码res.status(201)res.json('创建用户成功~')
})// 启动服务器
app.listen(9000, () => {console.log('express服务器启动成功~')
})

5.3、Express的路由

image.png

router/userRouter.js


const express = require('express')// 1.创建路由对象
const userRouter = express.Router()// 2.定义路由对象中的映射接口
userRouter.get('/', (req, res, next) => {res.json('用户列表数据')
})
userRouter.get('/:id', (req, res, next) => {const id = req.params.idres.json('某一个用户的数据:' + id)
})
userRouter.post('/', (req, res, next) => {res.json('创建用户成功')
})
userRouter.delete('/:id', (req, res, next) => {const id = req.params.idres.json('删除某一个用户的数据:' + id)
})
userRouter.patch('/:id', (req, res, next) => {const id = req.params.idres.json('修改某一个用户的数据:' + id)
})// 3.将路由导出
module.exports = userRouter
const express = require('express')
const userRouter = require('./router/userRouter')// 创建app对象
const app = express()// 编写中间件
app.post('/login', (req, res, next) => {})app.get('/home', (req, res, next) => {})/** 用户的接口 */
// 1.将用户的接口直接定义在app中
// app.get('/users', (req, res, next) => {})
// app.get('/users/:id', (req, res, next) => {})
// app.post('/users', (req, res, next) => {})
// app.delete('/users/:id', (req, res, next) => {})
// app.patch('/users/:id', (req, res, next) => {})// 2.将用户的接口定义在单独的路由对象中
// const userRouter = express.Router()
// userRouter.get('/', (req, res, next) => {
//   res.json('用户列表数据')
// })
// userRouter.get('/:id', (req, res, next) => {
//   const id = req.params.id
//   res.json('某一个用户的数据:' + id)
// })
// userRouter.post('/', (req, res, next) => {
//   res.json('创建用户成功')
// })
// userRouter.delete('/:id', (req, res, next) => {
//   const id = req.params.id
//   res.json('删除某一个用户的数据:' + id)
// })
// userRouter.patch('/:id', (req, res, next) => {
//   const id = req.params.id
//   res.json('修改某一个用户的数据:' + id)
// })// 让路由生效
app.use('/users', userRouter)// 启动服务器
app.listen(9000, () => {console.log('express服务器启动成功~')
})

5.4、express的静态资源服务器

const express = require('express')// 创建app对象
const app = express()// 内置的中间件: 直接将一个文件夹作为静态资源
app.use(express.static('./uploads'))
app.use(express.static('./build'))// 编写中间件
app.post('/login', (req, res, next) => {})// 启动服务器
app.listen(9000, () => {console.log('express服务器启动成功~')
})

5.5、express中错误处理的方案

const express = require('express')// 创建app对象
const app = express()app.use(express.json())// 编写中间件
app.post('/login', (req, res, next) => {// 1.获取登录传入的用户名和密码const { username, password } = req.body// 2.对用户名和密码进行判断if (!username || !password) {next(-1001)} else if (username !== 'coderwhy' || password !== '123456') {next(-1002)} else {res.json({code: 0,message: '登录成功, 欢迎回来~',token: '323dfafadfa3222'})}
})// 错误处理的中间件
app.use((errCode, req, res, next) => {const code = errCodelet message = '未知的错误信息'switch(code) {case -1001:message = '没有输入用户名和密码'breakcase -1002:message = '输入用户名或密码错误'break}res.json({ code, message })
})// 启动服务器
app.listen(9000, () => {console.log('express服务器启动成功~')
})

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/76836.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【每日易题】数据结构链表篇——单链表oj题(1),几道典型例题带你快速掌握单链表

君兮_的个人主页 勤时当勉励 岁月不待人 C/C 游戏开发 Hello,米娜桑们,这里是君兮_,今天来填一个埋了好久的坑,在暑假之前就预告过这个系列,但由于各种原因(主要是有点懒)今天才开坑。我们这个系列主要是…

1310. 数三角形

题目链接:https://www.acwing.com/problem/content/1312/ 首先不考虑三点共线的情况一共有 种,现在来计算三点共线的情况 1.三点在一条直线上 2.三点在一条竖线上 3.三点在一条斜线上,正反斜线对称,仅需考虑一边的情况 如果…

视频汇聚平台EasyCVR视频广场侧边栏支持拖拽

为了提升用户体验以及让平台的操作更加符合用户使用习惯,我们在EasyCVR v3.3版本中,支持面包屑侧边栏的广场视频、分组列表、收藏这三个模块拖拽排序,并且该操作在视频广场、视频调阅、电子地图、录像回放等页面均能支持。 TSINGSEE青犀视频…

服务器运行python程序的使用说明

服务器的使用与说明 文章目录 服务器的使用与说明1.登录2.Python的使用2.1 服务器已安装python32.2 往自己的用户目录安装python31.首先下载安装包2.解压缩3.编译与安装 2.3 新建环境变量2.4 测试 3 创建PBS作业并提交 1.登录 windowsr打开运行命令窗口,在运行框中…

【万字长文】SpringBoot整合Atomikos实现多数据源分布式事务(提供Gitee源码)

前言:在最近的实际开发的过程中,遇到了在多数据源的情况下要保证原子性的问题,这个问题当时遇到了也是思考了一段时间,后来通过搜集大量资料与学习,最后是采用了分布式事务来解决这个问题,在讲解之前&#…

puppeteer监听response并封装为express服务调用

const express require(express); const puppeteer require(puppeteer); const app express(); let browser; // 声明一个全局变量来存储浏览器实例app.get(/getInfo, async (req, res) > {try {const page_param req.query.page; // 获取名为"page"的查询参数…

接口测试之文件上传

在日常工作中,经常有上传文件功能的测试场景,因此,本文介绍两种主流编写上传文件接口测试脚本的方法。 首先,要知道文件上传的一般原理:客户端根据文件路径读取文件内容,将文件内容转换成二进制文件流的格式…

Gson:解析JSON为复杂对象:TypeToken

需求 通过Gson&#xff0c;将JSON字符串&#xff0c;解析为复杂类型。 比如&#xff0c;解析成如下类型&#xff1a; Map<String, List<Bean>> 依赖&#xff08;Gson&#xff09; <dependency><groupId>com.google.code.gson</groupId><art…

MyBatis查询数据库之一(概念+创建项目+基础交互)

目录 1.MyBatis是什么&#xff1f; 2.为什么学习MyBatis&#xff1f; 3. 怎么学 MyBatis 4.第⼀个MyBatis查询 4.1 添加MyBatis框架支持 4.1.1老项目添加MyBatis 4.1.2 新项目添加MyBatis 4.2 配置连接字符串和MyBatis 4.2.1 配置连接字符串 4.2.2 配置 MyBatis 中的…

eNSP:ospf和mgre的配置

实验要求&#xff1a; 第一步&#xff1a;路由、IP的配置 r1&#xff1a; <Huawei>sys Enter system view, return user view with CtrlZ. [Huawei]sys r1 [r1]int loop0 [r1-LoopBack0]ip add 192.168.1.1 24 [r1-LoopBack0]int g0/0/0 [r1-GigabitEthernet0/0/0]ip a…

Golang之路---04 并发编程——信道/通道

信道/通道 如果说 goroutine 是 Go语言程序的并发体的话&#xff0c;那么 channel&#xff08;信道&#xff09; 就是 它们之间的通信机制。channel&#xff0c;是一个可以让一个 goroutine 与另一个 goroutine 传输信息的通道&#xff0c;我把他叫做信道&#xff0c;也有人将…

基于STM32CubeMX和keil采用通用定时器中断实现固定PWM可调PWM波输出分别实现LED闪烁与呼吸灯

文章目录 前言1. PWM波阐述2. 通用定时器2.1 为什么用TIM142.2 TIM14功能介绍2.3 一些配置参数解释2.4 PWM实现流程&中断2.4.1 非中断PWM输出(LED闪烁)2.4.2 中断PWM输出(LED呼吸灯) 3. STM32CubeMX配置3.1 GPIO配置3.2 时钟配置3.3 定时器相关参数配置3.4 Debug配置3.5 中…

C# Blazor 学习笔记(11):路由跳转和信息传值

文章目录 前言路由跳转测试用例路由传参/路由约束想法更新&#xff1a;2023年8月4日 前言 Blazor对路由跳转进行了封装。 ASP.NET Core Blazor 路由和导航 NavigationManager 类 本文的主要内容就是全局的跳转 路由跳转 路由跳转就要用到NavigationManager 类。 其实最常用…

【腾讯云Cloud Studio实战训练营】使用React快速构建点餐H5

文章目录 前言一、Cloud Studio是什么二、Cloud Studio特点三、Cloud Studio使用1.访问官网2.账号注册3.模板选择4.模板初始化5.H5开发安装 antd-mobile安装 Less安装 normalize&#xff1a;上传项目需要的素材&#xff1a;替换App.js主文件&#xff1a;项目启动、展示 6.发布仓…

K8s中的Secret

Secret作用&#xff1a;加密数据存在etcd里面&#xff0c;让pod容器以挂载Volume方式进行访问。场景&#xff1a;凭据

数据集相关网站(Open datasets and sources)

数据集相关网站(Open datasets and sources&#xff09; 数据集网站 Open datasets and sources政府数据网站 Government Data:金融数据网站 Financial Data Sources:犯罪数据网站 Crime Data:健康数据网站 Health Data:学术和商业数据网站 Academic and Business Data:其他数据…

用C语言构建一个数字识别卷积神经网络

卷积神经网络的具体原理和对应的python例子参见末尾的参考资料2.3. 这里仅叙述卷积神经网络的配置, 其余部分不做赘述&#xff0c;构建和训练神经网络的具体步骤请参见上一篇: 用C语言构建一个手写数字识别神经网路 卷积网络同样采用简单的三层结构&#xff0c;包括输入层con…

最新2024届【海康威视】内推码【GTK3B6】

最新2024届【海康威视】内推码【GTK3B6】 【内推码使用方法】 1.请学弟学妹们登录校招官网&#xff0c;选择岗位投递简历&#xff1b; 2.投递过程中填写内推码完成内推步骤&#xff0c;即可获得内推特权。 内推码&#xff1a;GTK3B6 内推码&#xff1a;GTK3B6 内推码&…

01背包笔记

01背包题目链接 题意&#xff1a;有一个容量为m的背包以及n个可以拿的物品&#xff0c;给出n个物品的体积和价值&#xff0c;要求输出可以拿的最大价值 思路&#xff1a;代表在前i件物品中拿取总体积不超过j的最大价值 由此可以分情况讨论状态转移 当j<v[i]时&#xff0c;说…