【Node.js】Express学习笔记(黑马)

目录

  • 初识 Express
    • Express 简介
    • Express 的基本使用
    • 托管静态资源
    • nodemon
  • Express 路由
    • 路由的概念
    • 路由的使用
  • Express 中间件
    • 中间件的概念
    • Express 中间件的初体验
    • 中间件的分类

初识 Express

Express 简介

什么是 Express?

  • 官方给出的概念:Express 是基于 Node.js 平台,快速、开放、极简的 Web 开发框架。
  • 通俗的理解:Express 的作用和 Node.js 内置的 http 模块类似,是专门用来创建 Web 服务器的。
  • Express 的本质:就是一个 npm 上的第三方包,提供了快速创建 Web 服务器的便捷方法。

Express 的中文官网: http://www.expressjs.com.cn/

进一步理解 Express:

  • 思考:不使用 Express 能否创建 Web 服务器?
    答案:能,使用 Node.js 提供的原生 http 模块即可。
  • 思考:既生瑜何生亮(有了 http 内置模块,为什么还有用 Express)?
    答案:http 内置模块用起来很复杂,开发效率低;Express 是基于内置的 http 模块进一步封装出来的,能够极大的提高开发效率
  • 思考:http 内置模块与 Express 是什么关系?
    答案:类似于浏览器中 Web API 和 jQuery 的关系。后者是基于前者进一步封装出来的。

Express 能做什么?
对于前端程序员来说,最常见的两种服务器,分别是:

  • Web 网站服务器:专门对外提供 Web 网页资源的服务器。
  • API 接口服务器:专门对外提供 API 接口的服务器。

使用 Express,我们可以方便、快速的创建 Web 网站的服务器或 API 接口的服务器。

Express 的基本使用

1. 安装
在项目所处的目录中,运行如下的终端命令,即可将 express 安装到项目中使用:

npm install express --save也可以安装指定版本的express
npm install express@4.17.1

2. 创建基本的Web服务器
在安装express的目录下新建 app.js 文件,并插入如下代码:

// 1.导入 express
const express = require('express')
// 2.创建 web 服务器
const app = express()
// 3.调用 app.listen(端口号, 启动成功后的回调函数),启动服务器
app.listen(80, () => {console.log('服务器已启动(地址:http://127.0.0.1)')
})

然后在终端中运行所创建的web服务器:

node app.js

如果运行成功,就会在控制台打印服务器已启动(地址:http://127.0.0.1),在浏览器访问链接可以看到返回的Cannot GET /,因为我们还没有写具体的请求响应内容。

3.监听GET请求
通过 app.get() 方法,可以监听客户端的 GET 请求,具体语法如下:

// 参数1:客户端请求的 URL 地址
// 参数2:请求对应的处理函数
//      req:请求对象(包含了与请求相关的属性和方法)
//      res:响应对象(包含了与响应相关的属性和方法)
app.get('请求URL', function(req, res) { /* 处理函数 */ })

4.监听 POST 请求
通过 app.post() 方法,可以监听客户端的 POST 请求,具体的语法格式如下:

// 参数1:客户端请求的 URL 地址
// 参数2:请求对应的处理函数
//      req:请求对象(包含了与请求相关的属性和方法)
//      res:响应对象(包含了与响应相关的属性和方法)
app.post('请求URL', function(req, res) { /* 处理函数 */ })

5.把内容响应给客户端
通过 res.send() 方法,可以把处理好的内容,发送给客户端:

const express = require('express')
const app = express()app.get('/user', function(req, res) {// 向客户端发送 JSON 对象res.send({ name:'张三', age:20, gender:'男' })
})
app.post('/user', function(req, res) {// 向客户端发送文本内容res.send('post请求成功')
})app.listen(80, () => {console.log('服务器已启动(地址:http://127.0.0.1)')
})

通过node 文件名命令运行服务器后,对http://127.0.0.1/user发起get或post请求就可以分别得到res.send发送的数据。

在浏览器打开http://127.0.0.1/user也可以看到所定义的JSON对象在页面上显示,因为浏览器打开默认是GET请求
在这里插入图片描述

6.获取 URL 中携带的查询参数
通过 req.query 对象,可以访问到客户端通过查询字符串的形式,发送到服务器的参数:

app.get('/', function(req, res) {// req.query 默认是一个空对象// 客户端可以使用 ?name=zs&age=20 这种查询字符串形式,将参数发送到服务器// 发送到服务器的参数可以通过req.query访问到// 如:req.query.nameconsole.log(req.query)
})

运行服务器,浏览器访问http://127.0.0.1/?name=zs&age=20即可在服务器控制台输出如下内容:
在这里插入图片描述

7. 获取 URL 中的动态参数
通过 req.params 对象,可以访问到 URL 中,通过 : 匹配到的动态参数:

app.get('/user/:id', function(req, res) {// req.params 是一个空对象// 里面存放着通过 : 动态匹配到的参数值console.log(req.params)
})

运行服务器,浏览器访问http://127.0.0.1/user/2即可在服务器控制台输出如下内容:
在这里插入图片描述

托管静态资源

1.express.static()
express 提供了一个非常好用的函数,叫做 express.static(),通过它,我们可以非常方便地创建一个静态资源服务器
例如,通过如下代码就可以将 public 目录下的图片、CSS 文件、JavaScript 文件对外开放访问了:

app.use(express.static('public'))

现在,你就可以访问 public 目录中的所有文件了:
http://localhost:3000/images/bg.jpg
http://localhost:3000/css/style.css
http://localhost:3000/js/login.js

注意:Express 在指定的静态目录中查找文件,并对外提供资源的访问路径。因此,存放静态文件的目录名不会出现在 URL 中

2.托管多个静态资源目录
如果要托管多个静态资源目录,请多次调用 express.static() 函数:

const express = require('express')
const app = express()app.use(express.static('public'))
app.use(express.static('files'))app.listen(80, () => {console.log('服务器已启动(地址:http://127.0.0.1)')
})

3.挂载路径前缀
如果希望在托管的静态资源访问路径之前,挂载路径前缀,则可以使用如下的方式:

app.use('/public', express.static('public'))

现在,你就可以通过带有 /public 前缀地址来访问 public 目录中的文件了:
http://localhost:3000/public/images/kitten.jpg
http://localhost:3000/public/css/style.css
http://localhost:3000/public/js/app.js

nodemon

1.为什么要使用 nodemon
在编写调试 Node.js 项目的时候,如果修改了项目的代码,则需要频繁的手动 close 掉,然后再重新启动,非常繁琐。
现在,我们可以使用 nodemon(https://www.npmjs.com/package/nodemon) 这个工具,它能够监听项目文件的变动,当代码被修改后,nodemon 会自动帮我们重启项目,极大方便了开发和调试。

2.安装 nodemon
在终端中,运行如下命令,即可将 nodemon 安装为全局可用的工具:

npm install -g nodemon

3.使用 nodemon
当基于 Node.js 编写了一个网站应用的时候,传统的方式,是运行 node app.js 命令,来启动项目。

这样做的坏处是:代码被修改之后,需要手动重启项目。

现在,我们可以将 node 命令替换为 nodemon 命令,使用 nodemon app.js 来启动项目。

这样做的好处是:代码被修改之后,会被 nodemon 监听到,从而实现自动重启项目的效果。

node app.js
# 将上面的终端命令,替换为下面的终端命令,即可实现自动重启项目的效果
nodemon app.js

Express 路由

路由的概念

1.什么是路由

广义上来讲,路由就是映射关系

2.Express 中的路由

在 Express 中,路由指的是客户端的请求服务器处理函数之间的映射关系

Express 中的路由分 3 部分组成,分别是请求的类型请求的 URL 地址处理函数,格式如下:

app.METHOD(PATH, HANDLER)

3.路由的匹配过程

每当一个请求到达服务器之后,需要先经过路由的匹配,只有匹配成功之后,才会调用对应的处理函数。

在匹配时,会按照路由的顺序进行匹配,如果请求类型请求的 URL 同时匹配成功,则 Express 会将这次请求,转交给对应的 function 函数进行处理。
在这里插入图片描述
路由匹配的注意点:
① 按照定义的先后顺序进行匹配
请求类型请求的URL同时匹配成功,才会调用对应的处理函数

路由的使用

1.最简单的用法
在 Express 中使用路由最简单的方式,就是把路由挂载到 app 上,示例代码如下:

const express = require('express')
// 创建Web服务器,并命名为 app
const app = express()// 挂载路由
// 匹配 GET 请求,且请求 URL 为 /
app.get('/', (req, res) => { res.send('hello world.') })
// 匹配 POST 请求,且请求 URL 为 /
app.post('/', (req, res) => { res.send('Post Request.') })app.listen(80, () => { console.log('http://127.0.0.1') })

2.模块化路由
为了方便对路由进行模块化的管理,Express 不建议将路由直接挂载到 app 上,而是推荐将路由抽离为单独的模块

将路由抽离为单独模块的步骤如下

  1. 创建路由模块对应的.js文件
  2. 调用 express.Router() 函数创建路由对象
  3. 向路由对象上挂载具体的路由
  4. 使用module.exports 向外共享路由对象
  5. 使用app.use()函数注册路由模块

3.创建路由模块实例
在安装Express的项目目录下新建router.js文件,并添加以下代码:

// 这是路由模块
// 1. 导入 express
const express = require('express')
// 2. 创建路由对象
const router = express.Router()// 3. 挂载具体的路由
router.get('/user/list', (req, res) => {res.send('Get user list.')
})
router.post('/user/add', (req, res) => {res.send('Add new user.')
})// 4. 向外导出路由对象
module.exports = router

新建app.js文件,在app.js中导入并使用路由模块

const express = require('express')
const app = express()// 1. 导入路由模块
const router = require('./router')
// 2. 注册路由模块,并添加统一的访问前缀 /api ,便于分类
app.use('/api', router)// 注意: app.use() 函数的作用,就是来注册全局中间件app.listen(80, () => {console.log('http://127.0.0.1')
})

当请求地址为http://127.0.0.1/api/user/list,且请求方式为 GET 时,可以得到Get user list.的响应

Express 中间件

中间件的概念

1.什么是中间件
中间件(Middleware ),特指业务流程的中间处理环节

2.Express 中间件的调用流程
当一个请求到达 Express 的服务器之后,可以连续调用多个中间件,从而对这次请求进行预处理。
在这里插入图片描述

3.Express 中间件的格式
Express 的中间件,本质上就是一个function 处理函数,Express 中间件的格式如下:
在这里插入图片描述
注意:中间件函数的形参列表中,必须包含 next 参数。而路由处理函数中只包含 req 和 res。

4.next 函数的作用
next 函数是实现多个中间件连续调用的关键,它表示把流转关系转交给下一个中间件或路由。
在这里插入图片描述

Express 中间件的初体验

1.定义中间件函数
可以通过如下的方式,定义一个最简单的中间件函数:

// 定义一个最简单的中间件函数
const mw = function (req, res, next) {console.log('这是最简单的中间件函数')// 把流转关系,转交给下一个中间件或路由next()
}// 将 mw 注册为全局生效的中间件
app.use(mw)

或者也可以简写为如下格式:

app.use((req, res, next) => {console.log('这是最简单的中间件函数')next()
})

实例:

const express = require('express')
const app = express()// 这是定义全局中间件的简化形式
app.use((req, res, next) => {console.log('这是最简单的中间件函数')next()
})app.get('/', (req, res) => {console.log('调用了 / 这个路由')res.send('Home page.')
})
app.get('/user', (req, res) => {console.log('调用了 /user 这个路由')res.send('User page.')
})app.listen(80, () => {console.log('http://127.0.0.1')})

2.中间件的作用
多个中间件之间,共享同一份 req 和 res。基于这样的特性,我们可以在上游的中间件中,统一为 req 或 res 对象添加自定义的属性或方法,供下游的中间件或路由进行使用。
在这里插入图片描述

3.定义多个全局中间件
可以使用 app.use() 连续定义多个全局中间件。客户端请求到达服务器之后,会按照中间件定义的先后顺序依次进行调用,示例代码如下:

const express = require('express')
const app = express()// 定义第一个全局中间件
app.use((req, res, next) => {console.log('调用了第1个全局中间件')next()
})
// 定义第二个全局中间件
app.use((req, res, next) => {console.log('调用了第2个全局中间件')next()
})// 定义一个路由
app.get('/user', (req, res) => {res.send('User page.')
})app.listen(80, () => {console.log('http://127.0.0.1')
})

4.局部生效的中间件
不使用 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 server running at http://127.0.0.1')
})

当访问http://127.0.0.1/时,终端输出调用了局部生效的中间件
当访问http://127.0.0.1/user时,不调用定义的局部中间件函数

5.定义多个局部中间件
可以在路由中,通过如下两种等价的方式,使用多个局部中间件:

const express = require('express')
const app = express()// 1. 定义中间件函数
const mw1 = (req, res, next) => {console.log('调用了第一个局部生效的中间件')next()
}const mw2 = (req, res, next) => {console.log('调用了第二个局部生效的中间件')next()
}// 2. 创建路由
app.get('/', [mw1, mw2], (req, res) => {res.send('Home page.')
})
app.get('/user', (req, res) => {res.send('User page.')
})app.listen(80, function () {console.log('Express server running at http://127.0.0.1')
})

6.了解中间件的5个使用注意事项
① 一定要在路由之前注册中间件
② 客户端发送过来的请求,可以连续调用多个中间件进行处理
③ 执行完中间件的业务代码之后,不要忘记调用 next() 函数
④ 为了防止代码逻辑混乱,调用 next() 函数后不要再写额外的代码
⑤ 连续调用多个中间件时,多个中间件之间,共享 req 和 res 对象

中间件的分类

为了方便大家理解和记忆中间件的使用,Express 官方把常见的中间件用法,分成了 5 大类,分别是:

  • 应用级别的中间件
  • 路由级别的中间件
  • 错误级别的中间件
  • Express 内置的中间件
  • 第三方的中间件

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

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

相关文章

navicat远程连接mysql的异常解决-1130-2003-10061

结论: 1、修改数据库下root用户的host字段(为空或%) 2、修改 /etc/mysql/mysql.conf.d/mysqld.cnf 文件下 bind-address 的配置为 0.0.0.0 或者屏蔽此配置内容 (默认配置是: bind-address 127.0.0.1) 补充: 查看数据库下用户与host字段的关…

3D医疗图像配准 | 基于Vision-Transformer+Pytorch实现的3D医疗图像配准算法

项目应用场景 面向医疗图像配准场景,项目采用 Pytorch ViT 来实现,形态为 3D 医疗图像的配准。 项目效果 项目细节 > 具体参见项目 README.md (1) 模型架构 (2) Vision Transformer 架构 (3) 量化结果分析 项目获取 https://download.csdn.net/down…

【uniapp】vscode安装插件、ts校验、允许json文件注释

1、vscode安装的插件: uni-create-viewuni-hlperuniapp小程序扩展 2、ts校验 安装插件: pnpm i -D types/wechat-miniprogram uni-helper/uni-app-types配置tsconfig.json {"extends": "vue/tsconfig/tsconfig.json","compi…

内核是如何接收⽹络包的?

应用层做的那么舒服,为什么还要去看驱动和内核? “工作了四五年,并不是有4-5年经验,⽽是⼯作了4-5年⽽已” 引言 Linux里最重要的一个模块-网络模块,用简单的udp来举例,下图是我在大学的时候的基于linux的socket网络…

顶顶通呼叫中心中间件(mod_cti基于FreeSWITCH)-回铃音补偿

文章目录 前言联系我们解决问题操作步骤 前言 回铃音: 当别人打电话给你时,你的电话响铃了,而他听到的声音叫做回铃音。回铃音是被叫方向主叫方传送,也是彩铃功能的基础。我们平时打电话听到的“嘟 嘟 嘟 嘟”的声音,就…

mysql 查询实战-变量方式-解答

对mysql 查询实战-变量方式-题目,进行一个解答。(先看题,先做,再看解答) 1、查询表中⾄少连续三次的数字 1,处理思路 要计算连续出现的数字,加个前置变量,记录上一个的值&#xff0c…

postgresql uuid

示例数据库版本PG16,对于参照官方文档截图,可以在最上方切换到对应版本查看,相差不大。 方法一:自带函数 select gen_random_uuid(); 去掉四个斜杠,简化成32位 select replace(gen_random_uuid()::text, -, ); 官网介绍…

LoRa无线电机温振传感器,FlexLua低代码技术助力快速实现。

在物联网时代,无线传感技术的应用愈发广泛。其中,LoRa(长距离低功耗无线技术)作为一种适用于远距离、低功耗的通信技术,被广泛应用于各种物联网场景。而结合温度和振动传感技术,能够构建出用于监测机器状态…

pytest-yaml-sanmu(二):使用hook自定义yaml用例的执行方式

前言 本文抛砖引玉,通过以下几个测试框架的封装示例,一步步引导你实现属于自己的 yaml 测试框架: 加法测试 计算测试 接口测试 Web 测试 使用本插件需要对 Python 和 Pytest 较为熟练的应用经验,本文认为你已经具备这些条件。…

HTTP协议名词解释

一、HTTP协议通讯名词解释-URL URL(Uniform Resource Locator,统一资源定位符)是标识Web资源的唯一标识符。通过它即可获取其标识的资源。 最常用的URL格式如下: protocol://hostname[:port]/[path/Ifile[?paramvaluel 这个结构中有几个部分是可选的。如果端口…

Python数学建模学习-PageRank算法

1-基本概念 PageRank算法是由Google创始人Larry Page在斯坦福大学时提出,又称PR,佩奇排名。主要针对网页进行排名,计算网站的重要性,优化搜索引擎的搜索结果。PR值是表示其重要性的因子。 中心思想: 数量假设&#…

10kV配电室在线监控改造技术方案

安科瑞薛瑶瑶18701709087 摘要:目前,我国经济高速发展,社会在不断进步,国家加大了农村低压配电网络改造升级投入,低压配电网供电可靠性及供电质量得到明显提升,但低压配电网络自动化运维水平及农村电网用电…

如何使用Docker部署WPS Office服务并实现无公网IP远程处理文档表格

文章目录 1. 拉取WPS Office镜像2. 运行WPS Office镜像容器3. 本地访问WPS Office4. 群晖安装Cpolar5. 配置WPS Office远程地址6. 远程访问WPS Office小结 7. 固定公网地址 wps-office是一个在Linux服务器上部署WPS Office的镜像。它基于WPS Office的Linux版本,通过…

移动开发避坑指南——内存泄漏

在日常编写代码时难免会遇到各种各样的问题和坑,这些问题可能会影响我们的开发效率和代码质量,因此我们需要不断总结和学习,以避免这些问题的出现。接下来我们将围绕移动开发中常见问题做出总结,以提高大家的开发质量。本系列文章…

【Qt编译】ARM环境 Qt5.14.2-QtWebEngine库编译 (完整版)

ARM 编译Qt5.14.2源码 1.下载源码 下载Qt5.14.2源代码(可根据自己的需求下载不同版本) 下载网站:https://download.qt.io/new_archive/qt/5.14/5.14.2/single/ 2.相关依赖(如果需要的话) 先参考官方文档的需求进行安装: 官方…

第十五届蓝桥杯省赛C/C++大学B组真题及赛后总结

目录 个人总结 C/C 组真题 握手问题 小球反弹 好数 R 格式 宝石组合 数字接龙 爬山 拔河 ​编辑 再总结及后续规划 个人总结 第一次参加蓝桥杯,大二,以前都在在学技术,没有系统的学过算法。所以,还是花了挺多时间去备…

unity按路径移动

using System; using System.Collections; using System.Collections.Generic; using UnityEngine;public class FollowPathMove : MonoBehaviour {public Transform[] wayPointArray;[SerializeField] private Transform PathA;//路径点的父物体[SerializeField]private Trans…

用html写一个有趣的鬼魂动画

<!DOCTYPE html> <html lang"en" > <head><meta charset"UTF-8"><title>一个有趣的鬼魂动画</title><link rel"stylesheet" href"https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.m…

[leetcode] minimum-falling-path-sum

. - 力扣&#xff08;LeetCode&#xff09; 给你一个 n x n 的 方形 整数数组 matrix &#xff0c;请你找出并返回通过 matrix 的下降路径 的 最小和 。 下降路径 可以从第一行中的任何元素开始&#xff0c;并从每一行中选择一个元素。在下一行选择的元素和当前行所选元素最多…

a == 1 a== 2 a== 3 返回 true ?

1. 前言 下面这道题是 阿里、百度、腾讯 三个大厂都出过的面试题&#xff0c;一个前端同事跳槽面试也被问了这道题 // &#xff1f; 位置应该怎么写&#xff0c;才能输出 trueconst a ?console.log(a 1 && a 2 && a 3) 看了大厂的面试题会对面试官的精神…