7.Express模块基础用法

Express是做web服务器的,是一个第三方的包,官网 Express - 基于 Node.js 平台的 web 应用开发框架 - Express 中文文档 | Express 中文网

Express的部分用法与http模块类似

在我看来Express是一个轻量级的框架,如果用于做一些较复杂的业务会非常麻烦

目录

1  安装

2  创建基本的服务器

3  监听get请求

4  监听post请求

5  req对象

5.1  接收查询字符串 req.query

5.2  获取动态参数 req.params

6  静态文件

6.1  注册单一目录

6.2  注册多个目录

6.3  给目录路由

7  路由模块化

8  中间件的基本使用方法

8.1  全局生效的中间件

8.2  中间件的应用

8.3  定义多个全局中间件

8.4  局部生效的中间件

8.5  使用多个局部中间件

9  中间件的分类

9.1  应用级别中间件

9.2  路由级别中间件

9.3  错误级别中间件

9.3.1  加入中间件的情况

9.3.2  不加入中间件的情况

9.4  Express内置的中间件

9.4.1  express.json

9.4.2  express.urlencoded

9.5  第三方中间件

10  自定义中间件

10.1  中间件

10.2  服务

10.3  使用结果

11  编写接口

11.1  编写get接口

11.2  编写post接口

12  CORS跨域

12.1  跨域问题

12.2  使用cors中间件解决跨域问题

12.3  CORS的响应头

12.3.1  Access-Control-Allow-Origin

12.3.2  Access-Control-Allow-Header

12.3.3  Access-Control-Allow-Methods

12.4  CORS请求的分类

13  JSONP接口

13.1  客户端

13.2  服务端

13.3  请求结果

14  session

14.1  安装

14.2  配置

14.3  存储数据

14.4  获取数据

14.5  清空session

15  JWT


1  安装

我当前安装的是目前(2023.1.4)最新的 4.18.2

2  创建基本的服务器

目前这个服务里什么都没有,启动之后找不到指定路由的效果是这样的

3  监听get请求

我们简单做个例子

4  监听post请求

  • app.post()与app.get()可以挂同一个路由

5  req对象

5.1  接收查询字符串 req.query

给参数的情况

不给参数的情况

post发的参数用req.query接不到

只能接收查询字符串

5.2  获取动态参数 req.params

动态参数就在路由中提前写好的参数,让查询字符串不用再写键了

post也能用

动态参数可以像上面一样直接加,也可以加在斜杠后面

动态参数可以在任意位置加任意个

6  静态文件

6.1  注册单一目录

首先创建一个放静态文件的文件夹,我将其命名为static,然后向static中放一张图像

然后再代码中注册这个静态文件文件夹

  • 参数是文件夹名称,你也可以不叫static

之后在网页中就能访问到这张图片了

6.2  注册多个目录

你可以注册多个静态文件目录,我现在再加入一个目录file

之后我注册一下

访问一下发现可以访问file中的图片

现在我在file与static中有一个相同名称的图片Node.js.png,我先注册的static,所以会显示static中的Node.js.png

6.3  给目录路由

我们给各自的目录路由就可以精确的找到想要找的文件

  • 路由可给可不给,路由名称随便起

7  路由模块化

我们一般不把所有的路由都挂在主路由下,比如我们给网站先分 主页,用户管理,其他 这么几个部分,然后在各自的部分加入想要的路由。

我做个例子

user.js,这个是放用户模块的路由的

server.js 这个是启动的入口

启动server.js发现可以访问模块的路由

向这样就比较麻烦,每一个路由我还得多写一遍user

我们可以在server.js文件中统一为添加模块的路由,我们下面简单改一下

user.js

server.js

重启服务后可以正常访问

8  中间件的基本使用方法

中间件的概念可以看一下这个 25.中间件_Suyuoa的博客-CSDN博客_中间件执行顺序 大概理解一下就是,请求之前我应该处理点儿什么,响应之后我应该怎么处理响应,报错了怎么办,这些

express的中间件形参包含next参数

8.1  全局生效的中间件

中间件函数一定要在函数最后加上next(),不然会阻塞。使用app.use()可以在全局应用中间件

  • next()后不要再写代码,因为next()后的代码不会被执行,虽然不会报错但看起来会难看些

运行后我们访问一下,发现先执行的中间件,再执行的test_get

8.2  中间件的应用

比如我们现在想在每一次请求的时候打印出来请求的时间,那我们就这样定义一下中间件

你也可以在中间件内定义一些属性,到后面请求的时候再使用上这些属性

8.3  定义多个全局中间件

在app.use()中依次写上要执行的中间件就好。连续调用多个中间件时,多个中间件之间共享req与res对象

8.4  局部生效的中间件

我们下面只给 /test_get 绑定中间件mw1

8.5  使用多个局部中间件

给多个参数或给一个数组作为参数都可以使用多个中间件

9  中间件的分类

根据常见中间件的用法,Express官方将中间件分为5大类

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

9.1  应用级别中间件

绑定在app这个对象上的中间件,我们上面用的都是应用级别中间件

9.2  路由级别中间件

绑定在router这个对象上的中间件(上面提到的路由模块化的对象),可以用router.use()方法进行注册,其余用法也都与绑在app上相同

9.3  错误级别中间件

用来捕获项目中发现的异常,从而防止项目异常崩溃。错误级别中间件有四个形参 err,req,res,next。错误中间件要写在路由的后面

9.3.1  加入中间件的情况

  • 一般来讲错误级别中间件最后不写next()

如果出现了错误,路由错误下面的内容就不再被执行了

9.3.2  不加入中间件的情况

如果不加中间件,响应结果是这样的

9.4  Express内置的中间件

比如 express.static 这个我们在上面介绍静态文件时使用过,除此之外还有下面几个常用的

  • express.json 解析JSON格式的请求体数据
  • express.urlencoded 解析 URL-encoded 格式的请求体数据

express.static,express.json,express.urlencoded可以同时使用

9.4.1  express.json

我们先简单用一下express.json

如果你不使用express.json,请求会成功,但拿不到数据

9.4.2  express.urlencoded

如果不用 express.urlencoded 可以请求成功,但拿不到数据

9.5  第三方中间件

第三方中间件就是别人写的中间件,比如body-parser可以解析数据

  • 每一个第三方中间件的使用方式不尽相同,我只是在这里做个例子

我们首先运行 npm install body-parser 安装body-parser

10  自定义中间件

我们简单了解一下第三方中间件的创建过程,我们模拟一个类似express.urlencoded这样的中间件,来解析POST提交到服务器的表单数据

首先先创建两个js文件,一个放服务,一个放中间件

10.1  中间件

先写中间件

通过req的data事件获取客户端发送到服务器的数据

如果单次发送数据量较大,无法一次性发送完毕。那么客户端会把数据进行切割,分批发送到服务器。所以data事件可能会触发多次,每一次触发data事件时,获取到数据只是完整数据的一部分,需要手动对接到的数据进行拼接

我们打印出来接收到的req_str发现是一个查询字符串

Node.js内置querystring模块,可以把查询字符串解析为对象,在请求结束的时候会触发end事件,这个时候我们将查询字符串解析,然后赋值给req.body

最后导出供我们的服务使用

10.2  服务

引入后注册,注册后使用

10.3  使用结果

发个请求测试一下

11  编写接口

接口和视图实质上没有区别,就是返回的东西不一样,我们简单看一下

11.1  编写get接口

11.2  编写post接口

12  CORS跨域

CORS (Cross-Origin Resource Sharing) 跨域资源共享,由一系列HTTP响应头组成,这些HTTP响应头决定浏览器是否阻止前端JS代码跨域获取资源

CORS在服务端进行配置,客户端无需配置

CORS有兼容性问题,只有支持XMLHttpRequest Level2的浏览器才支持CORS

12.1  跨域问题

上面我们写的接口是不支持跨域请求的,在浏览器上直接访问http地址不算跨域

但用file协议的Ajax不行,不了解跨域可以看一下这个 8.跨域请求_Suyuoa的博客-CSDN博客

我们之前在上面那个链接中使用JSONP可以解决GET的跨域请求,但POST跨域请求搞不了。

现在我们使用CORS,CORS可以解决GET与POST的跨域请求

12.2  使用cors中间件解决跨域问题

cors是Express的第三方中间件,首先先安装cors

之后注册,然后使用

这样再进行GET与POST请求就可以了

12.3  CORS的响应头

12.3.1  Access-Control-Allow-Origin

Access-Control-Allow-Origin 允许的源,这个后面可以是一个域名(IP),可以使用res.setHeader()对响应头进行设置,比如

这样就允许 http://127.0.0.1 或 http://itcast.cn 发出请求,想要设置多个源可以用英文逗号隔开

也可以是一个星号,星号就是所有域名都可以访问

  • res.setHeader('Access-Control-Allow-Origin','*')

12.3.2  Access-Control-Allow-Header

Access-Control-Allow-Header 允许的请求头,默认情况下CORS仅支持下面9个请求头

  1. Accept
  2. Accept-Language
  3. Content-Language
  4. DPR
  5. Downlink
  6. Save-Data
  7. Viewport-Width
  8. Width
  9. Content-Type

上面是9个请求头的键,它们的值仅限于下面三个

  1. text/plain
  2. multipart/form-data
  3. application/x-www-form-urlencoded

如果客户端向服务端发送了额外的请求头信息,则需要在服务端进行声明,比如我现在允许Content-Type123与X-Custom-Header这两个请求头

  • res.setHeader('Access-Control-Allow-Headers','Content-Type123,X-Custom-Header')

12.3.3  Access-Control-Allow-Methods

Access-Control-Allow-Methods 允许的方法,默认情况下CORS仅支持客户端发起GET,POST,HEAD请求

比如我现在想加上DELETE请求,那就这样写

  • res.setHeader('Access-Control-Allow-Methods','POST,GET,DELETE,HEAD')

想允许所有的HTTP请求方法就用星号

  • res.setHeader('Access-Control-Allow-Methods','*')

12.4  CORS请求的分类

根据请求方式和请求头的不同可以分为 简单请求 与 预检请求

在浏览器与服务器正式通信之前,浏览器会先发送OPTION请求进行预检,目的是获知服务器是否允许该实际请求

此次OPTION请求称为OPTION预检请求

当服务器成功响应预检请求后,才会发送真正的请求,也就是说预检请求实质上是请求两次

简单请求条件

  • 请求方式属于 GET,POST,HEAD 三者之一
  • HTTP头部信息键属于
    1. 无自定义头部字段(自定义的不算)
    2. Accept
    3. Accept-Language
    4. Content-Language
    5. DPR
    6. Downlink
    7. Save-Data
    8. Viewport-Width
    9. Width
    10. Content-Type
  • HTTP头部信息的值属于
    1. application/x-www-form-urlencoded
    2. multipart/form-data
    3. text/plain

预检请求条件,符合下面任何一个条件的请求,都是预检请求

  • 请求方式为 GET,POST,HEAD 之外的请求方式
  • 请求头中包含自定义头部字段
  • 向服务器发送了 application/json格式的数据

我们用DELETE请求看一下预检请求

客户端

服务端

点击一次DELETE请求发现出现了两次请求

  • 有时200的请求会显示在前

这个204的请求就是OPTIONS请求

下面的是真正的DELETE请求

13  JSONP接口

在这里 8.跨域请求_Suyuoa的博客-CSDN博客 我们用flask做了一个JSONP接口,现在我们用express做一个

如果要同时使用CORS与JSONP,那么我们必须在配置CORS中间件之前声明JSONP的接口

13.1  客户端

13.2  服务端

在实际情况中使用JSONP应该是不需要后端进行处理的,后端的写法是相对固定的,只是接收 回调函数以及若干参数,然后返回就行

13.3  请求结果

14  session

14.1  安装

在express中使用session可以通过 express-session 中间件使用

使用之前我们首先安装 express-session 中间件

14.2  配置

安装后对express-session进行配置

其中secret是用来加密用的,值为任意字符串,resave与saveUninitialized就这么给就行,如果想深入了解的话可以看一下文档 express-session - npm

14.3  存储数据

用session的时候一般不会用get发送数据,所以我用的post

这样写session是存储在变量中的,服务关了session就没有了

14.4  获取数据

14.5  清空session

清空session不会讲所有客户端的session都清空,而是只会清空发出该请求客户端的所有session

此时再读取session就会出问题

15  JWT

在express中使用JWT可以组合使用 jsonwebtoken与express-jwt

jsonwebtoken是生成JWT字符串的,express-jwt是将JWT字符还原为JSON对象的

下面我写个例子

const express = require('express')
const jsonwebtoken = require('jsonwebtoken')
const { expressjwt: jwt } = require("express-jwt")

const secretKey = 'ifwoenigoiehriogjserohmtr'

const app = express()
app.use(express.urlencoded({extended:false}))
app.use(
    jwt({
      secret: secretKey,
      algorithms: ["HS256"],
    }).unless({ path: ["/login"] })
)

app.post('/login',(req,res) => {
    userinfo = req.body
    console.log('userinfo:',userinfo)
    res.send({
        message:'登录成功',
        token:jsonwebtoken.sign({username:userinfo.username},secretKey,{expiresIn:'300s'})
    })
})

app.get('/hello',(req,res) => {
    console.log('req.auth:',req.auth)
    res.send('你好' + req.auth.username)
})

app.use((err,req,res,next) => {
    if (err.name === 'UnauthorizedError') {
        return res.send({status:401,message:'无效的token'})
    }

    res.send({status:500,message:err.message})
}) 

app.listen(80,() => {
    console.log('服务在80端口启动')
})
  • 新版的 express-jwt 与老版的在使用方式上有差异,我当前的版本是 8.2.1 是2023年1月4日的最新版本

下面我们说一下这个例子

express-jwt的引入方式与其他的包有些不同

secret密钥是做加密与解密用的,他实质上是自定义的字符串

使用中间件jwt,secret是刚刚定义的密钥,algorithms是算法,不了解的这样写就行,后面的unless表示哪个路由不需要token就可以访问

接收到数据使用jsonwebtoken的sign将信息加密,token的安全性不如session,所以最好不要把密码这种敏感信息放在token中

expiresIn是有效期,expiresIn是有效期

接收的时候使用req.auth进行接收

为了避免看到大量的报错信息这里给一个中间件

运行一下后先直接访问/hello ,发现处理错误的中间件是生效的

然后请求 /login,发现请求成功,此时得到了一个token

之后再请求 /hello ,把刚刚的token复制上

iat与exp是控制token有效期的

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Suyuoa

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值