前言

用过expresskoa的同学,对中间件这个概念应该非常熟悉了,中间件可以拿到RequestResponse对象和next函数.

一般来讲中间件有以下作用:

  • 执行任何代码
  • 对请求与响应拦截并改造
  • 结束request-response周期
  • 通过next()调用下一个中间件
  • 如果当前中间件没有结束当前request-response周期,必须调用next()函数,否则请求会处于挂起状态,阻塞整个应用

中间件一般有两种:类中间件函数中间件

类中间件

创建类中间件

使用@Injectable()装饰器,并且需要实现NestMiddleware接口(use方法)

// Logger.middleware.ts
import { Injectable, NestMiddleware } from "@nestjs/common";
import { Request, Response } from "express"; @Injectable()
export class LoggerMiddleware implements NestMiddleware {
use(req: Request, res: Response, next: () => void) {
console.log('logger middleware', `url: ${req.url}`);
next();
}
}

使用类中间件

类中间创建完之后,需要在模块中进行挂载,但@Module装饰器并没有中间件的相关配置,我们需要让module类实现NestModule接口,实现里面configure方法来进行挂载

// user.module.ts
import { Module, NestModule } from '@nestjs/common';
import { UserService } from './user.service';
import { UserController } from './user.controller';
import { LoggerMiddleware } from '../middleware/Logger.middleware';
@Module({
controllers: [UserController],
providers: [UserService]
})
export class UserModule implements NestModule {
configure(consumer) {
consumer
.apply(LoggerMiddleware)
.forRoutes(UserController);
}
}
  • apply方法表示挂载的是哪个中间件
  • forRoutes方法表示对哪个请求路径起作用,这种方式与app.use(path, middleware)作用是一样,只针对部分路径起作用
  • 当给forRoutes方法传递的是一个controller控制器时,那么该中间件则对整个控制器下的路径生效

比如这里传递的是UserController控制器,那么针对该控制器下的路径都会生效

  • forRootes方法还能做更详细的配置,比如可以针对特定的请求方法、请求路径可以使用正则匹配(需要注意的是使用fastify驱动不能使用)
export class UserModule implements NestModule {
configure(consumer) {
consumer
.apply(LoggerMiddleware)
.forRoutes({ path: 'user', method: RequestMethod.GET});
}
}
  • apply可以同时挂载多个中间件
export class UserModule implements NestModule {
configure(consumer) {
consumer
.apply(LoggerMiddleware, aaaMiddleware, ...)
.forRoutes({ path: 'user', method: RequestMethod.GET});
}
}
  • forRoutes可以使用单个string路径,多个string路径,RouteInfo对象,单个Controller,多个Controller
export class AppModule implements NestModule {
configure(consumer) {
consumer
.apply(LoggerMiddleware, NjMiddleware, ...)
.forRoutes(UserController, NjController, ...);
}
}
  • exclude可以用来排除不使用中间件的路径
export class UserModule implements NestModule {
configure(consumer) {
consumer
.apply(LoggerMiddleware)
.exclude({ path: '/user/a', method: RequestMethod.GET})
.forRoutes(UserController);
}
}

需要注意的是forRoutes需要最后调用

函数中间件

这种方式较为简单,使用起来与类中间件一致

创建函数中间件

export function LoggerMiddleware(req: Request, res: Response, next: () => void) {
console.log('logger middleware', `url: ${req.url}`);
next();
}

使用函数中间件

export class UserModule implements NestModule {
configure(consumer) {
consumer
.apply(LoggerMiddleware)
.exclude({ path: '/user/a', method: RequestMethod.GET})
.forRoutes(UserController);
}
}

全局中间件

可以直接在入口文件main.ts中使用app.use来挂载中间件,这样挂载的中间件将全局生效

app.use(LoggerMiddleware) // 日志中间件

中间件其实可以用来实现很多功能,比如:日志系统、cors跨域处理、图片防盗等...

对图片防盗感兴趣的可以看我这篇文章:你不知道的 HTTP Referer

【NestJS系列】核心概念:Middleware中间件的更多相关文章

  1. Spark系列-核心概念

    Spark系列-初体验(数据准备篇) Spark系列-核心概念 一. Spark核心概念 Master,也就是架构图中的Cluster Manager.Spark的Master和Workder节点分别 ...

  2. fusionjs 学习二 核心概念

    核心概念 middleware 类似express 的中间件模型(实际上是构建在koa中间件模型上的),但是和koa 的中间件有差异 fusionjs 的中间件同时可以运行在浏览器页面加载的时候 se ...

  3. ZooKeeper 系列(一)—— ZooKeeper核心概念详解

    一.Zookeeper简介 二.Zookeeper设计目标 三.核心概念         3.1 集群角色         3.2 会话         3.3 数据节点         3.4 节点 ...

  4. ZooKeeper系列(一)—— ZooKeeper 简介及核心概念

    一.Zookeeper简介 Zookeeper 是一个开源的分布式协调服务,目前由 Apache 进行维护.Zookeeper 可以用于实现分布式系统中常见的发布/订阅.负载均衡.命令服务.分布式协调 ...

  5. Storm 系列(二)—— Storm 核心概念详解

    一.Storm核心概念 1.1 Topologies(拓扑) 一个完整的 Storm 流处理程序被称为 Storm topology(拓扑).它是一个是由 Spouts 和 Bolts 通过 Stre ...

  6. 框架源码系列十:Spring AOP(AOP的核心概念回顾、Spring中AOP的用法、Spring AOP 源码学习)

    一.AOP的核心概念回顾 https://docs.spring.io/spring/docs/5.1.3.RELEASE/spring-framework-reference/core.html#a ...

  7. Redux 核心概念

    http://gaearon.github.io/redux/index.html ,文档在 http://rackt.github.io/redux/index.html .本文不是官方文档的翻译. ...

  8. Laravel 核心概念

    工欲善其事,必先利其器.在开发Xblog的过程中,稍微领悟了一点Laravel的思想.确实如此,这篇文章读完你可能并不能从无到有写出一个博客,但知道Laravel的核心概念之后,当你再次写起Larav ...

  9. Laravel 的核心概念

    工欲善其事,必先利其器.在开发Xblog的过程中,稍微领悟了一点Laravel的思想.确实如此,这篇文章读完你可能并不能从无到有写出一个博客,但知道Laravel的核心概念之后,当你再次写起Larav ...

  10. 后端技术杂谈11:十分钟理解Kubernetes核心概念

    本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 本文转自 https://github.com/h2pl/Java-Tutorial 喜欢的 ...

随机推荐

  1. springboot~国际化Locale正确的姿势

    Java中的Locale.getDefault()获取的是操作系统的默认区域设置,如果需要获取客户端浏览器的区域设置,可以从HTTP头中获取"Accept-Language"的值来 ...

  2. RabbitMQ 工作模式介绍

    RabbitMQ 工作模式介绍 1.Hello World RabbitMQ 是一个消息代理:它接受并转发消息.您可以将其视为邮局:当您将要邮寄的邮件放入邮箱时,您可以确定信使最终会将邮件交付给您的收 ...

  3. Apache Hudi 1.x 版本重磅功能展望与讨论

    Apache Hudi 社区正在对Apache Hudi 1.x版本功能进行讨论,欢迎感兴趣同学参与讨论,PR链接:https://github.com/apache/hudi/pull/8679/f ...

  4. 记一次618军演压测TPS上不去排查及优化

    本文内容主要介绍,618医药供应链质量组一次军演压测发现的问题及排查优化过程.旨在给大家借鉴参考. 背景 本次军演压测背景是,2B业务线及多个业务侧共同和B中台联合军演. 现象 当压测商品卡片接口的时 ...

  5. Linux目录结构及常用命令

    目录 Linux目录结构... 1 Linux目录结构... 1 1. Linux常用命令... 4 1.1 Linux命令初体验... 4 1.2 文件目录操作命令... 8 1.3 拷贝移动命令. ...

  6. CSS3学习记录之loading动画

    loading动画就是在加载一些网页内容的时候呈现出来的小动画,记录一下学到的几种loading动画: 效果:http://39.105.101.122/myhtml/CSS/Loading/load ...

  7. SpringBoot RabbitMQ 实战解决项目中实践

    1 基础预览 1.1 环境准备 Springboot 1.5.6.RELEAS Springcloud Dalston.SR2 1.2 交换机类型 交换机是用来发送消息的AMQP实体.交换机拿到一个消 ...

  8. 基于uni-app+vue3渲染markdown格式|uniapp软键盘顶起问题解决方案

    前些时候有给大家分享一篇uni-app+vite4+uview-plus搭建跨端项目.今天主要分享下在uniapp中渲染markdown语法及uniapp中软键盘弹起,页面tabbar或顶部自定义na ...

  9. 【SpringBoot】整合Redis

    1.前言 最近公司在做项目,用到了redis,,发现自己一点都不会,然后就乘闲暇时间,自己学习一些redis相关的知识,在这里分享给像我一样的初学者. 2.我的项目结构: 2.1 pom.xml &l ...

  10. 【技术积累】Java中的常用类【一】

    Math类 Math类是Java中的一个数学工具类,提供了一系列常用的数学方法.下面是Math类的常用方法及其案例: abs() 返回一个数的绝对值. int num = -10; int absNu ...