06_node_express框架学习(更新中.......)
Express
学习目标

1、初识Express
1.1、什么是Express

本质就是一个第三方模块,提供创建Web服务器的方法,操作简单,功能比http内置模块强大,这也是我们学习它的目的

1.2、进一步理解

1.3、Express能做什么

总结:可以做Web网站服务器开发,也可以做API接口服务器的开发
1.4、安装Express
// 我这边的express已经更新了,终端中输入以下指令即可安装
npm i express@4.17.2

1.5、创建基本的Web服务器

// 1、导入express模块
const express = require('express')
// 2、使用express()函数创建一个Web服务器实例
const server = express();
// 3、配置服务器启动的配置
server.listen(8080,()=>{
console.log("This is WebServer To http://localhost:8080");
})
测试

1.6、处理Get和Post请求,响应请求

// 1、导入express模块
const express = require('express')
// 2、使用express()函数创建一个Web服务器实例
const server = express();
// 3、配置服务器启动的配置
server.listen(8080,()=>{
console.log("This is WebServer To http://localhost:8080");
})
/**
* 参数1:请求路径:这里的请求路径指的是,localhost:8080/ ==> / 后面的部分
* 参数2:匿名函数,包含两个参数,req请求对象,res响应对象
*/
// 通过app.get()方法,可以监听客户端的GET请求,具体的语法格式如下:
server.get("/user",(req,res)=>{
// send函数,将处理好的内容,发送给客户端,可以是json格式,也可以是字符串形式
res.send({username:'张三',age:18,phone:"13678230705"})
})
// 通过app.post()方法,可以监听客户端的POST请求,具体的语法格式如下:
server.post("/user",(req,res)=>{
res.send("This is post request............")
})
运行代码,启动服务器
get请求

post请求

1.7、获取URL地址当中所携带的参数
- 在req当中提供了一个query对象,默认该对象是空对象
- 如果在客户端当中使用 ?name='zhangsan';这种问号形式传递参数,req会将这些参数自动解析到query属性当中
- 因此可以通过req.query对象访问到
代码展示

// 1、导入express模块
const express = require('express')
// 2、使用express()函数创建一个Web服务器实例
const server = express();
// 3、配置服务器启动的配置
server.listen(8080,()=>{
console.log("This is WebServer To http://localhost:8080");
})
// 4、在post请求当中使用req的query对象获取用户输入的属性
server.post("/user/login",(req,res)=>{
var userInformation = req.query;
console.log(userInformation);
// 登陆成功,假设
res.send("login success!")
})
测试效果

控制台打印结果

1.8、获取URL当中的动态参数
req.params对象


// 4、动态参数类似于Restfull请求格式,通过 :xxx参数的形式来传递动态参数
server.post("/params/:username&:password",(req,res)=>{
// 我这里试试解构写法
var {params} = req
// 打印接收到的动态参数
console.log(params);
// 将接收到的参数以json数据格式进行返还
res.send(params)
})
测试结果

控制台输出内容

2、托管静态资源
2.1、express.static()

将原先写的时钟案例文件粘贴到我当前的项目目录当中

代码展示
// 1、导入express模块
const express = require('express')
// 2、使用express()函数创建一个Web服务器实例
const server = express();
// 3、express.static() ==>挂载静态资源
// 在服务器对象server当中,调用use函数,在use函数内部传递一个参数Function
server.use(express.static("./clock")) // 在static函数当中,输入需要被挂载的静态文件or文件夹
// 4、配置服务器启动的配置
server.listen(8080,()=>{
console.log("This is WebServer To http://localhost:8080");
})
启动服务器开始测试

这里应该是有个底层逻辑的,如果该文件下存在index.html页面,应该会重定向到该页面

如果我将index.html页面修改为waves.html呢,我改个名字看看


确实是这样的
2.2、托管多个静态资源

这个就不演示了
2.3、挂载路径前缀
注意,在挂载路径前缀的时候,一定要写上反斜杠(/)


// 1、导入express模块
const express = require('express')
// 2、使用express()函数创建一个Web服务器实例
const server = express();
// 3、express.static() ==>挂载静态资源
server.use('/clock',express.static("./clock")) // 挂载路径前缀
// 4、配置服务器启动的配置
server.listen(8080,()=>{
console.log("This is WebServer To http://localhost:8080");
})
测试


3、安装nodemon
3.1、为什么要用nodemon?
这个可以理解为SpringBoot的热重载机制

3.2、安装

npm i nodemon -g

在node的全局文件当中可以看到安装成功了

3.3、使用nodemon

测试



4、路由
4.1、路由概述
广义上来讲,路由就是映射关系
举个例子

一个按键会对应一个具体的服务,这个映射关系就叫做路由
4.2、express的路由
路由的三部分:请求类型,请求地址,处理函数

4.3、路由的匹配过程
- 每一个请求到达服务器的时候,需要先经过路由的匹配,(这里的匹配是指:请求方式、请求地址),二者完全匹配之后,才会调用相对的function处理函数
- 在匹配的时候,会按照路由的顺序,自顶而下进行匹配,如果双满足(方式、资源路径),则调用对应的处理函数,反之则往下继续匹配
- 概念图
4.4、路由的用法
就是之前写的代码,只是解释了什么是路由

缺陷,路由一般是不会挂载在服务器身上的,因为业务会越来越多,这样写会造成代码的冗余性;不方便管理
4.5、模块化路由
核心,将路由抽离成单独的模块(自定义模块),在该模块当中创建路由对象,配置请求类型,资源路径,和处理函数,最终将该路由对象向外暴露共享

-
创建路由模块和对应的js文件
-
代码展示
-
这里简单结合了一下之前所学知识,设计一个简单的登录请求验证
-

-
// 1、导入express模块 var express = require('express') // 2、创建路由对象 var router = express.Router(); // 3、挂载路由 == 配置路由;请求地址这里配置个简单点的动态数据获取 router.post('/user/login/:username&:password',(req,res)=>{ // 获取用户输入的数据,params是一个对象,用user来接受,params是用来接受动态参数的属性 var user = req.params; // 做一个简单的判断 if(user.username=='zhangsan'&&user.password=="123123"){ // 登录成功 res.send("login success~") }else{ // 登录失败 res.send("Error!") } }) // 4、向外导出router对象,供外部成员使用 module.exports = router
-
4.6、路由模块的注册

// 1、导入path模块,导入路由模块,导入express模块
const path = require('path')
const userRouter = require(path.join(__dirname,'./routers/userLogin'))
const express = require('express')
// 2、创建Web服务器实例对象
var server = express();
// 3、注册中间件(server.use()函数的作用,将路由模块注册)
server.use(userRouter)
// 启动服务器
server.listen(8080,()=>{
console.log("http://localhost:8080");
})
测试


4.7、为路由模块添加前缀

5、中间件
5.1、概念


5.2、中间件的作用
作用:对请求进行预处理的操作;一个请求可以 “连续调用多个中间件”

5.3、中间件的格式
我们来看一张图

next参数一定要放在最后面
5.4.next()函数的作用

5.5、中间件的使用
1、定义一个简单的中间件并将其注册为全局中间件

代码展示
// 1、导入express模块
const express = require('express')
// 2、创建Web服务器实例
const server = express();
// 3、创建中间件对象
// 本质上来讲,中间件就是一个function函数,只是与路由不同的是
// 中间件的第三个参数用来传递当前中间件的处理结果
const mw = (req,res,next)=>{
console.log('这是一个中间件');
// next函数的目的是将当前中间件的处理结果传递给下一个中间件
// 供其调用
next();
}
// 4、定义一个全局生效的中间件
// 通过use函数,对中间件进行全局的注册,当有请求进入的时候,优先调用这个头部的中间件
server.use(mw)
// 5、启动服务器
server.listen(8080,()=>{
console.log("http://localhost:8080");
})
启动服务器测试

2、定义全局中间件的简化形式
本质上中间件就是一个函数,那么直接将这个函数作为参数传递进去也可以完成全局中间件的注册

3、中间件的作用
- 多个中间件之间,共享同一个req和res对象
- 基于上述特性,我们可以在上游中间件当中,统一为res和req对象添加自定义的属性和方法,为下游的中间件提供使用和便捷

- 接下来我们做一个需求,全局中间件提供一个属性nowTime,这个属性可以记录中间件到下一个中间件所花费的时间
- 下游中间件,这里做一个嵌套,如果我的猜测没问题,第一个中间件我们做账号注册的验证,第二个中间件我们做账号注册时候的查重
- 我的想法是,我们这次不采用路由的方式进行创建,当然在挂载的时候还是在服务器对象身上通过use挂载的
- 所以在挂载的时候肯定遵循一个原理 == > 自上而下进行挂载,那么当两个相同的请求地址和请求参数参数的请求,如果合理存在,那么肯定也遵循这个原则,而且如果其中一个是中间件,那么猜想没错的话,这个中间件结束之后会通过next函数对下一个请求进行调用

注意,我的4.1和4.2是请求地址,请求方式完全相同的,不同的是4.1为中间件对象,4.2为普通的路由对象
这里4.2的注释写错了,不是请求参数不为空,而是对其进行查重


代码演示
// 1、导入express模块
const express = require('express')
// 2、创建Web服务器实例
const server = express();
// 3、定义全局中间件对象
server.use((req,res,next)=>{
console.log("这是全局中间件");
// 这里提供一个查询当前时间的属性
var nowTime = Date.now();
// 将这个属性挂载到req对象当中
req.nowTime = nowTime;
// 调用下一个中间件
next();
})
// 4.1、注册用户
server.post('/user/login/:username&:password',(req,res,next)=>{
// 获取请求参数
var {params} = req;
// 请求参数的内容不允许为空
if(params.username=='""'||params.password=='""'){
// 结束本次响应
res.send("register Error!")
}else{
next();
}
})
// 4.2、用户查重
server.post('/user/login/:username&:password',(req,res)=>{
// 获取请求参数
var {params} = req;
// 查重验证,用户名不能为张三
if(params.username=="zhangsan"){
// 用户已注册,结束本次响应
res.send("The user has registered!")
}else{
res.send("register success!" + "nowTime = "+req.nowTime)
}
})
// 5、启动服务器
server.listen(8080,()=>{
console.log("http://localhost:8080");
})
测试结果
- 测试内容为空(假定)
- 内容不为空,但是查重存在
- 注册成功
说明我的猜想是可以的,但是实际开发当中应该用不到,因为4.2的操作完全可以通过封装一个函数来实现,我这么做只是为了提供一种可行的方式,需求是无限的,说不定以后真就用到了呢,23333~
5.6、定义多个全局中间件
一个思想,自顶而下,谁先写谁现被调用







浙公网安备 33010602011771号