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.mzph.cn/news/18897.shtml

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

相关文章

AdvancedInstaller打包程序

文章目录 1. AdvancedInstaller 下载2. AdvancedInstaller 启动3. 新建工程4. 配置安装包详细信息5. 配置安装参数6. 添加要打包的文件7. 设置安装完成后启动程序8. 构建打包 1. AdvancedInstaller 下载 下载网址:https://www.advancedinstaller.com/ 2. AdvancedIn…

error: #5: cannot open source input file “core_cmInstr.h“

GD32F103VET6和STM32F103VET6引脚兼容。 GD32F103VET6工程模板需要包含头文件:core_cmInstr.h和core_cmFunc.h,这个和STM32F103还是有区别的,否则会报错,如下: error: #5: cannot open source input file "core…

Springboot之把外部依赖包纳入Spring容器管理的两种方式

前言 在Spring boot项目中,凡是标记有Component、Controller、Service、Configuration、Bean等注解的类,Spring boot都会在容器启动的时候,自动创建bean并纳入到Spring容器中进行管理,这样就可以使用Autowired等注解,…

MQ面试题3

1、讲一讲Kafka与RocketMQ中存储设计的异同? Kafka 中文件的布局是以 Topic/partition ,每一个分区一个物理文件夹,在分区文件级别实现文件顺序写,如果一个Kafka集群中拥有成百上千个主题,每一个主题拥有上百个分区&am…

《Vue3+Typescript》一个简单的日历组件实现

这是一个没有套路的前端博主,热衷各种前端向的骚操作,经常想到哪就写到哪,如果有感兴趣的技术和前端效果可以留言~博主看到后会去代替大家踩坑的~ 主页: oliver尹的主页 格言: 跌倒了爬起来就好~ 目录 一、…

架构的分类

目录 一、 RUP41 架构 1.1 RUP41架构方法概述 1.2 RUP41架构总体 1.3 RUP41架构方法内容 1.3.1 逻辑视图 1.3.2 开发视图 1.3.3 物理视图 1.3.4 处理视图 1.3.5 场景视图 ​二、 TOGAF9 架构 2.1 TOGAF9 架构概述 2.2 TOGAF9 架构分类 2.2.1 业务架构 2.2.2 数据架…

【1.3】Java微服务:Spring Cloud版本说明

✅作者简介:大家好,我是 Meteors., 向往着更加简洁高效的代码写法与编程方式,持续分享Java技术内容。 🍎个人主页:Meteors.的博客 💞当前专栏: 微服务 ✨特色专栏: 知识分享 &#x…

django4.2 day1Django快速入门

1、创建虚拟环境 打开cmd安装virtualenv pip install virtualenvwrapper-winworkon 查看虚拟环境mkvirtualenv 创建新的虚拟环境删除虚拟环境 rmvirtualenv 进入虚拟环境 workon env 2、创建django虚拟环境并安装django 创建虚拟环境mkvirtualenv django4env进入虚拟环境安…

Spring Boot Starter 剖析与实践 | 京东云技术团队

引言 对于 Java 开发人员来说,Spring 框架几乎是必不可少的。它是一个广泛用于开发企业应用程序的开源轻量级框架。近几年,Spring Boot 在传统 Spring 框架的基础上应运而生,不仅提供了 Spring 的全部功能,还使开发人员更加便捷地…

Redis 简介

文章目录 Redis 简介 Redis 简介 Redis(Remote Dictionary Server),远程词典服务器,基于 C/S 架构,是一个基于内存的键值型 NoSQL 数据库,开源,遵守 BSD 协议,Redis 由 C语言 实现。…

P4145 上帝造题的七分钟 2 / 花神游历各国

上帝造题的七分钟 2 / 花神游历各国 题目背景 XLk 觉得《上帝造题的七分钟》不太过瘾,于是有了第二部。 题目描述 "第一分钟,X 说,要有数列,于是便给定了一个正整数数列。 第二分钟,L 说,要能修改…

《向量数据库指南》——腾讯云向量数据库Tencent Cloud VectorDB产品特性,架构和应用场景

腾讯云向量数据库(Tencent Cloud VectorDB)是一款全托管的自研企业级分布式数据库服务,专用于存储、检索、分析多维向量数据。该数据库支持多种索引类型和相似度计算方法,单索引支持 10 亿级向量规模,可支持百万级 QPS 及毫秒级查询延迟。腾讯云向量数据库不仅能为大模型提…

JAVA开发工具-maven的安装与配置(最新最详细教程)

引言 Maven项目对象模型(POM),可以通过一小段描述信息来管理项目的构建,报告和文档的项目管理工具 软件。 Maven 除了以程序构建能力为特色之外,还提供高级项目管理工具。由于 Maven 的缺省构建规则有较 高的可重用性,所以常常用两…

模电专题-MOS管的放大电路分析

在实际应用中,我们经常会使用到功率MOS,这时通常不会将它当成一个开关使用,而是当成一个放大器来使用,那这就需要让其工作在放大状态。 参考下图中的mos管的特性曲线,右图中的输出特性曲线中有一根红色的分界线&#x…

竞速榜实时离线对数方案演进介绍 | 京东云技术团队

一、背景 竞速榜是大促期间各采销群提供的基于京东实时销售数据的排行榜,同样应对大促流量洪峰场景,通过榜单撬动品牌在京东增加资源投入。竞速榜基于用户配置规则进行实时数据计算,榜单排名在大促期间实时变化,相关排名数据在微…

【雕爷学编程】Arduino动手做(181)---Maixduino AI开发板2

37款传感器与执行器的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止这37种的。鉴于本人手头积累了一些传感器和执行器模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的&am…

roop 视频换脸

roop: one click face swap. 只用一张人脸图片,就能完成视频换脸。 项目地址: https://github.com/s0md3v/roopColab 部署: https://github.com/dream80/roop_colab 本文是本地部署的实践记录。 环境基础 OS: Ubuntu 22.04.2 LTSKernel: 5…

操作系统专栏2-文件系统from小林coding

文件系统 文件系统构成虚拟文件系统文件的使用文件的存储连续存储非连续空间存放方式链表方式索引方式 Linux文件的实现方式 空闲分区的管理文件系统结构目录的存储软链接和硬链接 文件系统构成 Linux的设计哲学有一点很重要:一切皆文件,不仅仅是普通的文件和目录,就连块设备,…

程序员面试金典17.*

文章目录 17.01 不用加号的加法17.04 消失的数字17.05字母与数字17.06 2出现的次数17.07 婴儿名字17.08 马戏团人塔17.09 第k个数17.10 主要元素17.11 单词距离17.12 BiNode17.13 恢复空格(未做,字典树dp)17.14 最小K个数17.15 最长单词17.16…