NestJs
是一个非常优秀的 Node
的后端框架,它的底层使用的是 express
等 Node HTTP
框架,它提供了 express
没有的 MVC
、IoC
、AOP
等架构特性,使得代码更容易维护、扩展。
NestJs
受到 Angular
的启发,在服务端提供一个开箱即用的应用框架,让开发人员和团队能够创造出高可测试、可扩展、松耦合、易维护的应用。代码组织更规范,只有代码规范了,开发出的应用才可以易测试、可扩展、松耦合、易维护。
AOP
AOP
的中文全称为 Aspect Oriented Programming
,翻译成人话就是 面向切面编程
,那么什么是切面呢?
其实你可以理解为一个汉堡,它的本质就是一个面包,在这里我们把它理解为我们的应用程序,我们要在扩展这个应用程序的时候,需要在里面添加更多的代码,而这个过程就是向这个面包加馅的过程,如下图所示,不知道你饿了没:
AOP
主要有以下的特点:
- 扩展功能方便,不影响业务之间的逻辑;
- 逻辑集中处理;
- 更有利于代码复用;
那我们再回到 NestJs
中的 AOP
,在 Nest
中实现 AOP
的方式有很多,具体如下图所示:
我们在前端发送一个请求,它首先会经过 Controller
(控制器)、Services
(服务)、Repository
(数据接入)的逻辑,主要流程如下图所示:
如果你想在这个调用链路里加入一些通用逻辑,你可以在这个执行流程中加入不同的逻辑,这个就是 AOP
给我们带来的好处,例如你要添加一些异常处理,日志记录。
Nest生命周期
在 vue
和 react
中都有它自己的生命周期,在 NestJs
中也有,它的整个生命周期如下图所示:
每个生命周期阶段都有不同的逻辑,例如 Interceptors
(拦截器),它分为前置拦截器和后置拦截器,前置拦截器又有这么三个逻辑,它们分别是全局拦截器
、控制器拦截器
、路由拦截器
三个。
一个完整的生命周期主要是有以下步骤:
- 收到请求;
- 全局中间件;
- 模块中间件;
- 全局守卫;
- 控制器守卫;
- 路由守卫;
- 全局拦截器(控制器之前);
- 控制器层拦截器(控制器之前);
- 路由拦截器(控制器之前);
- 全局管道;
- 控制器管道;
- 路由管道;
- 路由参数管道;
- 控制器;
- 路由拦截器;
- 控制器拦截器;
- 全局拦截器;
- 路由过滤器;
- 控制器过滤器;
- 全局过滤器;
- 服务器响应;
AOP应用案例之MIddleware (中间件)
中间件是一个在路由处理器之前被调用的函数,中间件函数可以访问请求和响应对象,以及应用程序的 请求-响应
周期中的 next()
中间件函数,下一个中间件函数通常由名为next的变量表示。
通俗的讲,中间件就是匹配路由之前或者匹配路由完成做的一系列的操作。
NestJs
的中间件实际上等价于 express
中间件,中间件函数主要执行的以下任务:
- 执行任何代码;
- 对请求和响应对象进行更改;
- 结束
请求-响应
周期; - 调用堆栈中的下一个中间件函数;
- 如果当前的中间件函数没有结束
请求-响应
周期,它必须调用next()
将控制传递给下一个中间件函数,否则请求将被挂起;
在 NestJs
中,它既可以是一个函数,也可以是一个被 @Injectable()
装饰的类,如果使用的是类,则必须 implement
NestMiddleware
接口。
创建中间件
要想创建中间件,NestJs
官方脚手架给我们提供了创建中间件的命令,如下所示:
nest g middleware middleware/wao
最后面那个参数是路径和文件名称,最终生成的代码(代码修改过)和文件如下所示:
引入
创建好中间件之后要在全局模块下引入,也就是 app.module.ts
文件下引入:
import { WaoMiddleware } from './middleware/wao/wao.middleware';
并且将 app.module.ts
文件下的 AppModule
类进行修改,具体代码如下所示:
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer.apply(WaoMiddleware).forRoutes('niubi'); // 匹配牛逼路由
}
}
我们在 app.controller.ts
文件下编写以下代码,如下所示:
import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';
@Controller('niubi')
export class AppController {
constructor(private readonly appService: AppService) {}
@Get()
getHello(): string {
return '你小子你终于来了,等你好久了';
}
}
此时当我们在浏览器输入完整地址时,并且请求地址为 niubi
路由时,会经过中间件,具体如下图所示:
当前这个配置访问其他路由时不会经过该中间件。
如果没有调用 next()
方法,并且没有调用 res.send()
方法,该请求会被挂起,这个浏览器页面会不停的转圈圈,如下图所示:
但你调用 res.send()
表示会对该请求进行了拦截,例如该用户没有权限访问该路由:
import { Injectable, NestMiddleware } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';
@Injectable()
export class WaoMiddleware implements NestMiddleware {
use(req: Request, res: Response, next: NextFunction) {
res.send('<h1>你小子我忍你好久了,不给你访问</h1>');
}
}
到这里文章也就结束了,更多详细的例子可以查看官方文档,写得挺好的。
总结
NestJs
底层是基于 express
封装的框架,主要是应用了 IoC
和 AOP
等架构思想,如果你了解 Typescript
,并且如果你有 express
基础的话,随便看两眼文档就可以上手了,真的很好玩,强烈推荐。
NestJs
我从去年年初就想学了,到现在才有机会学,这么好用也难怪我会这么喜欢!!!
本文正在参加「金石计划」
原文链接:https://juejin.cn/post/7222189908428783653 作者:Moment