web学习-Node.js入门学习
web学习-Node.js入门学习
- 1.回顾与思考
- 2. 初识Node.js
- 2.1 Node.js的简介
- 2.2Node.js的环境安装
- 2.3. fs文件系统模块
- 2.3.1 fs.readFile()
- 2.3.2 fs.writeFile()
- 2.3.3 练习-整理考试成绩
- 2.3.4 fs模块-路径动态拼接的问题
- 2.4 path路径模块
- 2.5 http模块
- 2.5.1 服务器相关的概念
- 2.5.2 创建最基本的web服务器
- 2.5.3 根据不同的url响应不同的html内容
- 3. 模块化
- 3.1 模块化的基本概念
- 3.2 Node.js中模块的分类
- 3.2.1 加载模块
- 3.2.2 模块作用域
- 3.2.3 向外共享模块作用域中的成员
- 3.3 npm与包
- 3.3.1 npm和包的概述
- 3.3.2 npm初体验
- 3.3.3 包管理配置文件
- 3.3.4 包的分类
- 3.3.5 开发属于自己的包
- 3.3.6 发布自己开发的包
- 3.4 模块的加载机制
- 4.Express
- 4.1 Express的基本使用
- 4.2 express路由
- 4.2.1 路由的介绍
- 4.2.2 路由的使用
- 4.3 express中间件
- 4.3.1 中间件的概念
- 4.3.2 Express 中间件的初体验
- 4.3.3 中间件的分类
- 4.3.4 自定义中间件
- 4.4使用Express写接口
- 4.4.1 接口实现
- 4.4.2 CORS跨域资源共享
- 4.4.3 JSONP接口
- 5. MySQL数据库
- 6 Web开发模式
- 6.1 身份认证
- 6.2 session认证机制
- 6.3 JWT认证机制
1.回顾与思考
浏览器中的JavaScript的组成部分:

为什么JavaScript可以在浏览器中执行:

为什么JavaScript可以操作DOM和BOM:

浏览器中的JavaScript运行环境(运行环境指的是代码正常运行所需的必要环境):

2. 初识Node.js
2.1 Node.js的简介
Node.js是一个基于Chrome V8引擎JavaScript运行环境,Node.js官网
Node.js中的JavaScript运行环境:

- Node.js可以做什么:Node.js作为一个JavaScript的运行环境,仅仅提供了基础的功能和API,然而,基于Node.js提供的这些基础功能,很多强大的工具和框架如雨后春笋,层出不穷,所以学习Node.js,可以让前端程序员胜任更多的工作和岗位:
- 基于Express框架 ,可以快速构建Web应用
- 基于Electron框架,可以构建跨平台的桌面应用
- 基于restify框架,可以快速构建API接口项目
- 读写和操作数据库、创建实用的命令行工具辅助前端开发、…
2.2Node.js的环境安装
如果希望通过Node.js来运行JavaScript代码,则必须在计算机上安装Node.js环境才能运行。
安装包可以去Node.js官网下载

LTS版本和Current版本的区别:- LTS为长期稳定版,对于
追求稳定性和企业级项目来说,推荐安装LTS版本的Node.js - Current为新特性尝鲜版,对热衷于尝试新特性的用户来说,推荐安装Current版本的Node.js,但是Current版本中可能存在隐藏的Bug或安全性漏洞,因此不推荐企业级项目中使用Current版本的Node.js
- LTS为长期稳定版,对于
如何确定Node.js已经安装成功:终端输入命令node -v可查看安装的版本,能看到安装的版本则表示安装成功, 否则没有安装成功

如何在Node.js环境中执行JavaScript的代码: 在终端进入到js文件目录下, 输入终端指令:node 要执行文件的路径

注意: 使用tab键, 能够快读不全路径
在终端中使用tab键快速不全路径, mac电脑不知道到支不支持
2.3. fs文件系统模块
fs模块是Node.js官方提供的、用来提供操作文件的模块。它提供了一系列的方法和属性,用来满足用户对文件的操作需求。
fs.readFile()方法,用来读取指定文件的内容fs.writeFile()方法,用来向指定的文件中写入内容
但是如果想要在JavaScript中,使用fs模块操作文件,则需要使用如下方式导入它:const fs = require(''fs)
2.3.1 fs.readFile()
fs.readFile(path, [options], callback)
参数解读:
- 参数1:
必选参数,字符串,表示文件路径 - 参数2:可选参数,表示以什么
编码格式来读取文件 - 参数3:
必选参数,文件读取完成后,通过回调函数拿到读取信息的结果

上面方法是正确读取文件的内容, 下面是 读取文件错误的错误信息打印
2.3.2 fs.writeFile()
fs.writeFile(path,data, [options], callback)
- 参数解读:
- 参数1:
必选参数,需要指定一个文件的路径 - 参数2:
必须参数,表示写入的内容 - 参数3:
可选参数,表示以什么格式写入文件内容,默认值是utf-8 - 参数4:
必选参数,文件写入完成后的回调函数 - 注意:只能用来创建文件,不能用来创建路径;重复调用write方法,新写入的内容会覆盖旧的内容
- 参数1:

文件写入成功,则error对象是null, 否则是一个错误对象。
2.3.3 练习-整理考试成绩

2.3.4 fs模块-路径动态拼接的问题
在使用fs模块操作文件时,如果提供的操作路径../或./开头的相对路径时,很容易出现路劲动态拼接错误的问题。
原因: 代码在运行的时候,会以执行node命令是所处的目录,动态拼接出被操作文件的完整路径。
解决方案: 在使用fs模块操作文件时,直接提供完整路径,不要提供./或../开头的相对路径,从而防止路径动态拼接的问题。



__dirname是一个固定路径,表示当前node文件执行文件所处在的目录

2.4 path路径模块
path模块:是Node.js官方提供的, 用来处理路径的模块, 它提供了一系列的方法和属性,用来满足用户对路径的处理需求path.join(): 用来将多个路径片段拼接成一个完整的路径字符串path.basename():用来从路径字符串中,将文件名解析出来注意:如果要在JavaScript代码中,使用path模块处理路径,则需要使用如下的方式先导入它:const path = require('path')
path.join([…paths])
- paths路径片段的序列
- 返回值:

path.basename()的示例代码

path.extname(): 获取路径中的扩展名部分,语法格式如下
path。extname(path)
- path 必选参数,表示一个路径的字符串
返回: 返回得到的扩展名字符串

2.5 http模块
http模块是Node.js官方提供的, 用来创建Web服务器的模块,通过http模块提供的http.createServer()方法,就能方便的把一台普通的电脑,变成一台Web服务器,从而对外提供Web资源服务
当然要使用http模块创建Web服务器,则需要先导入该模块:const http = require('http')
2.5.1 服务器相关的概念
服务器和普通电脑的区别在于,服务器上安装了web服务器软件, 例如:IIS、Apache等。通过安装这些服务软件就能把一台普通的电脑变成一台web服务器
在Node.js中,我们不需要使用这些第三方的web服务器。因为我们可以基于Node.js提供的http模块,通过几行简单的代码,就能轻松的手写一个服务器软件,从而对外听过web服务。
IP地址:表示互联网上每台计算机的唯一地址,因此IP地址具有唯一性。如果把个人电脑比作一台电话,那么IP地址就相当于电话号码,只有在知道对方IP地址的前提下,才能与对应的电脑之间进行数据通信。
IP地址的格式:通常使用点分十进制表示(a.b.c.d)的形式,其中a,b,c,d都是0~255之间的十进制整数。例如:用点份十进制的IP地址(192.168.1.1)
注意:
- 互联网中每台Web服务器,都有自己的IP地址,例如:大家可以在Windows的终端中运行
ping www.baidu.com命令,即可查看到百度服务器的IP地址- 在开发期间,自己的电脑既是一台服务器,也是一个客户端,为了方便测试,可以在自己的浏览器中输入127.0.0.1这个IP地址,就能发自己的电脑当做一台服务器进行访问了
**端口号:**计算机的端口号,就好想是现实生活中的门牌号一样。通过门牌号,外卖小哥可以在整栋大楼众多的房间中,准确的把外卖送到你手中。
同样的道理,在一台电脑中,可以运行成百上千个web服务器。每个web服务器都对应一个唯一的端口号。客户端发送过来的网络请求,铜鼓端口号,可以被准备地交给对应的web服务器进行处理

2.5.2 创建最基本的web服务器
- 导入http模块
- 创建web服务器实例
- 为服务器实例绑定
request事件,监听客户端的请求 - 启动服务器
然后再浏览器输入http://127.0.0.1访问本机, 输出控制台会输出如下信息。

req请求对象: 只要服务器接受到客户端的请求,就会调用server.on()为服务器绑定的request事假处理函数。如果想要在事件处理函数,访问与客户端相关的数据或属性可以使用如下方式:

res响应对象: 在服务器request事件处理函数中,如果访问与服务器相关的数据或属性,可以使用如下方式:

2.5.3 根据不同的url响应不同的html内容
- 核心实现步骤:
- 获取
请求的url地址 - 设置默认的响应内容为 404 Not found
- 判断用户请求的是否为
/或/index.html首页 - 判断用户请求是否为
/about.html关于页面 - 设置
Content-Type响应头,防止中文乱码 - 使用
res.end()把内容响应给客户端
- 获取

3. 模块化


3.1 模块化的基本概念
模块化:指解决一个复杂问题时,自顶向下逐层把系统划分成若干模块的过程。对于整个系统来说,模块是可组合、分解合更换的单元。
编程领域中的模块化,就是遵守固定的规则,把一个大文件拆分成独立并互相依赖的多个小模块。
把代码进行模块化 拆分的好处:
- 提高了代码的
复用性 - 提高了代码的
可维护性 - 可以实现
技术加载
模块化规范就是对代码进行模块化的拆分与组合时,需要遵守的那些规则。
例如:使用什么样的语法格式来引用模块、在模块中使用什么样的语法格式向外暴露成员
模块化规范的好处:大家都遵守同样的模块化规范写代码,降低了沟通成本,极大的方便了各个模块之间的相互调试。利人利己。
3.2 Node.js中模块的分类
Node.js中根据模块来源的不同,将模块化分为了3大类,分别是:
内置模块:内置模块是有Node.js官方提供的, 例如fs、path、http等自定义模块:用户创建的每个.js文件,都是自定义模块第三方模块:由第三方开发出来的模块,并非官方提供的内置模块,也不是用户创建的自定义模块,使用前需要先下载
3.2.1 加载模块
使用强大的require()方法,可以加载需要的内置模块、用户 自定义那模块、第三方模块进行使用:

注意:使用require()方法加载其他模块时,会执行被加载模块中的代码。在使用require()加载用户自定义模块期间,可以省略.js的后缀名

3.2.2 模块作用域
和函数作用域类似,在自定义模块中定义的变量、方法等成员,只能在当前模块内被访问,这种模块级别的访问限制,叫做模块作用域

模块作用域的好处: 防止了全局变量污染的问题

3.2.3 向外共享模块作用域中的成员
module对象:在每个.js自定义模块中都有一个module对象,它里面存储了和当前模块有关的信息,打印如下:

module.exports对象: 在自定义模块中,可以使用module.exports对象,将模块内的成员共享出去,供外界使用。外界用require()方法导入自定义模块时,得到的就是module.exports所指向的对象。

注意:使用require()方法导入模块时,导入的结果永远以module.exports指向的对象为准。

exports对象:由于module.exports单词写起来比较复杂,为了简化向外共享成员的代码,Node提供了exports对象,默认情况下,exports和module.exports指向同一个对象。最终共享的结果,还是以module.exports指向的对象为准

module.exports和exports的使用误区: 时刻谨记,require()模块时,得到的永远是module.exports指向的对象:

- Node.js中模块化规范:Node.js遵循了CommonJS模块化规范,CommonJS规定了
模块化特性和各模块之间如何相互依赖。CommonJS规定:- 每个模块内部, Module变量代表当前的模块
- module变量是一个对象, 它的exports属性,即
module.exports是对外的接口 - 加载某个模块, 其实是加载该模块的module.exports属性。
require()方法用于加载模块
3.3 npm与包
3.3.1 npm和包的概述
不同于Node.js中的内置模块与自定义模块, 包是由第三方个人或团队开发出来的,免费供所有人适用。
注意: Node.js中的包都是免费且开源的,不需要付费即可免费下载使用。
由于Node.js的内置模块仅仅提供了一些底层的API,导致在基于内置模块进行开发项目时,效率很低。
包是基于内置模块封装出来的,提供了更加高级的功能,更方便的API,极大提高了开发效率。
包和内置模块之间的关系,类似JQuery和浏览器内置API之间的关系。
- 搜索包的地址:https://www.npmjs.com
- 下载包的地址:https://registry.npmjs.org
npm,Inc公司除了提供上述地址之外,还提供了一个包管理工具Node Package Manager(简称npm包管理工具),这个工具随着Node.js的安装一起安装到电脑上了,大家可以在终端上执行npm -v命令,来查看电脑上所安装npm包管理工具的版本。

3.3.2 npm初体验
- 格式化时间的传统做法:

- 格式化时间的高级做法:
使用npm包管理工具,在具体的项目中安装格式化时间的包 monment- 使用require()导入格式化时间的包
- 参考monment的官方API 文档对时间进行格式化

在项目中安装包的命令:npm install 包的完整名称 , 上述命令还可以简写为npm i 完整包名称
那么初次安装包之后,多了哪些文件?
初次安装包完成后,在项目文件夹下多了一个叫做node_modules的文件夹和package-lock.json的配置文件。
node_modules文件夹用来存放所有已安装大项目中的包。require()导入第三方包时,就是从这个目录中查找并加载包的。
package-lock.json配置文件用来记录node_modules目录下的每一个包的下载信息,例如包的名字、版本号、下载地址等
注意: 程序员不要手动修改node_modules或package-lock.json文件中的任何代码,npm包管理工具会自动维护他们

默认情况下,使用npm install命令安装包的时候,会自动安装最新版本的包。如果需要指定安装指定版本的包,可以在包名之后,通过@符号指定具体的版本.例如:

包的版本号是以点分十进制形式进行定义的,总共有三位数字,例如2.24.0,其中每一位数字代表的含义如下:
- 第一位数字: 大版本
- 第二位数字:功能版本
- 第三位数字:Bug修复版本
版本号的提升规则: 只要前面的版本号增长,则后面的版本号归零。
3.3.3 包管理配置文件
npm 规定,在项目根目录中, 必须提供一个叫做package,.json的包管理配置文件。用来记录与项目有关的一些配置信息。例如:
- 项目的名称、版本号、描述等
- 项目中都用到了那些包
- 哪些包只在
开发期间会用到 - 那些包在
开发和部署时都需要用到
如果第三方的体积过大,不方便团队之间共享项目源代码。解决方案:共享时剔除node_modules
如何在记录项目中安装了哪些包?
在项目根目录中,创建了一个叫做package.json的配置文件,即可用来记录项目中安装了哪些包。从而方便剔除node_modules目录之后,在团队成员之间共享项目的源代码。
注意:在今后的项目开发中,一定要把node_modules文件夹,添加到.gitignore忽略文件中。
-
快速创建package.json : npm包管理工具提供了一个
快捷命令,可以在执行命令时所处的目录中快速创建package.json这个包管理配置文件:

-
如果包含中文和空格,会报名称不合法的错误
-
dependencies结点:package.json文件中,有一个dependencies结点,专门用来记录您使用npm install命令安装了哪些包

当我们拿到一个剔除了node_modules的项目之后,需要先把所有的包下载到项目中,才能将项目运行起来。否则会报类似于下面的错误:

可以运行npm install 命令或者npm i一次性安装所有的依赖包:

关于卸载包,可以运行命令npm uninstall命令来卸载指定的包,例如:npm uninstall moment, 这里需要注意的是 npm uninstall 命令执行成功后, 会把卸载的包,自动从package.json的dependencies种移除
如果某些包只在项目开发阶段会用到,在项目上线后不会用到,则建议把这些包记录到devDependencies几点中。与之对应的,如果在某些包在开发和项目上线之后都需要用到,则建议把这些包记录到dependenies节点中。
可以使用如下命令,将包记录到devDenpendencies节点中:

有时候下载包的速断比较慢?这是因为要国外的网站,所以有时候会比较慢。

可以切换npm的下包镜像源:

为了更方便的切换下包的镜像源,我们可以安装nrm这个小工具,利用nrm提供的终端命令,可以快速产看和切换下包的镜像源。


3.3.4 包的分类
项目包:那些被安装到项目的node_modules目录中的包都是项目包, 项目包又分两类:开发依赖包:被记录到devDenpendencies节点中的包,只在开发期间会用到核心依赖包:被记录到denpendencies节点中的包,在开发期间和项目上线之后都会用到

在执行npm install命令时, 如果提供了 -g参数,则会把包安装为全局包。
全局包会被安装到/usr/local/lib/node_modules目录下 npm i 包名 -g (全局安装指定的包);npm uninstall 包名 -g(卸载全局安装的包)
注意:1.只有工具性质的包,才有全局安装的必要性,因为他们提供了好用的终端命令。2、判断某个包是否需要全局才能使用,可以参考官方提供的使用说明即可
-
i5ting_toc:是一个可以把md文档转换成html页面的小工具,使用步骤如下:

-
规范的包结构:一个规范的包,它的组成结构,必须符合以下3点要求:
- 包必须以
单独的目录而存在 - 包的顶级目录下面必须包含
package.json这个包管理配置文件 - package.json中必须包含
name(包的名字)、version(包的版本)、main(包的入口)这三个属性。 - 注意:以上三点要求是一个规范的包结构必须遵守的格式,关于更多的约束,需要自行参考资料
- 包必须以
3.3.5 开发属于自己的包
-
初始化包的基本结构
- 新建date-tools文件夹,作为
包的根目录 - 在date-tools文件中,新建如下三个文件:
- package.json: 包的管理配置文件
- index.js : 包的入口文件
- README.md: 包的说明文档
- 配置package.json文件:

- 新建date-tools文件夹,作为
- 实现index.js中的格式化时间功能:

注意: 我们没有直接导入确定的.js文件,node会去该文件下面去查找是否有package.json文件,然后再看.json文件中是否有指定main属性(入口) 如果 没有则会报错 找不到文件
如果我们里面后面还有很多其他的功能方法, index.js文件中的代码会越来越多,会变得越来越难维护,为了解决这种情况,所以我们把功能相关的代码抽离出来作为一个独立的文件。

注意:...是展开对象中的每一个属性
- 编写包的说明文档:包根目录中
README.md文件,是包的使用说明文档。通过它,我们可以事先把包的使用说明,以markdown的格式写出来,方便用户参考。 内容包含: 安装方式、导入方式、功能使用介绍、开源协议
3.3.6 发布自己开发的包
访问https://www.npmjs.com/,然后注册一个账号。然后我们需要再终端执行命令npm login,依次输入用户名、密码、邮箱后,即可以登录成功。这里有一个注意点在运行npm login 命令之前,必须先把下包的服务器地址切换为npm 的官方服务器,否则会导致发布包失败
- 发布包:将终端切换到包的根目录之后,执行
npm publish命令,即可将包发布到npm上(注意:包名不能雷同) - 删除已发布包: 执行
npm unpublish 包名 --force命令,即可从npm删除已发布的包。- npm unpublish 命令只能删除
72小时以内发布的包 - npm unpublish 删除的包,在
24小时内不允许重复发布 - 发布包的时候要慎重,
尽量不要在王npm上发布没有意义的包
- npm unpublish 命令只能删除
3.4 模块的加载机制
模块在第一次加载后会被缓存,这也意味着多次调用require()不会导致模块的代码被执行多次。注意:不论是内置模块、用户自定义模块、还是第三方模块,他们都会优先从缓存中加载,从而提高模块的加载效率
-
内置模块是有Node.js官方提供的模块,
内置模块的加载优先级最高。例如,require(‘fs’)始终返回内置的fs模块,即使在node_modules目录下有名字相同的包也叫做fs -
使用require()加载自定义模块时,必须指定以
./或../开头的路径标识符,在加载自定义模块时,如果没有指定./或则../这样的路劲标识符,则node会把它当做内置模块或第三方模块进行加载。
同时,在使用require()导入自定义模块时,如果省略了文件的扩展名,则Node.js会按顺序分别尝试加载以下的文件:
- 按照
确切的文件名进行加载 - 补全
.js扩展名进行加载 - 补全
.json扩展名进行加载 - 补全
.node扩展名进行加载 - 加载失败,终端报错
- 第三方模块加载机制: 如果传递给require()的模块标识符不是一个内置模块,也没有以
./或../开头,则Node.js会从当前模块的父目录开始,尝试从/node_modules文件夹中加载第三方模块。如果没有找到对应的第三方模块,则移动到再上一层父目录中,进行加载,直到文件系统的根目录。

目录作为模块: 当把目录作为模块标识符,传递给require()进行加载的时候,又三种加载方式:- 在被加载的目录下查找一个叫做package.json的文件,并寻找main属性,作为require()加载的入口
- 如果目录里没有package.json文件,或则main入口不存在或无法解析,则Node.js将会视图加载目录下的
index.js文件。 - 如果以上两步都失败了,则Node.js会在终端打印错误信息,报告模块的缺失:Error Cannot find module ‘xxx’
4.Express
什么是Express?
官方给出的概念:Express是基于Node.js平台,快速、开放、极策的Web开发框架。通俗理解Express的作用和Node.js内置的http模块类似,是专门用来创建Web服务器的,其本质就是一个npm上的第三方包,提供了快速创建Web服务器的便捷方法Express中文官网 ,这里安装的是4.17.1版本。
Express能做什么?
对于前端程序员来说,最常见两种服务器,分别是:
Web网站服务器:专门对外提供Web网页资源的服务器API接口服务器:专门对外提供API接口的服务器
使用Express,我们可以方便,快速的创建Web网站的服务器或者API接口服务器
4.1 Express的基本使用
在项目所处的目录中, 运行如下的终端命令,即可将express安装到项目中使用:npm i express@4.17.1
- 使用express创建基本的web服务器:

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

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

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

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

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

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


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

注意:访问静态资源文件时,express.stack()函数会提供目录的添加顺序查找所需要的文件
- 挂载
静态资源前缀:如果希望在托管的静态资源访问路径之前,挂在路径前缀,则可以使用如下的方式:

- nodemon: 在编写调试Node.js项目的时候, 如果修改了项目的代码,则需要频繁手动
close掉,然后再重新启动,非常繁琐。现在,我们可以使用nodemon这个工具,它能够监听项目文件的变动,当代码修改后,nodemon会自动帮我们重启项目,极大方便了开发和调试
在终端执行命令npm install -g nodemon,即可将nodemon安装为全局可用的工具
当基于Node.js编写一个网站应用的时候,传统方式,是运行node app.js,来启动项目,这样做的坏处是,当代码被修改之后,需要手动重启项目。
现在,我们可以将node命令替换为nodemon,使用nodemon app.js来启动项目,这样做的好处:代码被修改之后,会被nodemon监听到,从而实现自动重启动项目的效果。

4.2 express路由
4.2.1 路由的介绍
在Express中, 路由指的是客户端的请求与服务器处理函数之间的映射关系。
Express中路由分3不分组成, 分别是请求的类型、请求的URL地址、处理函数格式如下:app.METHOD(PATH, HANDLER)

- 路由的匹配过程: 每当一个请求到达服务器之后,
需要先经过路由的匹配,只有匹配成功之后, 才会调用对应的处理函数。在匹配时,会按照路由的顺序进行匹配,如果请求类型和请求的URL同时匹配成功, 则Express 会将这次请求, 转交给对应的function函数进行处理。
注意:按照定义的先后顺序进行匹配,请求类型和请求的URL同时匹配成功,才会调用对应的处理函数
4.2.2 路由的使用
在Express 中使用路由最简单的方式, 就是把路由挂载到app上,实力代码如下

模块化路由:为了方便路由进行模块化的管理,Express 不建议将路由直接挂载到app上, 而是推荐将路由抽离为单独的模块。将路由抽离为单独模块步骤如下:
- 创建路由模块对应的js文件
- 调用
express.Route()函数创建路由对象 - 向路由对象上挂载具体的路由
- 使用
module.express向外共享路由对象 - 使用
app.user()函数注册路由模块

我们还可以为路由模块添加前缀, 类似于托管静态资源时, 为静态资源统一挂载访问访问前缀一样,路由模块添加前缀的方式也非常简单:

4.3 express中间件
4.3.1 中间件的概念
Express中间件的调用流程, 当一个请求到达Express的服务器之后,可以连续调用多个中间件,从而对这次请求进行预处理。

Express中间件的格式: Express的中间件,本质上就是一个function处理函数,Express中间件的格式如下:

注意: 中间件函数的形参列表中, 必须包含next参数,而路由处理函数中只包含req和res
上面多次提到next()函数,那么next()函数的作用是什么了?
next()函数是实现多个中间件连续调用的关键,它表示把流转关系转交给下一个中间件或路由。

4.3.2 Express 中间件的初体验
那么我们如何定义一个中间件函数,可以通过如下方式:

全局生效的中间件: 客户端发起的任何请求,到达服务器之后,都会触发的中间件,叫做全局生效的中间件。通过调用app.use(中间件函数),即可定义一个全局生效的中间件,示例代码如下:

定义中间件的简化形式:

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


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

除了全局中间件之外,我们还可以使用局部中间件,所谓局部生效的中间件, 就是不适用app.use()定义的中间件, 叫做局部生效中间件

注意:不使用app.use()注册的中间件都是局部中间件
跟全局中间件一样,我们一样也可以同时定义多个中间件。我们可以通过如下两种等价的方式,使用多个局部中间件:

- 中间件的5个使用注意事项:
- 一定要在
路由之前注册中间件 - 客户端发送过来的请求,
可以连续调用多个中间件进行处理 - 执行完中间件的业务代码之后,
不要忘记调用next()函数 - 为了
防止代码逻辑混乱,调用next()函数后不要在写额外的代码 - 连续调用多个中间件时,多个中间件之间,
共享req和res对象
- 一定要在
4.3.3 中间件的分类
为了方便大家理解和记忆中间件的使用, Express官方把常见的中间件用法,分成了5大类,分别是
应用级别的中间件路由级别的中间件错误级别的中间件Express内置的中间件第三方的中间件
通过app.use()或app.get()或app.post(),绑定到APP实例上的中间件, 叫做应用级别的中间件。代码示例如下:

绑定到express.Router()实例上的中间件,叫做路由级别的中间件, 它的想法和应用级别中间件没有任何的区别, 不过应用级别中间件是绑定到app实力上, 路由级别中间件绑定到router实例上:

错误级别的中间件的作用:专门用来捕获整个项目中发生的异常错误, 从而防止项目异常崩溃的问题。
格式:错误级别的中间件function处理函数中,必须有4个参数,形参顺序从前到后,分别是(err,req,res,next)。

注意:错误级别的中间件,必须注册在所有路由之后!
Express内置的中间件:自从Express 4.16.0版本开始Express 内置了3个常用的中间件,极大的提高了Express项目的开发效率和体验:express.static:快速托管静态资源的内置中间件,例如:HTML文件、图片、CSS样式等(无兼容性)express.json: 解析JSON格式的请求体数据(有兼容性,仅在4.16.0+版本中可用)express.urlencoded: 解析URL-encoded格式的请求数据(有兼容性,仅在4.16.0+版本中可用)

第三方的中间件指的是非Express官方内置的,而是由第三方开发出来的中间件,叫做第三方中间件。在项目开发中,大家可以按需下载并配置第三方中间件,从而提高项目的开发效率。例如在express@4.16.0之前的版本中经常使用body-parser这个第三方中间件,来解析请求数据,使用步骤如下:
- 运行
npm install body-parser安装中间件 - 使用
require导入中间件 - 调用
app.use()注册并使用中间件

注意:Express内置的express.urlencoded中间件,就是基于body-parser这个第三方中间件进一步封装出来的
4.3.4 自定义中间件
学习上述中间件的知识 ,我们可以尝试写一个自己的中间件。接下来我们手动模拟一个类似于express.unlencoded这样的中间件, 来解析POST提交服务器的表单数据。实现步骤如下:
- 定义中间件
- 监听req的data事件(在中间件中,需要监听req对象的data事件,来获取客户端发送到服务器的数据。如果数据量比较大,无法一次性发送完毕,则客户端
会把数据切割后,分批发送到服务器。所以data事件可能会触发多次,每一次触发data事件时,获取到数据只是完整数据的一部分,需要手动对接收到的数据进行拼接。) - 监听req的end事件(当请求数据
接受完毕之后,会自动触发req的end事件。因此,我们可以在req的end事件中,拿到并处理完整的请求数据。) - 使用querystring模块解析请求体数据(Node.js内置一个
querystring模块,专门用来处理查询字符串。通过这个模块提供的parse()函数,可以轻松把查询字符串,解析成对象的格式的数据) - 将解析出来的数据对象挂在为req.body(
上游的中间件和下游的中间件及路由之间,共享同一份req和res。因此我们可以将解析出来的数据,挂在为req的自定义属性,命名为req.body,供下游使用) - 将自定义中间件封装为模版

上述我们已经完成了我们自己中间件的功能实现, 但是我们发现我们的中间件的逻辑代码和主模块的代码在一起, 这样的代码结构不太好管理, 为了优化代码的结构,我们可以把自定义的中间件函数,封装为独立的模块,

4.4使用Express写接口
4.4.1 接口实现

上述html使用的jQuery是在线版本的相关地址-免费CND服务
编写接口之后,当我们进行接口测试的时候,发现浏览器报了如下错误:

4.4.2 CORS跨域资源共享
上述编写的接口,我们也发现了,存在一个很严重的问题: 不支持跨域请求。解决接口跨域问题的方案主要有两种:
CORS(主流的解决方案,推荐使用)JSONP(有缺陷的解决方案:支持支GET请求)
我们可以使用cors中间件解决跨域问题, cors是Express的一个第三方插件,通过安装和配置cors中间件,可以很方便地解决跨域问题。使用步骤如下:
- 运行
npm install cors中间件 - 使用
const cors = require('cors')导入中间件 - 在路由之前调用
app.use(cors())配置中间件

我们可能会有一个疑问? 到底什么是CORS?
cors(Cross-Origin Resource Sharing,跨域资源共享)由一系列HTTP响应头组成,这些HTTP响应头决定浏览器是否阻止前端JS代码跨域获取资源。
浏览器的同源安全策略默认会组织网页’跨域’获取资源,但如果接口服务器配置了CORS相关的HTTP响应头,就可以接触浏览器的跨域访问限制。

- CORS的注意事项:
- CORS主要是在
服务器进行配置,客户端浏览器无须做任何额外的配置,即可请求开启了CORS的接口。 - CORS在浏览器中
有兼容性,只支持XMLHttpRequestLevel2的浏览器,才能正常访问开启了CORS的服务端接口,例如IE10+、chrome4、FireFox3.5+
- CORS主要是在
CORS响应头部:Access-Control-Allow-Origin,响应头部中可以携带该字段,其语法如下:Access-Control-Allow-Origin: | *,其中origin参数指定了允许访问该资源的外域URL`。
例如,下面的字段值将只允许来自http://itcast.cn的请求:

如果指定了Access-Control-Allow-Origin的字段值为通配符 *,表示允许来自任何域的请求,示例代码如下:res.setheader('Access-Control-Allow-Origin', '*')
CORS响应头Access-Control-Allow-Headers默认情况下,CORS仅支持客户端像服务器发送如下的9个请求头:Accept、Accept-Language、Content-Lanaguage、DPR、Downlink、Viewport-Width、Width、Content-Type(值仅于text/plain、mulitpart/from-data、application/x-www-form-urlencoded三者之一)
如果客户端向服务端发送了额外的请求头信息, 则需要再服务器,通过Access-Control-Allow-Header对额外的请求头进行声明,否则这次请求会失败

CORS响应头部Access-Control-Allow-Methods,默认情况下,CORS仅支持客户端发起的GET、POST、HEAD请求,如果客户端希望通过PUT、DELETE等方式请求服务器资源,则需要再服务器端,通Access-Control-Allow-Methods来指明实际请求所允许使用的HTTP方法。

CORS请求的分类,客户端在请求CORS接口时,根据请求方式和请求头的不同,可以将CORS的请求分成两大类,分别是:简单请求和预检请求
简单请求:就是满足请求方式是GET、POST、HEAD三者之一, HTTP头部信息不超过上述的9种字段,无自定义表头。
预检请求: 只要符合其中一个要求,都需要进行预检请求。请求方式为GET、POST、HEAD之外的请求Method类型, 请求头中包含自定义头部字段,向服务器发送了application/json格式的数据
4.4.3 JSONP接口
浏览器端通过<script>标签的src属性,请求服务器上的数据,同时,服务器返回一个函数的调用,这种请求数据的方式叫做JSONP。其特点:
- JSONP不属于真正的Ajax请求,因为它没有使用
XMLHttpRequest这个对象。 - JSONP仅支持GET请求,不支持POST、PUT、DELETE等请求
创建JSONP请求的注意事项:如果项目中已经配置了CORS跨域资源共享,为了防止冲突,必须在配置CORS中间件之前申明JSONP的接口,否则JSONP接口会被处理成开启了CORS的接口。
使用JSONP的接口步骤:
获取客户端发来的回调函数名字- 得到要通过JSONP形式
发送给客户端的数据 - 根据前两部得到的数据,
拼接出一个函数调用的字符串 - 把上一步拼接得到的数据,响应给客户端
script标签进行解析执行

5. MySQL数据库
关于MySQL数据一些操作数据库的指令可以参考文章Java学习-MySQL数据库
这里主要介绍下载Express中怎么使用数据库。首先在项目中操作数据的步骤:
- 安装操作MySQL数据库的第三方模块(
mysql) - 通过mysql模块
链接到MySQL数据库 - 通过
mysql模块执行SQL语句

mysql模块是托管与npm上的第三方模块。它提供了Node.js项目中链接和操作MySQL数据库的能力。想要在项目中使用它,需要将mysql安装为项目的依赖包:npm install mysql
在使用mysql模块操作MySQL数据之前,必须先对mysql模块进行必要的配置,主要的配置步骤如下:

调用db.query函数,指定要执行SQL语句,通过回调函数那道执行的结果:

6 Web开发模式
6.1 身份认证
目前主流的Web开发者模式有两种,分别是:
- 基于
服务端渲染的传统Web开发模式 - 基于
前后端分离的新型Web开发者模式
服务端渲染的概念:服务器发送给客户端的HTML页面,是在服务器通过字符串的拼接,动态生成的。因此,客户端步需要使用Ajax这样的技术额外请求页面的数据。

服务端渲染的优缺点:
- 优点:
前端耗时少,因此服务端负责动态生成HTML内容,浏览器只需要直接渲染页面即可,尤其是移动端,更省电。有利于SEO,因为服务器响应是完成的HTML页面内容,所以爬虫更容易爬取获得信息,更有利于SEO
- 缺点:
占用服务器资源,即服务器完成HTML页面的拼接,如果请求较多,会对服务器造成一定的 访问压力不利于前后端分离,开发效率低,使用服务端渲染,则无法进行分工合作,尤其对于前端复杂度高的项目,不利于项目高效开发。
前后端分离的开发模式:前后端分离的开发模式,依赖于Ajax技术的广泛应用。简而言之,前后端分离的Web开发模式,就是后端只负责提供API接口,前端使用Ajax调用接口的开发模式
前后端分离的优缺点:
- 优点:
开发体验好,前端专注于UI页面的开发,后端专注于api的开发,切前端有更多的选择用户体验好,Ajax的技术广泛应用,极大的提高了用户的体验,可以轻松实现页面的局部刷新。减轻了服务器端的渲染压力。因此页面最终在每个用户的浏览器中生成的
- 缺点:
不利于SEO。因为完整的HTML页面需要再客户端动态拼接万完成,所以爬虫无法爬取页面的有效信息。(解决方案:利用Vue、React等前端架构的SSR(server side rende)技术能够很好的解决SEO问题!)
关于如何选择Web开发模式?
不谈业务场景而盲目选择使用何种开发模式都是耍流氓.
- 比如企业级网站,主要功能展示没有复杂的交互,并且需要良好的SEO,则这时我们就需要使用服务端渲染
- 而类似后台管理项目,交互性比较强,不需要考虑SEO,那么久可以使用前后端分离的开发模式。
另外,具体使用何种开发模式并不是绝对的,为了同时兼顾了首页的渲染速度和前后端分离的开发效率,一些网站采用了首屏服务端渲染+其它页面点后端分离的开发者模式。
什么是身份认证?
身份认证(Authentication)又称’身份验证‘、鉴权,是指,通过一定的手段,完成对用户身份的确认。 在Web开发中,涉及到用户身份认证,例如:各大网站的手机验证码登录、邮箱密码登录、二维码登录
不同开发模式下的身份认证, 对于服务端渲染和前后端分离这两种开发模式来说,分别有着不同的身份认证方案:
服务端渲染推荐使用Session认真机制前后端分离推荐使用JWT认证机制
6.2 session认证机制
- HTTP协议的
无状态性: 了解HTTP协议的无状态是进一步学习Session认证机制的必要前提。HTTP协议的无状态性,指的是客户端的每次HTTP请求都是独立的,连续多个请求之间没有直接关系,服务器不会主动保留每次HTTP请求的状态。

如何突破HTTP无状态的限制:对于超市来说,为了方便收银员在进行结算时给VIP用户打折,超市可以为每个VIP用户发放会员卡。

注意: 显示生活中会员卡身份认证机制,在Web开发中专业术语叫做Cookie。
Cookie:指存储在用户浏览器中的一段不超过4KB的字符串。它由一个名称(Name)、一个值(value)和其他几个用于Cookie有效期、安全性、使用范围的可选属性组成, 不同域名下的Cookie个字独立,每当客户端发起请求时,会自动把当前域名下所有未过期的Cookie一同发送到服务器。- Cookie的几大特性:自动发送、域名独立、过期时限、4KB限制。
Cookie在身份认证中的作用: 客户端在第一次请求服务器的时候,服务器通过
通过响应头的形式,向客户端发送一个身份认证的Cookie,客户端会自动将Cookie保存在浏览器中。
随后,当客户端浏览器每次请求服务器的时候, 浏览器会自动将自动将身份认证相关的Cookie,通过请求头的形式发送给服务器,服务器即可验明客户端的身份。

由于Cookie是存储在浏览器中的,而且浏览器也提供了读写Cookie的API,因此Cookie很容易被伪造, 不具备安全性,因此不建议服务器将重要的隐私数据,通过Cookie的形式发送给服务器。

注意: 千万不要使用Cookie存储重要且隐私的数据!比如用户的省份信息、密码等
为了防止客户伪造会员卡,收银员在拿到客户的会员卡之后,可以在收银机上进行刷卡认证,只有收银机确认存在的会员卡,才能被正常使用。

Session认证机制的工作原理:

在Express中使用Session认证, 首先我们需要安装express-session中间件,既可以在项目中使用

当express-session中间件配置成功后, 即可通过req-session来访问和使用session对象,从而存储用户的关键信息:




6.3 JWT认证机制
Session认证机制需要配合Cooke才能实现,由此Cookie默认不支持跨域访问,所以,当涉及到前端跨域请求后端接口的时候,需要做很多额外的配置,才能实现跨域Session认证。
注意:
- 当前段请求后端接口
不存在跨域问题的时候,推荐使用Session身份认证机制。 - 当前端需要跨域请求后端接口的时候,不推荐使用Session身份认证机制,推荐使用JWT认证机制。
JWT的工作原理:

- 用户的信息通过Token字符串的形式,保护在客户端浏览器中,服务器通过还原Token字符串的形式来认证用户的身份
JWT通常由三部分组成,分别是Header(头部)、Payload(有效荷载)、Signature(签名),三者之间使用英文的.分隔,格式如下:Header.Payload.Signature
Payload部分才是真正的用户信息,它是用户信息经过加密之后生成的字符串- Header和Signature是
安全性相关的部分,只是为了保证token的安全性。

如何使用JWT?
客户端收到服务器返回的JWT之后,通常会将它存储在localStorage或sessionStorage中。此后,客户端每次与服务器通信,都需要带上这个字符串,从而进行身份认证。推荐的做法就是把JWT放在HTTP请求头的Authorization字段中,格式如下:Authorization: Bearer <token>
如果想要在项目中使用JWT相关功能,需要安装两个相关的包;npm install jsonwebtoken express-jwt
在项目中为了保证JWT字符串的安全性,防止JWT字符串在网络传输过程中被别人破解,我们需要专门定义一个用于加密和解密的secrt秘钥:
- 当生成JWT字符串的时候,需要使用secret密钥对用户信息
进行加密,最终得到加密好的JWT字符串 - 当把JWT字符串解析还原成JSON对象的时候,需要使用secret密钥
进行解密
定义一个密钥,密钥本质是一个字符串,例如:const secretKey = "itedad NO1 @"

客户端每次在访问那些有权限的接口的时候,都需要主动在请求头中的Authorization字段,将token字符串发送到服务器进行身份验证。此时,服务器可以通过express-jwt这个中间件,自动将客户端发送过来的Token解析还原成JSON对象。

unless方法是设置那些接口,不需要使用访问权限。
注意:只要配置成功了express-jwt这个中间件,解析出来的信息可以通过auth来访问
当使用express-jwt解析Token字符串时,如果客户端发送过来的Token字符串过期或不合法,会产生一个解析失败的错误,影响项目的正常运行,我们可以通过Express的错误中间件,捕获整个错误并进行相关处理,示例代码如下:

相关文章:
web学习-Node.js入门学习
web学习-Node.js入门学习1.回顾与思考2. 初识Node.js2.1 Node.js的简介2.2Node.js的环境安装2.3. fs文件系统模块2.3.1 fs.readFile()2.3.2 fs.writeFile()2.3.3 练习-整理考试成绩2.3.4 fs模块-路径动态拼接的问题2.4 path路径模块2.5 http模块2.5.1 服务器相关的概念2.5.2 创…...
100 eeeee
全部 答对 答错 敏捷综合训练3 1.看板中的精益生产概念是如何减少工作在瓶颈时期的影响? A它不会减少瓶颈,因为瓶颈是任何生产系统不可避免的副产品 B通过运用 5Y 分析根本原因 C通过成为一个及时的进度系统 D通过每周完善活动 答错了 收藏 学员得…...
物盾安全汤晓冬:工业互联网企业如何应对高发的供应链安全风险?
编者按:物盾安全是一家专注于物联网安全的产品厂商,其核心产品“物安盾”在能源、制造、交通等多个领域落地,为这些行业企业提供覆盖物联网云、管、边、端的安全整体解决方案。“物安盾”集成了腾讯安全制品扫描(BSCA)…...
微纳制造技术——基础知识
1.什么是直接带隙半导体和间接带隙半导体 导带底和价带顶处以同一K值,称为直接带隙半导体 导带底和价带顶不处在同一K值,称为间接带隙半导体 2.扩散和漂移的公式 3.三五族半导体的性质 1.high mobility 2.wide bandgap 3.direct bandgap 4.三五族…...
Makefile的使用
Makefile的使用 自动化编译脚本,这个东西就是,进行简单的设置,然后实现原码编成为相应程序,简单化自己进行相关操作的过程。不需要一个个自己进行全部进行输入。而且还有许多的简化书写方法。 这个Makefile的本质为一种脚本语言…...
RealBasicVSR模型转成ONNX以及用c++推理
文章目录安装RealBasicVSR的环境1. 新建一个conda环境2. 安装pytorch(官网上选择合适的版本)版本太低会有问题3. 安装 mim 和 mmcv-full4. 安装 mmedit下载RealBasicVSR源码下载模型文件写一个模型转换的脚步测试生成的模型安装RealBasicVSR的环境 1. 新建一个conda环境 cond…...
C语言作用域(变量生存的空间)学习
C 作用域规则 任何一种编程中,作用域是程序中定义的变量所存在的区域,超过该区域变量就不能被访问。C 语言中有三个地方可以声明变量: 在函数或块内部的局部变量 在所有函数外部的全局变量 在形式参数的函数参数定义中 让我们来看看什么是局…...
Spark性能优化一 概念篇
(一)宽依赖和窄依赖 窄依赖(Narrow Dependency):指父RDD的每个分区只被子RDD的一个分区所使用,例如map、filter等 这些算子一个RDD,对它的父RDD只有简单的一对一的关系,也就是说,RDD的每个part…...
[数据结构]:09-二分查找(顺序表指针实现形式)(C语言实现)
目录 前言 已完成内容 二分查找实现 01-开发环境 02-文件布局 03-代码 01-主函数 02-头文件 03-PSeqListFunction.cpp 04-SearchFunction.cpp 结语 前言 此专栏包含408考研数据结构全部内容,除其中使用到C引用外,全为C语言代码。使用C引用主要…...
3.基于Label studio的训练数据标注指南:文本分类任务
文本分类任务Label Studio使用指南 1.基于Label studio的训练数据标注指南:信息抽取(实体关系抽取)、文本分类等 2.基于Label studio的训练数据标注指南:(智能文档)文档抽取任务、PDF、表格、图片抽取标注等…...
Python进阶-----面向对象3.0(面对对象三大特征之---封装)
目录 前言: 什么是封装 Python私有化封装 习题 前言: 上一期是讲解Python中类的私有属性和方法,其实很好理解,我给一个类中的部分属性进行加密拒绝访问(上一期链接Python进阶-----面向对象2.0&#…...
软考中级软件设计师备考建议
前言 首先我说一下个人对这个考试的一个感受看法,我觉得软件设计师考试并不难,主要是不要被内心的恐惧吓倒,考试中心态真的很重要! 一、中级软件设计师科目包括: (1)计算机与软件工程知识&am…...
【机器学习】决策树(理论)
决策树(理论) 目录一、何为决策树1、决策树的组成2、决策树的构建二、熵1、熵的作用2、熵的定义3、熵的计算4、条件熵的引入5、条件熵的计算三、划分选择1、信息增益( ID3 算法选用的评估标准)2、信息增益率( C4.5 算法…...
VSCode下载与安装使用教程【超详细讲解】
目录 一、VSCode介绍 二、官方下载地址 三、VSCode安装 1、点击我同意此协议,点击下一步; 2、点击浏览,选择安装路径,点击下一步; 3、添加到开始菜单,点击下一步; 4、根据需要勾选&#…...
2023年3月北京/上海/广州/深圳DAMA数据管理认证CDGA/CDGP
弘博创新是DAMA中国授权的数据治理人才培养基地,贴合市场需求定制教学体系,采用行业资深名师授课,理论与实践案例相结合,快速全面提升个人/企业数据治理专业知识与实践经验,通过考试还能获得数据专业领域证书。 DAMA认…...
进程和线程理论知识
1.进程和线程之间的联系。 进程是程序依次执行的过程,线程是比进程小的执行单位。 一个进程在其执行过程中可以创建多个线程。 多个线程共享进程的堆和方法区内存资源。 进程是OS进行资源分配的基本单位。 线程是OS进行调度的基本单位。 进程和线程是1࿱…...
华为OD机试用Python实现 -【广播服务器】
华为OD机试题 最近更新的博客华为 OD 机试 300 题大纲广播服务器题目输入输出示例一输入输出示例二输入输出Python代码代码编写思路最近更新的博客 华为od 2023 | 什么是华为od,od 薪资待遇,od机试题清单华为OD机试真题大全,用 Python 解华为机试题...
Solon2 的应用生命周期
Solon 框架的应用生命周期包括:一个初始化函数时机点 六个事件时机点 两个插件生命时机点 两个容器生命时机点(v2.2.0 版本的状态): 提醒: 启动过程完成后,项目才能正常运行(启动过程中&…...
学习笔记-架构的演进之服务容错策略设计模式-3月day02
文章目录前言断路器模式舱壁隔离模式重试模式总结附前言 容错设计模式,指的是“要实现某种容错策略,我们该如何去做”。微服务中常见的设计模式包括断路器模式、舱壁隔离模式和超时重试模式等,另外还有流量控制模式等。 断路器模式 断路器…...
【WEB前端进阶之路】 HTML 全路线学习知识点梳理(上)
前言 HTML 是一切Web开发的基础,本文专门为小白整理,针对前端零基础的朋友们,手把手教你学习HTML,让你轻松迈入WEB开发的行列。 首先,感谢 橙子_ 在HTML学习以及本文编写过程中对我的帮助。 文章目录前言一.HTML简介1.…...
SpringBoot-17-MyBatis动态SQL标签之常用标签
文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...
国防科技大学计算机基础课程笔记02信息编码
1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制,因此这个了16进制的数据既可以翻译成为这个机器码,也可以翻译成为这个国标码,所以这个时候很容易会出现这个歧义的情况; 因此,我们的这个国…...
conda相比python好处
Conda 作为 Python 的环境和包管理工具,相比原生 Python 生态(如 pip 虚拟环境)有许多独特优势,尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处: 一、一站式环境管理:…...
React 第五十五节 Router 中 useAsyncError的使用详解
前言 useAsyncError 是 React Router v6.4 引入的一个钩子,用于处理异步操作(如数据加载)中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误:捕获在 loader 或 action 中发生的异步错误替…...
React hook之useRef
React useRef 详解 useRef 是 React 提供的一个 Hook,用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途,下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...
Zustand 状态管理库:极简而强大的解决方案
Zustand 是一个轻量级、快速和可扩展的状态管理库,特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...
oracle与MySQL数据库之间数据同步的技术要点
Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异,它们的数据同步要求既要保持数据的准确性和一致性,又要处理好性能问题。以下是一些主要的技术要点: 数据结构差异 数据类型差异ÿ…...
CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云
目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...
Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...
FFmpeg:Windows系统小白安装及其使用
一、安装 1.访问官网 Download FFmpeg 2.点击版本目录 3.选择版本点击安装 注意这里选择的是【release buids】,注意左上角标题 例如我安装在目录 F:\FFmpeg 4.解压 5.添加环境变量 把你解压后的bin目录(即exe所在文件夹)加入系统变量…...
